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