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 Igor Almeida <igor.contato@gmail.com>
7 * Copyright (C) 2011 Joerie de Gram <j.de.gram@gmail.com>
9 * libsamsung-ipc is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
14 * libsamsung-ipc is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>.
30 #include <sys/ioctl.h>
34 #include <samsung-ipc.h>
42 #include "aries_ipc.h"
44 int aries_ipc_bootstrap(struct ipc_client *client)
46 void *modem_image_data = NULL;
47 void *onedram_address = NULL;
48 unsigned int onedram_init;
49 unsigned int onedram_magic;
50 unsigned int onedram_deinit;
55 struct timeval timeout;
63 if (client == NULL || client->handlers == NULL || client->handlers->power_on == NULL || client->handlers->power_off == NULL)
66 ipc_client_log(client, "Starting aries modem bootstrap");
68 modem_image_data = file_data_read(ARIES_MODEM_IMAGE_DEVICE, ARIES_MODEM_IMAGE_SIZE, 0x1000);
69 if (modem_image_data == NULL) {
70 ipc_client_log(client, "Reading modem image data failed");
73 ipc_client_log(client, "Read modem image data");
75 onedram_fd = open(ARIES_ONEDRAM_DEVICE, O_RDWR);
77 ipc_client_log(client, "Opening onedram failed");
80 ipc_client_log(client, "Opened onedram");
82 rc = network_iface_down(ARIES_MODEM_IFACE, AF_PHONET, SOCK_DGRAM);
84 ipc_client_log(client, "Turning modem network iface down failed");
87 ipc_client_log(client, "Turned modem network iface down");
89 rc = client->handlers->power_on(client->handlers->power_data);
91 ipc_client_log(client, "Powering the modem off failed");
94 ipc_client_log(client, "Powered the modem off");
98 rc = client->handlers->power_off(client->handlers->power_data);
100 ipc_client_log(client, "Powering the modem on failed");
103 ipc_client_log(client, "Powered the modem on");
105 serial_fd = open(ARIES_MODEM_SERIAL_DEVICE, O_RDWR | O_NDELAY);
107 ipc_client_log(client, "Opening serial failed");
110 ipc_client_log(client, "Opened serial");
114 p = (unsigned char *) modem_image_data;
116 rc = xmm6160_psi_send(client, serial_fd, (void *) p, ARIES_PSI_SIZE);
118 ipc_client_log(client, "Sending XMM6160 PSI failed");
121 ipc_client_log(client, "Sent XMM6160 PSI");
128 FD_SET(onedram_fd, &fds);
135 rc = select(onedram_fd + 1, &fds, NULL, NULL, &timeout);
137 ipc_client_log(client, "Reading onedram init failed");
141 rc = read(onedram_fd, &onedram_init, sizeof(onedram_init));
142 if (rc < (int) sizeof(onedram_init)) {
143 ipc_client_log(client, "Reading onedram init failed");
148 ipc_client_log(client, "Reading onedram init failed");
151 } while (onedram_init != ARIES_ONEDRAM_INIT);
152 ipc_client_log(client, "Read onedram init (0x%x)", onedram_init);
154 onedram_address = mmap(NULL, ARIES_ONEDRAM_MEMORY_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, onedram_fd, 0);
155 if (onedram_address == NULL || onedram_address == (void *) 0xffffffff) {
156 ipc_client_log(client, "Mapping onedram to memory failed");
159 ipc_client_log(client, "Mapped onedram to memory");
161 pp = (unsigned char *) onedram_address;
163 rc = xmm6160_firmware_send(client, -1, (void *) pp, (void *) p, ARIES_MODEM_IMAGE_SIZE - ARIES_PSI_SIZE);
165 ipc_client_log(client, "Sending XMM6160 firmware failed");
168 ipc_client_log(client, "Sent XMM6160 firmware");
170 pp = (unsigned char *) onedram_address + ARIES_ONEDRAM_NV_DATA_OFFSET;
172 rc = xmm6160_nv_data_send(client, -1, pp);
174 ipc_client_log(client, "Sending XMM6160 nv_data failed");
177 ipc_client_log(client, "Sent XMM6160 nv_data");
179 munmap(onedram_address, ARIES_ONEDRAM_MEMORY_SIZE);
180 onedram_address = NULL;
182 rc = ioctl(onedram_fd, ONEDRAM_REL_SEM);
186 onedram_magic = ARIES_ONEDRAM_MAGIC;
187 rc = write(onedram_fd, &onedram_magic, sizeof(onedram_magic));
188 if (rc < (int) sizeof(onedram_magic)) {
189 ipc_client_log(client, "Writing onedram magic failed");
192 ipc_client_log(client, "Wrote onedram magic");
195 FD_SET(onedram_fd, &fds);
202 rc = select(onedram_fd + 1, &fds, NULL, NULL, &timeout);
204 ipc_client_log(client, "Reading onedram deinit failed");
208 rc = read(onedram_fd, &onedram_deinit, sizeof(onedram_deinit));
209 if (rc < (int) sizeof(onedram_deinit)) {
210 ipc_client_log(client, "Reading onedram deinit failed");
215 ipc_client_log(client, "Reading onedram deinit failed");
218 } while (onedram_deinit != ARIES_ONEDRAM_DEINIT);
219 ipc_client_log(client, "Read onedram deinit (0x%x)", onedram_deinit);
228 if (modem_image_data != NULL)
229 free(modem_image_data);
234 if (onedram_address != NULL)
235 munmap(onedram_address, ARIES_ONEDRAM_MEMORY_SIZE);
243 int aries_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
245 struct ipc_fmt_header header;
249 if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
252 ipc_fmt_header_fill(&header, request);
254 buffer = malloc(header.length);
256 memcpy(buffer, &header, sizeof(struct ipc_fmt_header));
257 if (request->data != NULL && request->length > 0)
258 memcpy((void *) ((unsigned char *) buffer + sizeof(struct ipc_fmt_header)), request->data, request->length);
260 ipc_client_log_send(client, request, __func__);
262 rc = client->handlers->write(client->handlers->transport_data, buffer, header.length);
263 if (rc < header.length) {
264 ipc_client_log(client, "Writing FMT data to the modem failed");
281 int aries_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
283 struct ipc_fmt_header *header;
288 if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
291 length = ARIES_DATA_SIZE;
292 buffer = malloc(length);
294 rc = client->handlers->read(client->handlers->transport_data, buffer, length);
295 if (rc < (int) sizeof(struct ipc_fmt_header)) {
296 ipc_client_log(client, "Reading FMT data from the modem failed");
300 header = (struct ipc_fmt_header *) buffer;
302 ipc_fmt_message_fill(header, response);
304 if (header->length > sizeof(struct ipc_fmt_header)) {
305 response->length = header->length - sizeof(struct ipc_fmt_header);
306 response->data = malloc(response->length);
308 memcpy(response->data, (void *) ((unsigned char *) buffer + sizeof(struct ipc_fmt_header)), response->length);
311 ipc_client_log_recv(client, response, __func__);
328 int aries_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
330 struct ipc_rfs_header header;
334 if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
337 ipc_rfs_header_fill(&header, request);
339 buffer = malloc(header.length);
341 memcpy(buffer, &header, sizeof(struct ipc_rfs_header));
342 if (request->data != NULL && request->length > 0)
343 memcpy((void *) ((unsigned char *) buffer + sizeof(struct ipc_rfs_header)), request->data, request->length);
345 ipc_client_log_send(client, request, __func__);
347 rc = client->handlers->write(client->handlers->transport_data, buffer, header.length);
349 ipc_client_log(client, "Writing RFS data to the modem failed");
366 int aries_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
368 struct ipc_rfs_header *header;
373 if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
376 length = ARIES_DATA_SIZE;
377 buffer = malloc(length);
379 rc = client->handlers->read(client->handlers->transport_data, buffer, length);
380 if (rc < (int) sizeof(struct ipc_rfs_header)) {
381 ipc_client_log(client, "Reading RFS data from the modem failed");
385 header = (struct ipc_rfs_header *) buffer;
387 ipc_rfs_message_fill(header, response);
389 if (header->length > sizeof(struct ipc_rfs_header)) {
390 response->length = header->length - sizeof(struct ipc_rfs_header);
391 response->data = malloc(response->length);
393 memcpy(response->data, (void *) ((unsigned char *) buffer + sizeof(struct ipc_rfs_header)), response->length);
396 ipc_client_log_recv(client, response, __func__);
411 int aries_ipc_open(void *data, int type)
413 struct aries_ipc_transport_data *transport_data;
414 struct sockaddr_pn *spn;
418 int socket_rfs_magic;
426 transport_data = (struct aries_ipc_transport_data *) data;
427 memset(data, 0, sizeof(struct aries_ipc_transport_data));
429 spn = &transport_data->spn;
431 memset(&ifr, 0, sizeof(ifr));
432 strncpy(ifr.ifr_name, ARIES_MODEM_IFACE, IFNAMSIZ);
434 spn->spn_family = AF_PHONET;
438 case IPC_CLIENT_TYPE_FMT:
439 spn->spn_resource = ARIES_MODEM_FMT_SPN;
441 case IPC_CLIENT_TYPE_RFS:
442 spn->spn_resource = ARIES_MODEM_RFS_SPN;
448 fd = socket(AF_PHONET, SOCK_DGRAM, 0);
452 rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, IFNAMSIZ);
456 rc = ioctl(fd, SIOCGIFINDEX, &ifr);
461 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
465 rc = bind(fd, (const struct sockaddr *) spn, sizeof(struct sockaddr_pn));
469 transport_data->fd = fd;
471 if (type == IPC_CLIENT_TYPE_RFS)
473 socket_rfs_magic = ARIES_SOCKET_RFS_MAGIC;
474 rc = setsockopt(fd, SOL_SOCKET, SO_IPC_RFS, &socket_rfs_magic, sizeof(socket_rfs_magic));
479 rc = network_iface_up(ARIES_MODEM_IFACE, AF_PHONET, SOCK_DGRAM);
486 int aries_ipc_close(void *data)
488 struct aries_ipc_transport_data *transport_data;
494 transport_data = (struct aries_ipc_transport_data *) data;
496 fd = transport_data->fd;
500 transport_data->fd = -1;
506 int aries_ipc_read(void *data, void *buffer, unsigned int length)
508 struct aries_ipc_transport_data *transport_data;
513 if (data == NULL || buffer == NULL || length == 0)
516 transport_data = (struct aries_ipc_transport_data *) data;
518 fd = transport_data->fd;
522 spn_size = sizeof(struct sockaddr_pn);
524 rc = recvfrom(fd, buffer, length, 0, (const struct sockaddr *) &transport_data->spn, &spn_size);
528 int aries_ipc_write(void *data, void *buffer, unsigned int length)
530 struct aries_ipc_transport_data *transport_data;
535 if (data == NULL || buffer == NULL || length == 0)
538 transport_data = (struct aries_ipc_transport_data *) data;
540 fd = transport_data->fd;
544 spn_size = sizeof(struct sockaddr_pn);
546 rc = sendto(fd, buffer, length, 0, (const struct sockaddr *) &transport_data->spn, spn_size);
550 int aries_ipc_poll(void *data, struct timeval *timeout)
552 struct aries_ipc_transport_data *transport_data;
560 transport_data = (struct aries_ipc_transport_data *) data;
562 fd = transport_data->fd;
569 rc = select(fd + 1, &fds, NULL, NULL, timeout);
573 int aries_ipc_power_on(void *data)
575 char buffer[] = "on\n";
579 value = sysfs_value_read(ARIES_MODEMCTL_STATUS_SYSFS);
583 /* The modem is already on */
587 rc = sysfs_string_write(ARIES_MODEMCTL_CONTROL_SYSFS, (char *) &buffer, strlen(buffer));
594 int aries_ipc_power_off(void *data)
596 char buffer[] = "off\n";
600 value = sysfs_value_read(ARIES_MODEMCTL_STATUS_SYSFS);
604 /* The modem is already off */
608 rc = sysfs_string_write(ARIES_MODEMCTL_CONTROL_SYSFS, (char *) &buffer, strlen(buffer));
615 int aries_ipc_data_create(void **transport_data, void **power_data, void **gprs_data)
617 if (transport_data == NULL)
620 *transport_data = (void *) malloc(sizeof(struct aries_ipc_transport_data));
621 memset(*transport_data, 0, sizeof(struct aries_ipc_transport_data));
626 int aries_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data)
628 if (transport_data == NULL)
631 free(transport_data);
636 int aries_ipc_gprs_activate(void *data, int cid)
640 rc = sysfs_value_write(ARIES_MODEM_PDP_ACTIVATE_SYSFS, cid);
647 int aries_ipc_gprs_deactivate(void *data, int cid)
651 rc = sysfs_value_write(ARIES_MODEM_PDP_DEACTIVATE_SYSFS, cid);
658 char *aries_ipc_gprs_get_iface(int cid)
666 memset(&ifr, 0, sizeof(ifr));
668 fd = socket(AF_PHONET, SOCK_DGRAM, 0);
672 for (i = (ARIES_GPRS_IFACE_COUNT - 1); i >= 0; i--) {
673 sprintf(ifr.ifr_name, "%s%d", ARIES_GPRS_IFACE_PREFIX, i);
674 rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
675 if (rc < 0 || ifr.ifr_flags & IFF_UP) {
678 asprintf(&iface, "%s%d", ARIES_GPRS_IFACE_PREFIX, i);
686 int aries_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
688 if (capabilities == NULL)
691 capabilities->port_list = 1;
692 capabilities->cid_max = ARIES_GPRS_IFACE_COUNT;
697 struct ipc_ops aries_ipc_fmt_ops = {
698 .bootstrap = aries_ipc_bootstrap,
699 .send = aries_ipc_fmt_send,
700 .recv = aries_ipc_fmt_recv,
703 struct ipc_ops aries_ipc_rfs_ops = {
705 .send = aries_ipc_rfs_send,
706 .recv = aries_ipc_rfs_recv,
709 struct ipc_handlers aries_ipc_handlers = {
710 .open = aries_ipc_open,
711 .close = aries_ipc_close,
712 .read = aries_ipc_read,
713 .write = aries_ipc_write,
714 .poll = aries_ipc_poll,
715 .transport_data = NULL,
716 .power_on = aries_ipc_power_on,
717 .power_off = aries_ipc_power_off,
719 .gprs_activate = aries_ipc_gprs_activate,
720 .gprs_deactivate = aries_ipc_gprs_deactivate,
722 .data_create = aries_ipc_data_create,
723 .data_destroy = aries_ipc_data_destroy,
726 struct ipc_gprs_specs aries_ipc_gprs_specs = {
727 .gprs_get_iface = aries_ipc_gprs_get_iface,
728 .gprs_get_capabilities = aries_ipc_gprs_get_capabilities,
731 // vim:ts=4:sw=4:expandtab