Rename ipc_header to ipc_fmt_header, add ipc_rfs_header and utility functions
[libsamsung-ipc.git] / samsung-ipc / device / xmm6260 / xmm6260_sec_modem.c
1 /*
2  * This file is part of libsamsung-ipc.
3  *
4  * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
5  * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
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
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include <sys/select.h>
29
30 #include <samsung-ipc.h>
31 #include <ipc.h>
32 #include <util.h>
33
34 #include "modem.h"
35 #include "modem_prj.h"
36 #include "modem_link_device_hsic.h"
37
38 #include "xmm6260.h"
39 #include "xmm6260_sec_modem.h"
40
41 int xmm6260_sec_modem_power(int device_fd, int power)
42 {
43     int rc;
44
45     if (device_fd < 0)
46         return -1;
47
48     rc = ioctl(device_fd, power ? IOCTL_MODEM_ON : IOCTL_MODEM_OFF, 0);
49     if (rc < 0)
50         return -1;
51
52     return 0;
53 }
54
55 int xmm6260_sec_modem_boot_power(int device_fd, int power)
56 {
57     int rc;
58
59     if (device_fd < 0)
60         return -1;
61
62     rc = ioctl(device_fd, power ? IOCTL_MODEM_BOOT_ON : IOCTL_MODEM_BOOT_OFF, 0);
63     if (rc < 0)
64         return -1;
65
66     return 0;
67 }
68
69 int xmm6260_sec_modem_status_online_wait(int device_fd)
70 {
71     int status;
72     int i;
73
74     if (device_fd < 0)
75         return -1;
76
77     i = 0;
78     for (i = 0; i < 100; i++) {
79         status = ioctl(device_fd, IOCTL_MODEM_STATUS, 0);
80         if (status == STATE_ONLINE)
81             return 0;
82
83         usleep(50000);
84     }
85
86     return -1;
87 }
88
89 int xmm6260_sec_modem_hci_power(int power)
90 {
91     int ehci_rc, ohci_rc;
92
93     ehci_rc = sysfs_value_write(XMM6260_SEC_MODEM_EHCI_POWER_SYSFS, !!power);
94     if (ehci_rc >= 0)
95         usleep(50000);
96
97     ohci_rc = sysfs_value_write(XMM6260_SEC_MODEM_OHCI_POWER_SYSFS, !!power);
98     if (ohci_rc >= 0)
99         usleep(50000);
100
101     if (ehci_rc < 0 && ohci_rc < 0)
102         return -1;
103
104     return 0;
105 }
106
107 int xmm6260_sec_modem_link_control_enable(int device_fd, int enable)
108 {
109     int rc;
110
111     if (device_fd < 0)
112         return -1;
113
114     rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ENABLE, &enable);
115     if (rc < 0)
116         return -1;
117
118     return 0;
119 }
120
121 int xmm6260_sec_modem_link_control_active(int device_fd, int active)
122 {
123     int rc;
124
125     if (device_fd < 0)
126         return -1;
127
128     rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ACTIVE, &active);
129     if (rc < 0)
130         return -1;
131
132     return 0;
133 }
134
135 int xmm6260_sec_modem_link_connected_wait(int device_fd)
136 {
137     int status;
138     int i;
139
140     if (device_fd < 0)
141         return -1;
142
143     i = 0;
144     for (i = 0; i < 100; i++) {
145         status = ioctl(device_fd, IOCTL_LINK_CONNECTED, 0);
146         if (status)
147             return 0;
148
149         usleep(50000);
150     }
151
152     return -1;
153 }
154
155 int xmm6260_sec_modem_link_get_hostwake_wait(int device_fd)
156 {
157     int status;
158     int i;
159
160     if (device_fd < 0)
161         return -1;
162
163     i = 0;
164     for (i = 0; i < 10; i++) {
165         status = ioctl(device_fd, IOCTL_LINK_GET_HOSTWAKE, 0);
166         if (status)
167             return 0;
168
169         usleep(50000);
170     }
171
172     return -1;
173 }
174
175 int xmm6260_sec_modem_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
176 {
177     struct ipc_fmt_header header;
178     void *buffer;
179     unsigned char *p;
180     int count;
181     int rc;
182
183     if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
184         return -1;
185
186     ipc_fmt_header_fill(&header, request);
187
188     buffer = malloc(header.length);
189
190     memcpy(buffer, &header, sizeof(struct ipc_fmt_header));
191     if (request->data != NULL && request->length > 0)
192         memcpy((void *) ((unsigned char *) buffer + sizeof(struct ipc_fmt_header)), request->data, request->length);
193
194     ipc_client_log_send(client, request, __func__);
195
196     p = (unsigned char *) buffer;
197
198     count = 0;
199     while (count < header.length) {
200         rc = client->handlers->write(client->handlers->transport_data, p, header.length - count);
201         if (rc <= 0) {
202             ipc_client_log(client, "Writing FMT data to the modem failed");
203             goto error;
204         }
205
206         count += rc;
207         p += rc;
208     }
209
210     rc = 0;
211     goto complete;
212
213 error:
214     rc = -1;
215
216 complete:
217     if (buffer != NULL)
218         free(buffer);
219
220     return rc;
221 }
222
223 int xmm6260_sec_modem_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
224 {
225     struct ipc_fmt_header *header;
226     void *buffer = NULL;
227     unsigned char *p;
228     int length;
229     int count;
230     int rc;
231
232     if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
233         return -1;
234
235     length = XMM6260_DATA_SIZE;
236     buffer = malloc(length);
237
238     rc = client->handlers->read(client->handlers->transport_data, buffer, length);
239     if (rc < (int) sizeof(struct ipc_fmt_header)) {
240         ipc_client_log(client, "Reading FMT header from the modem failed");
241         goto error;
242     }
243
244     header = (struct ipc_fmt_header *) buffer;
245
246     ipc_fmt_message_fill(header, response);
247
248     if (header->length > sizeof(struct ipc_fmt_header)) {
249         response->length = header->length - sizeof(struct ipc_fmt_header);
250         response->data = malloc(response->length);
251
252         p = (unsigned char *) response->data;
253
254         count = rc - sizeof(struct ipc_fmt_header);
255         if (count > 0) {
256             memcpy(p, (void *) ((unsigned char *) buffer + sizeof(struct ipc_fmt_header)), count);
257             p += count;
258         }
259
260         while (count < (int) response->length) {
261             rc = client->handlers->read(client->handlers->transport_data, p, response->length - count);
262             if (rc <= 0) {
263                 ipc_client_log(client, "Reading FMT data from the modem failed");
264                 goto error;
265             }
266
267             count += rc;
268             p += rc;
269         }
270     }
271
272     ipc_client_log_recv(client, response, __func__);
273
274     rc = 0;
275     goto complete;
276
277 error:
278     rc = -1;
279
280 complete:
281     if (buffer != NULL)
282         free(buffer);
283
284     return rc;
285 }
286
287 int xmm6260_sec_modem_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
288 {
289     struct ipc_rfs_header header;
290     void *buffer;
291     unsigned char *p;
292     int count;
293     int rc;
294
295
296     if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
297         return -1;
298
299     ipc_rfs_header_fill(&header, request);
300
301     buffer = malloc(header.length);
302
303     memcpy(buffer, &header, sizeof(struct ipc_rfs_header));
304     if (request->data != NULL && request->length > 0)
305         memcpy((void *) ((unsigned char *) buffer + sizeof(struct ipc_rfs_header)), request->data, request->length);
306
307     ipc_client_log_send(client, request, __func__);
308
309     p = (unsigned char *) buffer;
310
311     count = 0;
312     while (count < (int) header.length) {
313         rc = client->handlers->write(client->handlers->transport_data, p, header.length - count);
314         if (rc <= 0) {
315             ipc_client_log(client, "Writing RFS data to the modem failed");
316             goto error;
317         }
318
319         count += rc;
320         p += rc;
321     }
322
323     rc = 0;
324     goto complete;
325
326 error:
327     rc = -1;
328
329 complete:
330     if (buffer != NULL)
331         free(buffer);
332
333     return rc;
334 }
335
336 int xmm6260_sec_modem_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
337 {
338     struct ipc_rfs_header *header;
339     void *buffer = NULL;
340     unsigned char *p;
341     int length;
342     int count;
343     int rc;
344
345     if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
346         return -1;
347
348     length = XMM6260_DATA_SIZE;
349     buffer = malloc(length);
350
351     rc = client->handlers->read(client->handlers->transport_data, buffer, length);
352     if (rc < (int) sizeof(struct ipc_rfs_header)) {
353         ipc_client_log(client, "Reading RFS header from the modem failed");
354         goto error;
355     }
356
357     header = (struct ipc_rfs_header *) buffer;
358
359     ipc_rfs_message_fill(header, response);
360
361     if (header->length > sizeof(struct ipc_rfs_header)) {
362         response->length = header->length - sizeof(struct ipc_rfs_header);
363         response->data = malloc(response->length);
364
365         p = (unsigned char *) response->data;
366
367         count = rc - sizeof(struct ipc_rfs_header);
368         if (count > 0) {
369             memcpy(p, (void *) ((unsigned char *) buffer + sizeof(struct ipc_rfs_header)), count);
370             p += count;
371         }
372
373         while (count < (int) response->length) {
374             rc = client->handlers->read(client->handlers->transport_data, p, response->length - count);
375             if (rc <= 0) {
376                 ipc_client_log(client, "Reading RFS data from the modem failed");
377                 goto error;
378             }
379
380             count += rc;
381             p += rc;
382         }
383     }
384
385     ipc_client_log_recv(client, response, __func__);
386
387     rc = 0;
388     goto complete;
389
390 error:
391     rc = -1;
392
393 complete:
394     if (buffer != NULL)
395         free(buffer);
396
397     return rc;
398 }
399
400 int xmm6260_sec_modem_ipc_open(int type)
401 {
402     int fd;
403
404     switch (type) {
405         case IPC_CLIENT_TYPE_FMT:
406             fd = open(XMM6260_SEC_MODEM_IPC0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
407             break;
408         case IPC_CLIENT_TYPE_RFS:
409             fd = open(XMM6260_SEC_MODEM_RFS0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
410             break;
411         default:
412             return -1;
413     }
414
415     return fd;
416 }
417
418 int xmm6260_sec_modem_ipc_close(int fd)
419 {
420     if (fd < 0)
421         return -1;
422
423     close(fd);
424
425     return 0;
426 }
427
428 int xmm6260_sec_modem_ipc_read(int fd, void *buffer, unsigned int length)
429 {
430     int rc;
431
432     if (fd < 0 || buffer == NULL || length <= 0)
433         return -1;
434
435     rc = read(fd, buffer, length);
436     return rc;
437 }
438
439 int xmm6260_sec_modem_ipc_write(int fd, void *buffer, unsigned int length)
440 {
441     int rc;
442
443     if (fd < 0 || buffer == NULL || length <= 0)
444         return -1;
445
446     rc = write(fd, buffer, length);
447     return rc;
448 }
449
450 int xmm6260_sec_modem_ipc_poll(int fd, struct timeval *timeout)
451 {
452     fd_set fds;
453     int rc;
454     int status;
455
456     if (fd < 0)
457         return -1;
458
459     FD_ZERO(&fds);
460     FD_SET(fd, &fds);
461
462     rc = select(fd + 1, &fds, NULL, NULL, timeout);
463     if (FD_ISSET(fd, &fds)) {
464         status = ioctl(fd, IOCTL_MODEM_STATUS, 0);
465         if (status != STATE_ONLINE && status != STATE_BOOTING)
466             return 0;
467     }
468
469     return rc;
470 }
471
472 char *xmm6260_sec_modem_ipc_gprs_get_iface(int cid)
473 {
474     char *iface = NULL;
475
476     if (cid > XMM6260_SEC_MODEM_GPRS_IFACE_COUNT)
477         return NULL;
478
479     asprintf(&iface, "%s%d", XMM6260_SEC_MODEM_GPRS_IFACE_PREFIX, cid - 1);
480
481     return iface;
482 }
483
484 int xmm6260_sec_modem_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
485 {
486     if (capabilities == NULL)
487         return -1;
488
489     capabilities->port_list = 0;
490     capabilities->cid_max = XMM6260_SEC_MODEM_GPRS_IFACE_COUNT;
491
492     return 0;
493 }
494
495 // vim:ts=4:sw=4:expandtab