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 ipc_poll_fds *fds, struct timeval *timeout)
393 struct crespo_transport_data *transport_data;
404 transport_data = (struct crespo_transport_data *) data;
406 fd = transport_data->fd;
415 if (fds != NULL && fds->fds != NULL && fds->count > 0) {
416 for (i = 0; i < fds->count; i++) {
417 if (fds->fds[i] >= 0) {
418 FD_SET(fds->fds[i], &set);
420 if (fds->fds[i] > fd_max)
421 fd_max = fds->fds[i];
426 rc = select(fd_max + 1, &set, NULL, NULL, timeout);
428 if (fds != NULL && fds->fds != NULL && fds->count > 0) {
431 for (i = 0; i < fds->count; i++) {
432 if (!FD_ISSET(fds->fds[i], &set)) {
444 int crespo_power_on(void *data)
449 fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR);
453 rc = ioctl(fd, IOCTL_MODEM_START);
463 int crespo_power_off(void *data)
468 fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR);
472 rc = ioctl(fd, IOCTL_MODEM_OFF);
482 int crespo_data_create(void **transport_data, void **power_data,
485 if (transport_data == NULL)
488 *transport_data = calloc(1, sizeof(struct crespo_transport_data));
493 int crespo_data_destroy(void *transport_data, void *power_data, void *gprs_data)
495 if (transport_data == NULL)
498 free(transport_data);
503 int crespo_gprs_activate(void *data, unsigned int cid)
508 int crespo_gprs_deactivate(void *data, unsigned int cid)
513 char *crespo_gprs_get_iface_single(unsigned int cid)
517 asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, 0);
522 int crespo_gprs_get_capabilities_single(struct ipc_client_gprs_capabilities *capabilities)
524 if (capabilities == NULL)
527 capabilities->cid_count = 1;
532 char *crespo_gprs_get_iface(unsigned int cid)
536 if (cid > CRESPO_GPRS_IFACE_COUNT)
539 asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, cid - 1);
544 int crespo_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
546 if (capabilities == NULL)
549 capabilities->cid_count = CRESPO_GPRS_IFACE_COUNT;
554 struct ipc_client_ops crespo_fmt_ops = {
556 .send = crespo_fmt_send,
557 .recv = crespo_fmt_recv,
560 struct ipc_client_ops crespo_rfs_ops = {
562 .send = crespo_rfs_send,
563 .recv = crespo_rfs_recv,
566 struct ipc_client_handlers crespo_handlers = {
568 .close = crespo_close,
570 .write = crespo_write,
572 .transport_data = NULL,
573 .power_on = crespo_power_on,
574 .power_off = crespo_power_off,
576 .gprs_activate = crespo_gprs_activate,
577 .gprs_deactivate = crespo_gprs_deactivate,
579 .data_create = crespo_data_create,
580 .data_destroy = crespo_data_destroy,
583 struct ipc_client_gprs_specs crespo_gprs_specs_single = {
584 .gprs_get_iface = crespo_gprs_get_iface_single,
585 .gprs_get_capabilities = crespo_gprs_get_capabilities_single,
588 struct ipc_client_gprs_specs crespo_gprs_specs = {
589 .gprs_get_iface = crespo_gprs_get_iface,
590 .gprs_get_capabilities = crespo_gprs_get_capabilities,
593 struct ipc_client_nv_data_specs crespo_nv_data_specs = {
594 .nv_data_path = XMM616_NV_DATA_PATH,
595 .nv_data_md5_path = XMM616_NV_DATA_MD5_PATH,
596 .nv_data_backup_path = XMM616_NV_DATA_BACKUP_PATH,
597 .nv_data_backup_md5_path = XMM616_NV_DATA_BACKUP_MD5_PATH,
598 .nv_data_secret = XMM616_NV_DATA_SECRET,
599 .nv_data_size = XMM616_NV_DATA_SIZE,
600 .nv_data_chunk_size = XMM616_NV_DATA_CHUNK_SIZE,
603 // vim:ts=4:sw=4:expandtab