aboutsummaryrefslogtreecommitdiffstats
path: root/samsung-ipc/device/xmm6260/xmm6260_sec_modem.c
diff options
context:
space:
mode:
Diffstat (limited to 'samsung-ipc/device/xmm6260/xmm6260_sec_modem.c')
-rw-r--r--samsung-ipc/device/xmm6260/xmm6260_sec_modem.c500
1 files changed, 500 insertions, 0 deletions
diff --git a/samsung-ipc/device/xmm6260/xmm6260_sec_modem.c b/samsung-ipc/device/xmm6260/xmm6260_sec_modem.c
new file mode 100644
index 0000000..1a3629d
--- /dev/null
+++ b/samsung-ipc/device/xmm6260/xmm6260_sec_modem.c
@@ -0,0 +1,500 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+
+#include <samsung-ipc.h>
+#include <ipc.h>
+#include <util.h>
+
+#include "modem.h"
+#include "modem_prj.h"
+#include "modem_link_device_hsic.h"
+
+#include "xmm6260.h"
+#include "xmm6260_sec_modem.h"
+
+int xmm6260_sec_modem_power(int device_fd, int power)
+{
+ int rc;
+
+ if (device_fd < 0)
+ return -1;
+
+ rc = ioctl(device_fd, power ? IOCTL_MODEM_ON : IOCTL_MODEM_OFF, 0);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int xmm6260_sec_modem_boot_power(int device_fd, int power)
+{
+ int rc;
+
+ if (device_fd < 0)
+ return -1;
+
+ rc = ioctl(device_fd, power ? IOCTL_MODEM_BOOT_ON : IOCTL_MODEM_BOOT_OFF, 0);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int xmm6260_sec_modem_status_online_wait(int device_fd)
+{
+ int status;
+ int i;
+
+ if (device_fd < 0)
+ return -1;
+
+ i = 0;
+ for (i = 0; i < 100; i++) {
+ status = ioctl(device_fd, IOCTL_MODEM_STATUS, 0);
+ if (status == STATE_ONLINE)
+ return 0;
+
+ usleep(50000);
+ }
+
+ return -1;
+}
+
+int xmm6260_sec_modem_hci_power(int power)
+{
+ int ehci_rc, ohci_rc;
+
+ ehci_rc = sysfs_value_write(XMM6260_SEC_MODEM_EHCI_POWER_SYSFS, !!power);
+ if (ehci_rc >= 0)
+ usleep(50000);
+
+ ohci_rc = sysfs_value_write(XMM6260_SEC_MODEM_OHCI_POWER_SYSFS, !!power);
+ if (ohci_rc >= 0)
+ usleep(50000);
+
+ if (ehci_rc < 0 && ohci_rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int xmm6260_sec_modem_link_control_enable(int device_fd, int enable)
+{
+ int rc;
+
+ if (device_fd < 0)
+ return -1;
+
+ rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ENABLE, &enable);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int xmm6260_sec_modem_link_control_active(int device_fd, int active)
+{
+ int rc;
+
+ if (device_fd < 0)
+ return -1;
+
+ rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ACTIVE, &active);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int xmm6260_sec_modem_link_connected_wait(int device_fd)
+{
+ int status;
+ int i;
+
+ if (device_fd < 0)
+ return -1;
+
+ i = 0;
+ for (i = 0; i < 100; i++) {
+ status = ioctl(device_fd, IOCTL_LINK_CONNECTED, 0);
+ if (status)
+ return 0;
+
+ usleep(50000);
+ }
+
+ return -1;
+}
+
+int xmm6260_sec_modem_link_get_hostwake_wait(int device_fd)
+{
+ int status;
+ int i;
+
+ if (device_fd < 0)
+ return -1;
+
+ i = 0;
+ for (i = 0; i < 10; i++) {
+ status = ioctl(device_fd, IOCTL_LINK_GET_HOSTWAKE, 0);
+ if (status)
+ return 0;
+
+ usleep(50000);
+ }
+
+ return -1;
+}
+
+int xmm6260_sec_modem_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+ struct ipc_header header;
+ void *buffer;
+ unsigned char *p;
+ int count;
+ int rc;
+
+ if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
+ return -1;
+
+ ipc_header_fill(&header, request);
+
+ buffer = malloc(header.length);
+
+ memcpy(buffer, &header, sizeof(struct ipc_header));
+ if (request->data != NULL && request->length > 0)
+ memcpy((void *) ((unsigned char *) buffer + sizeof(struct ipc_header)), request->data, request->length);
+
+ ipc_client_log_send(client, request, __func__);
+
+ p = (unsigned char *) buffer;
+
+ count = 0;
+ while (count < header.length) {
+ rc = client->handlers->write(client->handlers->transport_data, p, header.length - count);
+ if (rc <= 0) {
+ ipc_client_log(client, "Writing FMT data to the modem failed");
+ goto error;
+ }
+
+ count += rc;
+ p += rc;
+ }
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ if (buffer != NULL)
+ free(buffer);
+
+ return rc;
+}
+
+int xmm6260_sec_modem_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+ struct ipc_header *header;
+ void *buffer = NULL;
+ unsigned char *p;
+ int length;
+ int count;
+ int rc;
+
+ if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
+ return -1;
+
+ length = XMM6260_DATA_SIZE;
+ buffer = malloc(length);
+
+ rc = client->handlers->read(client->handlers->transport_data, buffer, length);
+ if (rc < (int) sizeof(struct ipc_header)) {
+ ipc_client_log(client, "Reading FMT header from the modem failed");
+ goto error;
+ }
+
+ header = (struct ipc_header *) buffer;
+
+ ipc_message_info_fill(header, response);
+
+ if (header->length > sizeof(struct ipc_header)) {
+ response->length = header->length - sizeof(struct ipc_header);
+ response->data = malloc(response->length);
+
+ p = (unsigned char *) response->data;
+
+ count = rc - sizeof(struct ipc_header);
+ if (count > 0) {
+ memcpy(p, (void *) ((unsigned char *) buffer + sizeof(struct ipc_header)), count);
+ p += count;
+ }
+
+ while (count < (int) response->length) {
+ rc = client->handlers->read(client->handlers->transport_data, p, response->length - count);
+ if (rc <= 0) {
+ ipc_client_log(client, "Reading FMT data from the modem failed");
+ goto error;
+ }
+
+ count += rc;
+ p += rc;
+ }
+ }
+
+ ipc_client_log_recv(client, response, __func__);
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ if (buffer != NULL)
+ free(buffer);
+
+ return rc;
+}
+
+int xmm6260_sec_modem_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+ struct rfs_hdr header;
+ void *buffer;
+ unsigned char *p;
+ int count;
+ int rc;
+
+
+ if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
+ return -1;
+
+ header.id = request->mseq;
+ header.cmd = request->index;
+ header.len = sizeof(struct rfs_hdr) + request->length;
+
+ buffer = malloc(header.len);
+
+ memcpy(buffer, &header, sizeof(struct rfs_hdr));
+ if (request->data != NULL && request->length > 0)
+ memcpy((void *) ((unsigned char *) buffer + sizeof(struct rfs_hdr)), request->data, request->length);
+
+ ipc_client_log_send(client, request, __func__);
+
+ p = (unsigned char *) buffer;
+
+ count = 0;
+ while (count < (int) header.len) {
+ rc = client->handlers->write(client->handlers->transport_data, p, header.len - count);
+ if (rc <= 0) {
+ ipc_client_log(client, "Writing RFS data to the modem failed");
+ goto error;
+ }
+
+ count += rc;
+ p += rc;
+ }
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ if (buffer != NULL)
+ free(buffer);
+
+ return rc;
+}
+
+int xmm6260_sec_modem_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+ struct rfs_hdr *header;
+ void *buffer = NULL;
+ unsigned char *p;
+ int length;
+ int count;
+ int rc;
+
+ if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
+ return -1;
+
+ length = XMM6260_DATA_SIZE;
+ buffer = malloc(length);
+
+ rc = client->handlers->read(client->handlers->transport_data, buffer, length);
+ if (rc < (int) sizeof(struct rfs_hdr)) {
+ ipc_client_log(client, "Reading RFS header from the modem failed");
+ goto error;
+ }
+
+ header = (struct rfs_hdr *) buffer;
+
+ memset(response, 0, sizeof(struct ipc_message_info));
+ response->aseq = header->id;
+ response->group = IPC_GROUP_RFS;
+ response->index = header->cmd;
+
+ if (header->len > sizeof(struct rfs_hdr)) {
+ response->length = header->len - sizeof(struct rfs_hdr);
+ response->data = malloc(response->length);
+
+ p = (unsigned char *) response->data;
+
+ count = rc - sizeof(struct rfs_hdr);
+ if (count > 0) {
+ memcpy(p, (void *) ((unsigned char *) buffer + sizeof(struct rfs_hdr)), count);
+ p += count;
+ }
+
+ while (count < (int) response->length) {
+ rc = client->handlers->read(client->handlers->transport_data, p, response->length - count);
+ if (rc <= 0) {
+ ipc_client_log(client, "Reading RFS data from the modem failed");
+ goto error;
+ }
+
+ count += rc;
+ p += rc;
+ }
+ }
+
+ ipc_client_log_recv(client, response, __func__);
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ if (buffer != NULL)
+ free(buffer);
+
+ return rc;
+}
+
+int xmm6260_sec_modem_ipc_open(int type)
+{
+ int fd;
+
+ switch (type) {
+ case IPC_CLIENT_TYPE_FMT:
+ fd = open(XMM6260_SEC_MODEM_IPC0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ break;
+ case IPC_CLIENT_TYPE_RFS:
+ fd = open(XMM6260_SEC_MODEM_RFS0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ break;
+ default:
+ return -1;
+ }
+
+ return fd;
+}
+
+int xmm6260_sec_modem_ipc_close(int fd)
+{
+ if (fd < 0)
+ return -1;
+
+ close(fd);
+
+ return 0;
+}
+
+int xmm6260_sec_modem_ipc_read(int fd, void *buffer, unsigned int length)
+{
+ int rc;
+
+ if (fd < 0 || buffer == NULL || length <= 0)
+ return -1;
+
+ rc = read(fd, buffer, length);
+ return rc;
+}
+
+int xmm6260_sec_modem_ipc_write(int fd, void *buffer, unsigned int length)
+{
+ int rc;
+
+ if (fd < 0 || buffer == NULL || length <= 0)
+ return -1;
+
+ rc = write(fd, buffer, length);
+ return rc;
+}
+
+int xmm6260_sec_modem_ipc_poll(int fd, struct timeval *timeout)
+{
+ fd_set fds;
+ int rc;
+ int status;
+
+ if (fd < 0)
+ return -1;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ rc = select(fd + 1, &fds, NULL, NULL, timeout);
+ if (FD_ISSET(fd, &fds)) {
+ status = ioctl(fd, IOCTL_MODEM_STATUS, 0);
+ if (status != STATE_ONLINE && status != STATE_BOOTING)
+ return 0;
+ }
+
+ return rc;
+}
+
+char *xmm6260_sec_modem_ipc_gprs_get_iface(int cid)
+{
+ char *iface = NULL;
+
+ if (cid > XMM6260_SEC_MODEM_GPRS_IFACE_COUNT)
+ return NULL;
+
+ asprintf(&iface, "%s%d", XMM6260_SEC_MODEM_GPRS_IFACE_PREFIX, cid - 1);
+
+ return iface;
+}
+
+int xmm6260_sec_modem_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
+{
+ if (capabilities == NULL)
+ return -1;
+
+ capabilities->port_list = 0;
+ capabilities->cid_max = XMM6260_SEC_MODEM_GPRS_IFACE_COUNT;
+
+ return 0;
+}
+
+// vim:ts=4:sw=4:expandtab