1a3629de6212cd70bdb8bbd8626cab39dfa38c0f
[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_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_header_fill(&header, request);
187
188     buffer = malloc(header.length);
189
190     memcpy(buffer, &header, sizeof(struct ipc_header));
191     if (request->data != NULL && request->length > 0)
192         memcpy((void *) ((unsigned char *) buffer + sizeof(struct ipc_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_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_header)) {
240         ipc_client_log(client, "Reading FMT header from the modem failed");
241         goto error;
242     }
243
244     header = (struct ipc_header *) buffer;
245
246     ipc_message_info_fill(header, response);
247
248     if (header->length > sizeof(struct ipc_header)) {
249         response->length = header->length - sizeof(struct ipc_header);
250         response->data = malloc(response->length);
251
252         p = (unsigned char *) response->data;
253
254         count = rc - sizeof(struct ipc_header);
255         if (count > 0) {
256             memcpy(p, (void *) ((unsigned char *) buffer + sizeof(struct ipc_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 rfs_hdr 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     header.id = request->mseq;
300     header.cmd = request->index;
301     header.len = sizeof(struct rfs_hdr) + request->length;
302
303     buffer = malloc(header.len);
304
305     memcpy(buffer, &header, sizeof(struct rfs_hdr));
306     if (request->data != NULL && request->length > 0)
307         memcpy((void *) ((unsigned char *) buffer + sizeof(struct rfs_hdr)), request->data, request->length);
308
309     ipc_client_log_send(client, request, __func__);
310
311     p = (unsigned char *) buffer;
312
313     count = 0;
314     while (count < (int) header.len) {
315         rc = client->handlers->write(client->handlers->transport_data, p, header.len - count);
316         if (rc <= 0) {
317             ipc_client_log(client, "Writing RFS data to the modem failed");
318             goto error;
319         }
320
321         count += rc;
322         p += rc;
323     }
324
325     rc = 0;
326     goto complete;
327
328 error:
329     rc = -1;
330
331 complete:
332     if (buffer != NULL)
333         free(buffer);
334
335     return rc;
336 }
337
338 int xmm6260_sec_modem_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
339 {
340     struct rfs_hdr *header;
341     void *buffer = NULL;
342     unsigned char *p;
343     int length;
344     int count;
345     int rc;
346
347     if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
348         return -1;
349
350     length = XMM6260_DATA_SIZE;
351     buffer = malloc(length);
352
353     rc = client->handlers->read(client->handlers->transport_data, buffer, length);
354     if (rc < (int) sizeof(struct rfs_hdr)) {
355         ipc_client_log(client, "Reading RFS header from the modem failed");
356         goto error;
357     }
358
359     header = (struct rfs_hdr *) buffer;
360
361     memset(response, 0, sizeof(struct ipc_message_info));
362     response->aseq = header->id;
363     response->group = IPC_GROUP_RFS;
364     response->index = header->cmd;
365
366     if (header->len > sizeof(struct rfs_hdr)) {
367         response->length = header->len - sizeof(struct rfs_hdr);
368         response->data = malloc(response->length);
369
370         p = (unsigned char *) response->data;
371
372         count = rc - sizeof(struct rfs_hdr);
373         if (count > 0) {
374             memcpy(p, (void *) ((unsigned char *) buffer + sizeof(struct rfs_hdr)), count);
375             p += count;
376         }
377
378         while (count < (int) response->length) {
379             rc = client->handlers->read(client->handlers->transport_data, p, response->length - count);
380             if (rc <= 0) {
381                 ipc_client_log(client, "Reading RFS data from the modem failed");
382                 goto error;
383             }
384
385             count += rc;
386             p += rc;
387         }
388     }
389
390     ipc_client_log_recv(client, response, __func__);
391
392     rc = 0;
393     goto complete;
394
395 error:
396     rc = -1;
397
398 complete:
399     if (buffer != NULL)
400         free(buffer);
401
402     return rc;
403 }
404
405 int xmm6260_sec_modem_ipc_open(int type)
406 {
407     int fd;
408
409     switch (type) {
410         case IPC_CLIENT_TYPE_FMT:
411             fd = open(XMM6260_SEC_MODEM_IPC0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
412             break;
413         case IPC_CLIENT_TYPE_RFS:
414             fd = open(XMM6260_SEC_MODEM_RFS0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
415             break;
416         default:
417             return -1;
418     }
419
420     return fd;
421 }
422
423 int xmm6260_sec_modem_ipc_close(int fd)
424 {
425     if (fd < 0)
426         return -1;
427
428     close(fd);
429
430     return 0;
431 }
432
433 int xmm6260_sec_modem_ipc_read(int fd, void *buffer, unsigned int length)
434 {
435     int rc;
436
437     if (fd < 0 || buffer == NULL || length <= 0)
438         return -1;
439
440     rc = read(fd, buffer, length);
441     return rc;
442 }
443
444 int xmm6260_sec_modem_ipc_write(int fd, void *buffer, unsigned int length)
445 {
446     int rc;
447
448     if (fd < 0 || buffer == NULL || length <= 0)
449         return -1;
450
451     rc = write(fd, buffer, length);
452     return rc;
453 }
454
455 int xmm6260_sec_modem_ipc_poll(int fd, struct timeval *timeout)
456 {
457     fd_set fds;
458     int rc;
459     int status;
460
461     if (fd < 0)
462         return -1;
463
464     FD_ZERO(&fds);
465     FD_SET(fd, &fds);
466
467     rc = select(fd + 1, &fds, NULL, NULL, timeout);
468     if (FD_ISSET(fd, &fds)) {
469         status = ioctl(fd, IOCTL_MODEM_STATUS, 0);
470         if (status != STATE_ONLINE && status != STATE_BOOTING)
471             return 0;
472     }
473
474     return rc;
475 }
476
477 char *xmm6260_sec_modem_ipc_gprs_get_iface(int cid)
478 {
479     char *iface = NULL;
480
481     if (cid > XMM6260_SEC_MODEM_GPRS_IFACE_COUNT)
482         return NULL;
483
484     asprintf(&iface, "%s%d", XMM6260_SEC_MODEM_GPRS_IFACE_PREFIX, cid - 1);
485
486     return iface;
487 }
488
489 int xmm6260_sec_modem_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
490 {
491     if (capabilities == NULL)
492         return -1;
493
494     capabilities->port_list = 0;
495     capabilities->cid_max = XMM6260_SEC_MODEM_GPRS_IFACE_COUNT;
496
497     return 0;
498 }
499
500 // vim:ts=4:sw=4:expandtab