Missing gprs_activate/deactivate handlers definitions
[libsamsung-ipc.git] / samsung-ipc / devices / crespo / crespo.c
1 /*
2  * This file is part of libsamsung-ipc.
3  *
4  * Copyright (C) 2011 Joerie de Gram <j.de.gram@gmail.com>
5  * Copyright (C) 2011 Simon Busch <morphis@gravedo.de>
6  * Copyright (C) 2011-2014 Paul Kocialkowski <contact@paulk.fr>
7  *
8  * libsamsung-ipc is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * libsamsung-ipc is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <stdint.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <fcntl.h>
28 #include <sys/ioctl.h>
29
30 #include <samsung-ipc.h>
31 #include <ipc.h>
32
33 #include "crespo_modem_ctl.h"
34
35 #include "xmm616.h"
36 #include "crespo.h"
37
38 int crespo_boot(struct ipc_client *client)
39 {
40     void *modem_image_data = NULL;
41     int modem_ctl_fd = -1;
42     int serial_fd = -1;
43     unsigned char *p;
44     int rc;
45
46     if (client == NULL)
47         return -1;
48
49     ipc_client_log(client, "Starting crespo modem boot");
50
51     modem_image_data = file_data_read(CRESPO_MODEM_IMAGE_DEVICE, CRESPO_MODEM_IMAGE_SIZE, 0x1000, 0);
52     if (modem_image_data == NULL) {
53         ipc_client_log(client, "Reading modem image data failed");
54         goto error;
55     }
56     ipc_client_log(client, "Read modem image data");
57
58     modem_ctl_fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR | O_NDELAY);
59     if (modem_ctl_fd < 0) {
60         ipc_client_log(client, "Opening modem ctl failed");
61         goto error;
62     }
63     ipc_client_log(client, "Opened modem ctl");
64
65     rc = ioctl(modem_ctl_fd, IOCTL_MODEM_RESET);
66     if (rc < 0) {
67         ipc_client_log(client, "Resetting modem failed");
68         goto error;
69     }
70     ipc_client_log(client, "Reset modem");
71
72     serial_fd = open(CRESPO_MODEM_SERIAL_DEVICE, O_RDWR | O_NDELAY);
73     if (serial_fd < 0) {
74         ipc_client_log(client, "Opening serial failed");
75         goto error;
76     }
77     ipc_client_log(client, "Opened serial");
78
79     usleep(100000);
80
81     p = (unsigned char *) modem_image_data;
82
83     rc = xmm616_psi_send(client, serial_fd, (void *) p, CRESPO_PSI_SIZE);
84     if (rc < 0) {
85         ipc_client_log(client, "Sending XMM616 PSI failed");
86         goto error;
87     }
88     ipc_client_log(client, "Sent XMM616 PSI");
89
90     p += CRESPO_PSI_SIZE;
91
92     lseek(modem_ctl_fd, 0, SEEK_SET);
93
94     rc = xmm616_firmware_send(client, modem_ctl_fd, NULL, (void *) p, CRESPO_MODEM_IMAGE_SIZE - CRESPO_PSI_SIZE);
95     if (rc < 0) {
96         ipc_client_log(client, "Sending XMM616 firmware failed");
97         goto error;
98     }
99     ipc_client_log(client, "Sent XMM616 firmware");
100
101     lseek(modem_ctl_fd, CRESPO_MODEM_CTL_NV_DATA_OFFSET, SEEK_SET);
102
103     rc = xmm616_nv_data_send(client, modem_ctl_fd, NULL);
104     if (rc < 0) {
105         ipc_client_log(client, "Sending XMM616 nv_data failed");
106         goto error;
107     }
108     ipc_client_log(client, "Sent XMM616 nv_data");
109
110     rc = 0;
111     goto complete;
112
113 error:
114     rc = -1;
115
116 complete:
117     if (modem_image_data != NULL)
118         free(modem_image_data);
119
120     if (serial_fd >= 0)
121         close(serial_fd);
122
123     if (modem_ctl_fd >= 0)
124         close(modem_ctl_fd);
125
126     return rc;
127 }
128
129 int crespo_fmt_send(struct ipc_client *client, struct ipc_message *message)
130 {
131     struct ipc_fmt_header header;
132     struct modem_io mio;
133     int rc;
134
135     if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || message == NULL)
136         return -1;
137
138     ipc_fmt_header_setup(&header, message);
139
140     memset(&mio, 0, sizeof(struct modem_io));
141     mio.size = message->size + sizeof(struct ipc_fmt_header);
142     mio.data = calloc(1, mio.size);
143
144     memcpy(mio.data, &header, sizeof(struct ipc_fmt_header));
145     if (message->data != NULL && message->size > 0)
146         memcpy((void *) ((unsigned char *) mio.data + sizeof(struct ipc_fmt_header)), message->data, message->size);
147
148     ipc_client_log_send(client, message, __func__);
149
150     rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io));
151     if (rc < 0) {
152         ipc_client_log(client, "Writing FMT data failed");
153         goto error;
154     }
155
156     rc = 0;
157     goto complete;
158
159 error:
160     rc = -1;
161
162 complete:
163     if (mio.data != NULL)
164         free(mio.data);
165
166     return rc;
167 }
168
169 int crespo_fmt_recv(struct ipc_client *client, struct ipc_message *message)
170 {
171     struct ipc_fmt_header *header;
172     struct modem_io mio;
173     int rc;
174
175     if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || message == NULL)
176         return -1;
177
178     memset(&mio, 0, sizeof(struct modem_io));
179     mio.size = CRESPO_BUFFER_LENGTH;
180     mio.data = calloc(1, mio.size);
181
182     rc = client->handlers->read(client->handlers->transport_data, &mio, sizeof(struct modem_io) + mio.size);
183     if (rc < 0 || mio.data == NULL || mio.size < sizeof(struct ipc_fmt_header)) {
184         ipc_client_log(client, "Reading FMT data failed");
185         goto error;
186     }
187
188     header = (struct ipc_fmt_header *) mio.data;
189
190     ipc_fmt_message_setup(header, message);
191
192     if (mio.size > sizeof(struct ipc_fmt_header)) {
193         message->size = mio.size - sizeof(struct ipc_fmt_header);
194         message->data = calloc(1, message->size);
195
196         memcpy(message->data, (void *) ((unsigned char *) mio.data + sizeof(struct ipc_fmt_header)), message->size);
197     }
198
199     ipc_client_log_recv(client, message, __func__);
200
201     rc = 0;
202     goto complete;
203
204 error:
205     rc = -1;
206
207 complete:
208     if (mio.data != NULL)
209         free(mio.data);
210
211     return rc;
212 }
213
214 int crespo_rfs_send(struct ipc_client *client, struct ipc_message *message)
215 {
216     struct modem_io mio;
217     int rc;
218
219     if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || message == NULL)
220         return -1;
221
222     memset(&mio, 0, sizeof(struct modem_io));
223     mio.id = message->mseq;
224     mio.cmd = IPC_INDEX(message->command);
225     mio.size = message->size;
226
227     if (message->data != NULL && message->size > 0) {
228         mio.data = calloc(1, mio.size);
229
230         memcpy(mio.data, message->data, message->size);
231     }
232
233     ipc_client_log_send(client, message, __func__);
234
235     rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io));
236     if (rc < 0) {
237         ipc_client_log(client, "Writing RFS data failed");
238         goto error;
239     }
240
241     rc = 0;
242     goto complete;
243
244 error:
245     rc = -1;
246
247 complete:
248     if (mio.data != NULL)
249         free(mio.data);
250
251     return rc;
252 }
253
254 int crespo_rfs_recv(struct ipc_client *client, struct ipc_message *message)
255 {
256     struct modem_io mio;
257     int rc;
258
259     if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || message == NULL)
260         return -1;
261
262     memset(&mio, 0, sizeof(struct modem_io));
263     mio.size = CRESPO_BUFFER_LENGTH;
264     mio.data = calloc(1, mio.size);
265
266     rc = client->handlers->read(client->handlers->transport_data, &mio, sizeof(struct modem_io) + mio.size);
267     if (rc < 0 || mio.data == NULL || mio.size <= 0) {
268         ipc_client_log(client, "Reading RFS data failed");
269         goto error;
270     }
271
272     memset(message, 0, sizeof(struct ipc_message));
273     message->aseq = mio.id;
274     message->command = IPC_COMMAND(IPC_GROUP_RFS, mio.cmd);
275
276     if (mio.size > 0) {
277         message->size = mio.size;
278         message->data = calloc(1, message->size);
279
280         memcpy(message->data, mio.data, message->size);
281     }
282
283     ipc_client_log_recv(client, message, __func__);
284
285     rc = 0;
286     goto complete;
287
288 error:
289     rc = -1;
290
291 complete:
292     if (mio.data != NULL)
293         free(mio.data);
294
295     return rc;
296 }
297
298 int crespo_open(void *data, int type)
299 {
300     struct crespo_transport_data *transport_data;
301     int fd;
302
303     if (data == NULL)
304         return -1;
305
306     transport_data = (struct crespo_transport_data *) data;
307
308     switch (type) {
309         case IPC_CLIENT_TYPE_FMT:
310             fd = open(CRESPO_MODEM_FMT_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
311             break;
312         case IPC_CLIENT_TYPE_RFS:
313             fd = open(CRESPO_MODEM_RFS_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
314             break;
315         default:
316             return -1;
317     }
318
319     if (fd < 0)
320         return -1;
321
322     transport_data->fd = fd;
323
324     return 0;
325 }
326
327 int crespo_close(void *data)
328 {
329     struct crespo_transport_data *transport_data;
330     int fd;
331
332     if (data == NULL)
333         return -1;
334
335     transport_data = (struct crespo_transport_data *) data;
336
337     fd = transport_data->fd;
338     if (fd < 0)
339         return -1;
340
341     transport_data->fd = -1;
342     close(fd);
343
344     return 0;
345 }
346
347 int crespo_read(void *data, void *buffer, size_t length)
348 {
349     struct crespo_transport_data *transport_data;
350     int fd;
351     int rc;
352
353     if (data == NULL || buffer == NULL || length == 0)
354         return -1;
355
356     transport_data = (struct crespo_transport_data *) data;
357
358     fd = transport_data->fd;
359     if (fd < 0)
360         return -1;
361
362     rc = ioctl(fd, IOCTL_MODEM_RECV, buffer);
363     if (rc < 0)
364         return -1;
365
366     return 0;
367 }
368
369 int crespo_write(void *data, const void *buffer, size_t length)
370 {
371     struct crespo_transport_data *transport_data;
372     int fd;
373     int rc;
374
375     if (data == NULL || buffer == NULL || length == 0)
376         return -1;
377
378     transport_data = (struct crespo_transport_data *) data;
379
380     fd = transport_data->fd;
381     if (fd < 0)
382         return -1;
383
384     rc = ioctl(fd, IOCTL_MODEM_SEND, buffer);
385     if (rc < 0)
386         return -1;
387
388     return 0;
389 }
390
391 int crespo_poll(void *data, struct timeval *timeout)
392 {
393     struct crespo_transport_data *transport_data;
394     fd_set fds;
395     int fd;
396     int rc;
397
398     if (data == NULL)
399         return -1;
400
401     transport_data = (struct crespo_transport_data *) data;
402
403     fd = transport_data->fd;
404     if (fd < 0)
405         return -1;
406
407     FD_ZERO(&fds);
408     FD_SET(fd, &fds);
409
410     rc = select(fd + 1, &fds, NULL, NULL, timeout);
411     return rc;
412 }
413
414 int crespo_power_on(void *data)
415 {
416     int fd;
417     int rc;
418
419     fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR);
420     if (fd < 0)
421         return -1;
422
423     rc = ioctl(fd, IOCTL_MODEM_START);
424
425     close(fd);
426
427     if (rc < 0)
428         return -1;
429
430     return 0;
431 }
432
433 int crespo_power_off(void *data)
434 {
435     int fd;
436     int rc;
437
438     fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR);
439     if (fd < 0)
440         return -1;
441
442     rc = ioctl(fd, IOCTL_MODEM_OFF);
443
444     close(fd);
445
446     if (rc < 0)
447         return -1;
448
449     return 0;
450 }
451
452 int crespo_data_create(void **transport_data, void **power_data,
453     void **gprs_data)
454 {
455     if (transport_data == NULL)
456         return -1;
457
458     *transport_data = calloc(1, sizeof(struct crespo_transport_data));
459
460     return 0;
461 }
462
463 int crespo_data_destroy(void *transport_data, void *power_data, void *gprs_data)
464 {
465     if (transport_data == NULL)
466         return -1;
467
468     free(transport_data);
469
470     return 0;
471 }
472
473 int crespo_gprs_activate(void *data, unsigned int cid)
474 {
475     return 0;
476 }
477
478 int crespo_gprs_deactivate(void *data, unsigned int cid)
479 {
480     return 0;
481 }
482
483 char *crespo_gprs_get_iface_single(unsigned int cid)
484 {
485     char *iface = NULL;
486
487     asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, 0);
488
489     return iface;
490 }
491
492 int crespo_gprs_get_capabilities_single(struct ipc_client_gprs_capabilities *capabilities)
493 {
494     if (capabilities == NULL)
495         return -1;
496
497     capabilities->cid_count = 1;
498
499     return 0;
500 }
501
502 char *crespo_gprs_get_iface(unsigned int cid)
503 {
504     char *iface = NULL;
505
506     if (cid > CRESPO_GPRS_IFACE_COUNT)
507         return NULL;
508
509     asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, cid - 1);
510
511     return iface;
512 }
513
514 int crespo_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
515 {
516     if (capabilities == NULL)
517         return -1;
518
519     capabilities->cid_count = CRESPO_GPRS_IFACE_COUNT;
520
521     return 0;
522 }
523
524 struct ipc_client_ops crespo_fmt_ops = {
525     .boot = crespo_boot,
526     .send = crespo_fmt_send,
527     .recv = crespo_fmt_recv,
528 };
529
530 struct ipc_client_ops crespo_rfs_ops = {
531     .boot = NULL,
532     .send = crespo_rfs_send,
533     .recv = crespo_rfs_recv,
534 };
535
536 struct ipc_client_handlers crespo_handlers = {
537     .open = crespo_open,
538     .close = crespo_close,
539     .read = crespo_read,
540     .write = crespo_write,
541     .poll = crespo_poll,
542     .transport_data = NULL,
543     .power_on = crespo_power_on,
544     .power_off = crespo_power_off,
545     .power_data = NULL,
546     .gprs_activate = crespo_gprs_activate,
547     .gprs_deactivate = crespo_gprs_deactivate,
548     .gprs_data = NULL,
549     .data_create = crespo_data_create,
550     .data_destroy = crespo_data_destroy,
551 };
552
553 struct ipc_client_gprs_specs crespo_gprs_specs_single = {
554     .gprs_get_iface = crespo_gprs_get_iface_single,
555     .gprs_get_capabilities = crespo_gprs_get_capabilities_single,
556 };
557
558 struct ipc_client_gprs_specs crespo_gprs_specs = {
559     .gprs_get_iface = crespo_gprs_get_iface,
560     .gprs_get_capabilities = crespo_gprs_get_capabilities,
561 };
562
563 struct ipc_client_nv_data_specs crespo_nv_data_specs = {
564     .nv_data_path = XMM616_NV_DATA_PATH,
565     .nv_data_md5_path = XMM616_NV_DATA_MD5_PATH,
566     .nv_data_backup_path = XMM616_NV_DATA_BACKUP_PATH,
567     .nv_data_backup_md5_path = XMM616_NV_DATA_BACKUP_MD5_PATH,
568     .nv_data_secret = XMM616_NV_DATA_SECRET,
569     .nv_data_size = XMM616_NV_DATA_SIZE,
570     .nv_data_chunk_size = XMM616_NV_DATA_CHUNK_SIZE,
571 };
572
573 // vim:ts=4:sw=4:expandtab