b3df61dd894aa3cc1d9ba014bcaa81289e7efb7a
[libsamsung-ipc.git] / samsung-ipc / devices / piranha / piranha.c
1 /*
2  * This file is part of libsamsung-ipc.
3  *
4  * Copyright (C) 2013-2014 Paul Kocialkowski <contact@paulk.fr>
5  *
6  * libsamsung-ipc is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * libsamsung-ipc is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25
26 #include <samsung-ipc.h>
27 #include <ipc.h>
28
29 #include "xmm626.h"
30 #include "xmm626_mipi.h"
31 #include "xmm626_sec_modem.h"
32 #include "piranha.h"
33
34 int piranha_boot(struct ipc_client *client)
35 {
36     void *modem_image_data = NULL;
37     int modem_image_fd = -1;
38     int modem_boot_fd = -1;
39     unsigned char *p;
40     int rc;
41
42     if (client == NULL)
43         return -1;
44
45     ipc_client_log(client, "Starting piranha modem boot");
46
47     modem_image_fd = open(PIRANHA_MODEM_IMAGE_DEVICE, O_RDONLY);
48     if (modem_image_fd < 0) {
49         ipc_client_log(client, "Opening modem image device failed");
50         goto error;
51     }
52     ipc_client_log(client, "Opened modem image device");
53
54     modem_image_data = mmap(0, PIRANHA_MODEM_IMAGE_SIZE, PROT_READ, MAP_SHARED, modem_image_fd, 0);
55     if (modem_image_data == NULL || modem_image_data == (void *) 0xffffffff) {
56             ipc_client_log(client, "Mapping modem image data to memory failed");
57             goto error;
58     }
59     ipc_client_log(client, "Mapped modem image data to memory");
60
61     modem_boot_fd = open(XMM626_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
62     if (modem_boot_fd < 0) {
63         ipc_client_log(client, "Opening modem boot device failed");
64         goto error;
65     }
66     ipc_client_log(client, "Opened modem boot device");
67
68     rc = xmm626_sec_modem_power(modem_boot_fd, 0);
69     if (rc < 0) {
70         ipc_client_log(client, "Turning the modem off failed");
71         goto error;
72     }
73     ipc_client_log(client, "Turned the modem off");
74
75     rc = xmm626_sec_modem_power(modem_boot_fd, 1);
76     if (rc < 0) {
77         ipc_client_log(client, "Turning the modem on failed");
78         goto error;
79     }
80     ipc_client_log(client, "Turned the modem on");
81
82     p = (unsigned char *) modem_image_data + PIRANHA_PSI_OFFSET;
83
84     rc = xmm626_mipi_psi_send(client, modem_boot_fd, (void *) p, PIRANHA_PSI_SIZE);
85     if (rc < 0) {
86         ipc_client_log(client, "Sending XMM626 MIPI PSI failed");
87         goto error;
88     }
89     ipc_client_log(client, "Sent XMM626 MIPI PSI");
90
91     close(modem_boot_fd);
92
93     modem_boot_fd = open(XMM626_SEC_MODEM_BOOT1_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
94     if (modem_boot_fd < 0) {
95         ipc_client_log(client, "Opening modem boot device failed");
96         goto error;
97     }
98     ipc_client_log(client, "Opened modem boot device");
99
100     p = (unsigned char *) modem_image_data + PIRANHA_EBL_OFFSET;
101
102     rc = xmm626_mipi_ebl_send(client, modem_boot_fd, (void *) p, PIRANHA_EBL_SIZE);
103     if (rc < 0) {
104         ipc_client_log(client, "Sending XMM626 MIPI EBL failed");
105         goto error;
106     }
107     ipc_client_log(client, "Sent XMM626 MIPI EBL");
108
109     rc = xmm626_mipi_port_config_send(client, modem_boot_fd);
110     if (rc < 0) {
111         ipc_client_log(client, "Sending XMM626 MIPI port config failed");
112         goto error;
113     }
114     ipc_client_log(client, "Sent XMM626 MIPI port config");
115
116     p = (unsigned char *) modem_image_data + PIRANHA_SEC_START_OFFSET;
117
118     rc = xmm626_mipi_sec_start_send(client, modem_boot_fd, (void *) p, PIRANHA_SEC_START_SIZE);
119     if (rc < 0) {
120         ipc_client_log(client, "Sending XMM626 MIPI SEC start failed");
121         goto error;
122     }
123     ipc_client_log(client, "Sent XMM626 MIPI SEC start");
124
125     p = (unsigned char *) modem_image_data + PIRANHA_FIRMWARE_OFFSET;
126
127     rc = xmm626_mipi_firmware_send(client, modem_boot_fd, (void *) p, PIRANHA_FIRMWARE_SIZE);
128     if (rc < 0) {
129         ipc_client_log(client, "Sending XMM626 MIPI firmware failed");
130         goto error;
131     }
132     ipc_client_log(client, "Sent XMM626 MIPI firmware");
133
134     rc = xmm626_mipi_nv_data_send(client, modem_boot_fd);
135     if (rc < 0) {
136         ipc_client_log(client, "Sending XMM626 MIPI nv_data failed");
137         goto error;
138     }
139     ipc_client_log(client, "Sent XMM626 MIPI nv_data");
140
141     rc = xmm626_mipi_sec_end_send(client, modem_boot_fd);
142     if (rc < 0) {
143         ipc_client_log(client, "Sending XMM626 MIPI SEC end failed");
144         goto error;
145     }
146     ipc_client_log(client, "Sent XMM626 MIPI SEC end");
147
148     rc = xmm626_mipi_hw_reset_send(client, modem_boot_fd);
149     if (rc < 0) {
150         ipc_client_log(client, "Sending XMM626 MIPI HW reset failed");
151         goto error;
152     }
153     ipc_client_log(client, "Sent XMM626 MIPI HW reset");
154
155     rc = 0;
156     goto complete;
157
158 error:
159     rc = -1;
160
161 complete:
162     if (modem_image_data != NULL)
163         munmap(modem_image_data, PIRANHA_MODEM_IMAGE_SIZE);
164
165     if (modem_image_fd >= 0)
166         close(modem_image_fd);
167
168     if (modem_boot_fd >= 0)
169         close(modem_boot_fd);
170
171     return rc;
172 }
173
174 int piranha_open(void *data, int type)
175 {
176     struct piranha_transport_data *transport_data;
177
178     if (data == NULL)
179         return -1;
180
181     transport_data = (struct piranha_transport_data *) data;
182
183     transport_data->fd = xmm626_sec_modem_open(type);
184     if (transport_data->fd < 0)
185         return -1;
186
187     return 0;
188 }
189
190 int piranha_close(void *data)
191 {
192     struct piranha_transport_data *transport_data;
193
194     if (data == NULL)
195         return -1;
196
197     transport_data = (struct piranha_transport_data *) data;
198
199     xmm626_sec_modem_close(transport_data->fd);
200     transport_data->fd = -1;
201
202     return 0;
203 }
204
205 int piranha_read(void *data, void *buffer, size_t length)
206 {
207     struct piranha_transport_data *transport_data;
208     int rc;
209
210     if (data == NULL)
211         return -1;
212
213     transport_data = (struct piranha_transport_data *) data;
214
215     rc = xmm626_sec_modem_read(transport_data->fd, buffer, length);
216
217     return rc;
218 }
219
220 int piranha_write(void *data, const void *buffer, size_t length)
221 {
222     struct piranha_transport_data *transport_data;
223     int rc;
224
225     if (data == NULL)
226         return -1;
227
228     transport_data = (struct piranha_transport_data *) data;
229
230     rc = xmm626_sec_modem_write(transport_data->fd, buffer, length);
231
232     return rc;
233 }
234
235 int piranha_poll(void *data, struct timeval *timeout)
236 {
237     struct piranha_transport_data *transport_data;
238     int rc;
239
240     if (data == NULL)
241         return -1;
242
243     transport_data = (struct piranha_transport_data *) data;
244
245     rc = xmm626_sec_modem_poll(transport_data->fd, timeout);
246
247     return rc;
248 }
249
250 int piranha_power_on(void *data)
251 {
252     return 0;
253 }
254
255 int piranha_power_off(void *data)
256 {
257     int fd;
258     int rc;
259
260     fd = open(XMM626_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
261     if (fd < 0)
262         return -1;
263
264     rc = xmm626_sec_modem_power(fd, 0);
265
266     close(fd);
267
268     if (rc < 0)
269         return -1;
270
271     return 0;
272 }
273
274 int piranha_gprs_activate(void *data, unsigned int cid)
275 {
276     return 0;
277 }
278
279 int piranha_gprs_deactivate(void *data, unsigned int cid)
280 {
281     return 0;
282 }
283
284 int piranha_data_create(void **transport_data, void **power_data,
285     void **gprs_data)
286 {
287     if (transport_data == NULL)
288         return -1;
289
290     *transport_data = calloc(1, sizeof(struct piranha_transport_data));
291
292     return 0;
293 }
294
295 int piranha_data_destroy(void *transport_data, void *power_data,
296     void *gprs_data)
297 {
298     if (transport_data == NULL)
299         return -1;
300
301     free(transport_data);
302
303     return 0;
304 }
305
306 struct ipc_client_ops piranha_fmt_ops = {
307     .boot = piranha_boot,
308     .send = xmm626_sec_modem_fmt_send,
309     .recv = xmm626_sec_modem_fmt_recv,
310 };
311
312 struct ipc_client_ops piranha_rfs_ops = {
313     .boot = NULL,
314     .send = xmm626_sec_modem_rfs_send,
315     .recv = xmm626_sec_modem_rfs_recv,
316 };
317
318 struct ipc_client_handlers piranha_handlers = {
319     .read = piranha_read,
320     .write = piranha_write,
321     .open = piranha_open,
322     .close = piranha_close,
323     .poll = piranha_poll,
324     .transport_data = NULL,
325     .power_on = piranha_power_on,
326     .power_off = piranha_power_off,
327     .power_data = NULL,
328     .gprs_activate = piranha_gprs_activate,
329     .gprs_deactivate = piranha_gprs_deactivate,
330     .gprs_data = NULL,
331     .data_create = piranha_data_create,
332     .data_destroy = piranha_data_destroy,
333 };
334
335 struct ipc_client_gprs_specs piranha_gprs_specs = {
336     .gprs_get_iface = xmm626_sec_modem_gprs_get_iface,
337     .gprs_get_capabilities = xmm626_sec_modem_gprs_get_capabilities,
338 };
339
340 struct ipc_client_nv_data_specs piranha_nv_data_specs = {
341     .nv_data_path = XMM626_NV_DATA_PATH,
342     .nv_data_md5_path = XMM626_NV_DATA_MD5_PATH,
343     .nv_data_backup_path = XMM626_NV_DATA_BACKUP_PATH,
344     .nv_data_backup_md5_path = XMM626_NV_DATA_BACKUP_MD5_PATH,
345     .nv_data_secret = XMM626_NV_DATA_SECRET,
346     .nv_data_size = XMM626_NV_DATA_SIZE,
347     .nv_data_chunk_size = XMM626_NV_DATA_CHUNK_SIZE,
348 };
349
350 // vim:ts=4:sw=4:expandtab