2 * This file is part of libsamsung-ipc.
4 * Copyright (C) 2011-2013 Paul Kocialkowski <contact@paulk.fr>
5 * Copyright (C) 2011 Simon Busch <morphis@gravedo.de>
6 * Copyright (C) 2011 Joerie de Gram <j.de.gram@gmail.com>
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.
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.
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/>.
29 #include <sys/ioctl.h>
31 #include <samsung-ipc.h>
35 #include "crespo_modem_ctl.h"
38 #include "crespo_ipc.h"
40 int crespo_ipc_bootstrap(struct ipc_client *client)
42 void *modem_image_data = NULL;
44 int modem_ctl_fd = -1;
53 ipc_client_log(client, "Starting crespo modem bootstrap");
55 modem_image_data = file_data_read(CRESPO_MODEM_IMAGE_DEVICE, CRESPO_MODEM_IMAGE_SIZE, 0x1000);
56 if (modem_image_data == NULL) {
57 ipc_client_log(client, "Reading modem image data failed");
60 ipc_client_log(client, "Read modem image data");
62 modem_ctl_fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR | O_NDELAY);
63 if (modem_ctl_fd < 0) {
64 ipc_client_log(client, "Opening modem ctl failed");
67 ipc_client_log(client, "Opened modem ctl");
69 rc = ioctl(modem_ctl_fd, IOCTL_MODEM_RESET);
71 ipc_client_log(client, "Resetting modem failed");
74 ipc_client_log(client, "Reset modem");
76 serial_fd = open(CRESPO_MODEM_SERIAL_DEVICE, O_RDWR | O_NDELAY);
78 ipc_client_log(client, "Opening serial failed");
81 ipc_client_log(client, "Opened serial");
85 p = (unsigned char *) modem_image_data;
87 rc = xmm6160_psi_send(client, serial_fd, (void *) p, CRESPO_PSI_SIZE);
89 ipc_client_log(client, "Sending XMM6160 PSI failed");
92 ipc_client_log(client, "Sent XMM6160 PSI");
96 lseek(modem_ctl_fd, 0, SEEK_SET);
98 rc = xmm6160_firmware_send(client, modem_ctl_fd, NULL, (void *) p, CRESPO_MODEM_IMAGE_SIZE - CRESPO_PSI_SIZE);
100 ipc_client_log(client, "Sending XMM6160 firmware failed");
103 ipc_client_log(client, "Sent XMM6160 firmware");
105 lseek(modem_ctl_fd, CRESPO_MODEM_CTL_NV_DATA_OFFSET, SEEK_SET);
107 rc = xmm6160_nv_data_send(client, modem_ctl_fd, NULL);
109 ipc_client_log(client, "Sending XMM6160 nv_data failed");
112 ipc_client_log(client, "Sent XMM6160 nv_data");
121 if (modem_image_data != NULL)
122 free(modem_image_data);
127 if (modem_ctl_fd >= 0)
133 int crespo_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
135 struct ipc_header header;
139 if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
142 ipc_header_fill(&header, request);
144 memset(&mio, 0, sizeof(struct modem_io));
145 mio.size = request->length + sizeof(struct ipc_header);
146 mio.data = malloc(mio.size);
148 memcpy(mio.data, &header, sizeof(struct ipc_header));
149 if (request->data != NULL && request->length > 0)
150 memcpy((void *) ((unsigned char *) mio.data + sizeof(struct ipc_header)), request->data, request->length);
152 ipc_client_log_send(client, request, __func__);
154 rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io));
156 ipc_client_log(client, "Writing FMT data to the modem failed");
167 if (mio.data != NULL)
173 int crespo_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
175 struct ipc_header *header;
179 if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
182 memset(&mio, 0, sizeof(struct modem_io));
183 mio.size = CRESPO_DATA_SIZE;
184 mio.data = malloc(mio.size);
186 rc = client->handlers->read(client->handlers->transport_data, &mio, sizeof(struct modem_io) + mio.size);
187 if (rc < 0 || mio.data == NULL || mio.size < sizeof(struct ipc_header)) {
188 ipc_client_log(client, "Reading FMT data from the modem failed");
192 header = (struct ipc_header *) mio.data;
194 ipc_message_info_fill(header, response);
196 if (mio.size > sizeof(struct ipc_header)) {
197 response->length = mio.size - sizeof(struct ipc_header);
198 response->data = malloc(response->length);
200 memcpy(response->data, (void *) ((unsigned char *) mio.data + sizeof(struct ipc_header)), response->length);
203 ipc_client_log_recv(client, response, __func__);
212 if (mio.data != NULL)
218 int crespo_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
223 if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
226 memset(&mio, 0, sizeof(struct modem_io));
227 mio.id = request->mseq;
228 mio.cmd = request->index;
229 mio.size = request->length;
231 if (request->data != NULL && request->length > 0) {
232 mio.data = malloc(mio.size);
234 memcpy(mio.data, request->data, request->length);
237 ipc_client_log_send(client, request, __func__);
239 rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io));
241 ipc_client_log(client, "Writing RFS data to the modem failed");
252 if (mio.data != NULL)
258 int crespo_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
263 if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
266 memset(&mio, 0, sizeof(struct modem_io));
267 mio.size = CRESPO_DATA_SIZE;
268 mio.data = malloc(mio.size);
270 rc = client->handlers->read(client->handlers->transport_data, &mio, sizeof(struct modem_io) + mio.size);
271 if (rc < 0 || mio.data == NULL || mio.size <= 0) {
272 ipc_client_log(client, "Reading RFS data from the modem failed");
276 memset(response, 0, sizeof(struct ipc_message_info));
277 response->aseq = mio.id;
278 response->group = IPC_GROUP_RFS;
279 response->index = mio.cmd;
282 response->length = mio.size;
283 response->data = malloc(response->length);
285 memcpy(response->data, mio.data, response->length);
288 ipc_client_log_recv(client, response, __func__);
297 if (mio.data != NULL)
303 int crespo_ipc_open(void *data, int type)
305 struct crespo_ipc_transport_data *transport_data;
311 transport_data = (struct crespo_ipc_transport_data *) data;
314 case IPC_CLIENT_TYPE_FMT:
315 fd = open(CRESPO_MODEM_FMT_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
317 case IPC_CLIENT_TYPE_RFS:
318 fd = open(CRESPO_MODEM_RFS_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
327 transport_data->fd = fd;
332 int crespo_ipc_close(void *data)
334 struct crespo_ipc_transport_data *transport_data;
340 transport_data = (struct crespo_ipc_transport_data *) data;
342 fd = transport_data->fd;
346 transport_data->fd = -1;
352 int crespo_ipc_read(void *data, void *buffer, unsigned int length)
354 struct crespo_ipc_transport_data *transport_data;
358 if (data == NULL || buffer == NULL || length == 0)
361 transport_data = (struct crespo_ipc_transport_data *) data;
363 fd = transport_data->fd;
367 rc = ioctl(fd, IOCTL_MODEM_RECV, buffer);
374 int crespo_ipc_write(void *data, void *buffer, unsigned int length)
376 struct crespo_ipc_transport_data *transport_data;
380 if (data == NULL || buffer == NULL || length == 0)
383 transport_data = (struct crespo_ipc_transport_data *) data;
385 fd = transport_data->fd;
389 rc = ioctl(fd, IOCTL_MODEM_SEND, buffer);
396 int crespo_ipc_poll(void *data, struct timeval *timeout)
398 struct crespo_ipc_transport_data *transport_data;
406 transport_data = (struct crespo_ipc_transport_data *) data;
408 fd = transport_data->fd;
415 rc = select(fd + 1, &fds, NULL, NULL, timeout);
419 int crespo_ipc_power_on(void *data)
424 fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR);
428 rc = ioctl(fd, IOCTL_MODEM_START);
438 int crespo_ipc_power_off(void *data)
443 fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR);
447 rc = ioctl(fd, IOCTL_MODEM_OFF);
457 int crespo_ipc_data_create(void **transport_data, void **power_data, void **gprs_data)
459 if (transport_data == NULL)
462 *transport_data = (void *) malloc(sizeof(struct crespo_ipc_transport_data));
463 memset(*transport_data, 0, sizeof(struct crespo_ipc_transport_data));
468 int crespo_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data)
470 if (transport_data == NULL)
473 free(transport_data);
478 char *crespo_ipc_gprs_get_iface_single(int cid)
482 asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, 0);
487 int crespo_ipc_gprs_get_capabilities_single(struct ipc_client_gprs_capabilities *capabilities)
489 if (capabilities == NULL)
492 capabilities->port_list = 0;
493 capabilities->cid_max = 1;
498 char *crespo_ipc_gprs_get_iface(int cid)
502 if (cid > CRESPO_GPRS_IFACE_COUNT)
505 asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, cid - 1);
510 int crespo_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
512 if (capabilities == NULL)
515 capabilities->port_list = 0;
516 capabilities->cid_max = CRESPO_GPRS_IFACE_COUNT;
521 struct ipc_ops crespo_ipc_fmt_ops = {
522 .bootstrap = crespo_ipc_bootstrap,
523 .send = crespo_ipc_fmt_send,
524 .recv = crespo_ipc_fmt_recv,
527 struct ipc_ops crespo_ipc_rfs_ops = {
529 .send = crespo_ipc_rfs_send,
530 .recv = crespo_ipc_rfs_recv,
533 struct ipc_handlers crespo_ipc_handlers = {
534 .open = crespo_ipc_open,
535 .close = crespo_ipc_close,
536 .read = crespo_ipc_read,
537 .write = crespo_ipc_write,
538 .poll = crespo_ipc_poll,
539 .transport_data = NULL,
540 .power_on = crespo_ipc_power_on,
541 .power_off = crespo_ipc_power_off,
543 .gprs_activate = NULL,
544 .gprs_deactivate = NULL,
546 .data_create = crespo_ipc_data_create,
547 .data_destroy = crespo_ipc_data_destroy,
550 struct ipc_gprs_specs crespo_ipc_gprs_specs_single = {
551 .gprs_get_iface = crespo_ipc_gprs_get_iface_single,
552 .gprs_get_capabilities = crespo_ipc_gprs_get_capabilities_single,
555 struct ipc_gprs_specs crespo_ipc_gprs_specs = {
556 .gprs_get_iface = crespo_ipc_gprs_get_iface,
557 .gprs_get_capabilities = crespo_ipc_gprs_get_capabilities,
560 // vim:ts=4:sw=4:expandtab