2 * This file is part of libsamsung-ipc.
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>
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/>.
28 #include <sys/ioctl.h>
30 #include <samsung-ipc.h>
33 #include "crespo_modem_ctl.h"
38 int crespo_boot(struct ipc_client *client)
40 void *modem_image_data = NULL;
41 int modem_ctl_fd = -1;
49 ipc_client_log(client, "Starting crespo modem boot");
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");
56 ipc_client_log(client, "Read modem image data");
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");
63 ipc_client_log(client, "Opened modem ctl");
65 rc = ioctl(modem_ctl_fd, IOCTL_MODEM_RESET);
67 ipc_client_log(client, "Resetting modem failed");
70 ipc_client_log(client, "Reset modem");
72 serial_fd = open(CRESPO_MODEM_SERIAL_DEVICE, O_RDWR | O_NDELAY);
74 ipc_client_log(client, "Opening serial failed");
77 ipc_client_log(client, "Opened serial");
81 p = (unsigned char *) modem_image_data;
83 rc = xmm616_psi_send(client, serial_fd, (void *) p, CRESPO_PSI_SIZE);
85 ipc_client_log(client, "Sending XMM616 PSI failed");
88 ipc_client_log(client, "Sent XMM616 PSI");
92 lseek(modem_ctl_fd, 0, SEEK_SET);
94 rc = xmm616_firmware_send(client, modem_ctl_fd, NULL, (void *) p, CRESPO_MODEM_IMAGE_SIZE - CRESPO_PSI_SIZE);
96 ipc_client_log(client, "Sending XMM616 firmware failed");
99 ipc_client_log(client, "Sent XMM616 firmware");
101 lseek(modem_ctl_fd, CRESPO_MODEM_CTL_NV_DATA_OFFSET, SEEK_SET);
103 rc = xmm616_nv_data_send(client, modem_ctl_fd, NULL);
105 ipc_client_log(client, "Sending XMM616 nv_data failed");
108 ipc_client_log(client, "Sent XMM616 nv_data");
117 if (modem_image_data != NULL)
118 free(modem_image_data);
123 if (modem_ctl_fd >= 0)
129 int crespo_fmt_send(struct ipc_client *client, struct ipc_message *message)
131 struct ipc_fmt_header header;
135 if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || message == NULL)
138 ipc_fmt_header_setup(&header, message);
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);
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);
148 ipc_client_log_send(client, message, __func__);
150 rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io));
152 ipc_client_log(client, "Writing FMT data failed");
163 if (mio.data != NULL)
169 int crespo_fmt_recv(struct ipc_client *client, struct ipc_message *message)
171 struct ipc_fmt_header *header;
175 if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || message == NULL)
178 memset(&mio, 0, sizeof(struct modem_io));
179 mio.size = CRESPO_BUFFER_LENGTH;
180 mio.data = calloc(1, mio.size);
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) || mio.size > CRESPO_BUFFER_LENGTH) {
184 ipc_client_log(client, "Reading FMT data failed");
188 header = (struct ipc_fmt_header *) mio.data;
190 ipc_fmt_message_setup(header, message);
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);
196 memcpy(message->data, (void *) ((unsigned char *) mio.data + sizeof(struct ipc_fmt_header)), message->size);
199 ipc_client_log_recv(client, message, __func__);
208 if (mio.data != NULL)
214 int crespo_rfs_send(struct ipc_client *client, struct ipc_message *message)
219 if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || message == NULL)
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;
227 if (message->data != NULL && message->size > 0) {
228 mio.data = calloc(1, mio.size);
230 memcpy(mio.data, message->data, message->size);
233 ipc_client_log_send(client, message, __func__);
235 rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io));
237 ipc_client_log(client, "Writing RFS data failed");
248 if (mio.data != NULL)
254 int crespo_rfs_recv(struct ipc_client *client, struct ipc_message *message)
259 if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || message == NULL)
262 memset(&mio, 0, sizeof(struct modem_io));
263 mio.size = CRESPO_BUFFER_LENGTH;
264 mio.data = calloc(1, mio.size);
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 || mio.size > CRESPO_BUFFER_LENGTH) {
268 ipc_client_log(client, "Reading RFS data failed");
272 memset(message, 0, sizeof(struct ipc_message));
273 message->aseq = mio.id;
274 message->command = IPC_COMMAND(IPC_GROUP_RFS, mio.cmd);
277 message->size = mio.size;
278 message->data = calloc(1, message->size);
280 memcpy(message->data, mio.data, message->size);
283 ipc_client_log_recv(client, message, __func__);
292 if (mio.data != NULL)
298 int crespo_open(void *data, int type)
300 struct crespo_transport_data *transport_data;
306 transport_data = (struct crespo_transport_data *) data;
309 case IPC_CLIENT_TYPE_FMT:
310 fd = open(CRESPO_MODEM_FMT_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
312 case IPC_CLIENT_TYPE_RFS:
313 fd = open(CRESPO_MODEM_RFS_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
322 transport_data->fd = fd;
327 int crespo_close(void *data)
329 struct crespo_transport_data *transport_data;
335 transport_data = (struct crespo_transport_data *) data;
337 fd = transport_data->fd;
341 transport_data->fd = -1;
347 int crespo_read(void *data, void *buffer, size_t length)
349 struct crespo_transport_data *transport_data;
353 if (data == NULL || buffer == NULL || length == 0)
356 transport_data = (struct crespo_transport_data *) data;
358 fd = transport_data->fd;
362 rc = ioctl(fd, IOCTL_MODEM_RECV, buffer);
369 int crespo_write(void *data, const void *buffer, size_t length)
371 struct crespo_transport_data *transport_data;
375 if (data == NULL || buffer == NULL || length == 0)
378 transport_data = (struct crespo_transport_data *) data;
380 fd = transport_data->fd;
384 rc = ioctl(fd, IOCTL_MODEM_SEND, buffer);
391 int crespo_poll(void *data, struct timeval *timeout)
393 struct crespo_transport_data *transport_data;
401 transport_data = (struct crespo_transport_data *) data;
403 fd = transport_data->fd;
410 rc = select(fd + 1, &fds, NULL, NULL, timeout);
414 int crespo_power_on(void *data)
419 fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR);
423 rc = ioctl(fd, IOCTL_MODEM_START);
433 int crespo_power_off(void *data)
438 fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR);
442 rc = ioctl(fd, IOCTL_MODEM_OFF);
452 int crespo_data_create(void **transport_data, void **power_data,
455 if (transport_data == NULL)
458 *transport_data = calloc(1, sizeof(struct crespo_transport_data));
463 int crespo_data_destroy(void *transport_data, void *power_data, void *gprs_data)
465 if (transport_data == NULL)
468 free(transport_data);
473 int crespo_gprs_activate(void *data, unsigned int cid)
478 int crespo_gprs_deactivate(void *data, unsigned int cid)
483 char *crespo_gprs_get_iface_single(unsigned int cid)
487 asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, 0);
492 int crespo_gprs_get_capabilities_single(struct ipc_client_gprs_capabilities *capabilities)
494 if (capabilities == NULL)
497 capabilities->cid_count = 1;
502 char *crespo_gprs_get_iface(unsigned int cid)
506 if (cid > CRESPO_GPRS_IFACE_COUNT)
509 asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, cid - 1);
514 int crespo_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
516 if (capabilities == NULL)
519 capabilities->cid_count = CRESPO_GPRS_IFACE_COUNT;
524 struct ipc_client_ops crespo_fmt_ops = {
526 .send = crespo_fmt_send,
527 .recv = crespo_fmt_recv,
530 struct ipc_client_ops crespo_rfs_ops = {
532 .send = crespo_rfs_send,
533 .recv = crespo_rfs_recv,
536 struct ipc_client_handlers crespo_handlers = {
538 .close = crespo_close,
540 .write = crespo_write,
542 .transport_data = NULL,
543 .power_on = crespo_power_on,
544 .power_off = crespo_power_off,
546 .gprs_activate = crespo_gprs_activate,
547 .gprs_deactivate = crespo_gprs_deactivate,
549 .data_create = crespo_data_create,
550 .data_destroy = crespo_data_destroy,
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,
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,
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,
573 // vim:ts=4:sw=4:expandtab