GTA04: Added device files with working transport handlers
authorPaul Kocialkowski <contact@paulk.fr>
Tue, 17 Jul 2012 22:20:27 +0000 (00:20 +0200)
committerPaul Kocialkowski <contact@paulk.fr>
Wed, 18 Jul 2012 14:34:06 +0000 (16:34 +0200)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
Android.mk
device/gta04/gta04.c [new file with mode: 0644]
device/gta04/gta04.h [new file with mode: 0644]

index 27684ab..b664d34 100644 (file)
@@ -21,6 +21,11 @@ hayes_ril_files := \
        hayes-ril.c \
        device.c
 
+ifeq ($(TARGET_DEVICE),gta04)
+       hayes_ril_device_files := device/gta04/gta04.c
+       LOCAL_C_INCLUDES += $(LOCAL_PATH)/device/gta04/
+endif
+
 ifeq ($(TARGET_DEVICE),passion)
        hayes_ril_device_files := device/passion/passion.c
        LOCAL_C_INCLUDES += $(LOCAL_PATH)/device/passion/
diff --git a/device/gta04/gta04.c b/device/gta04/gta04.c
new file mode 100644 (file)
index 0000000..c988a34
--- /dev/null
@@ -0,0 +1,405 @@
+/**
+ * This file is part of hayes-ril.
+ *
+ * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#define LOG_TAG "RIL-DEV"
+#include <utils/Log.h>
+
+#include "gta04.h"
+#include <hayes-ril.h>
+
+int gta04_power_boot(void *sdata)
+{
+       struct stat tty_node_stat;
+       char *tty_node;
+       int rc;
+       int i;
+
+       for(i=0 ; i < TTY_NODE_MAX ; i++) {
+               asprintf(&tty_node, "%s/%s%d", TTY_DEV_BASE, TTY_NODE_BASE, i);
+
+               rc = stat(tty_node, &tty_node_stat);
+               if(rc < 0) {
+                       free(tty_node);
+                       return -1;
+               }
+
+               free(tty_node);
+       }
+
+       return 0;
+}
+
+int gta04_transport_sdata_create(void **sdata)
+{
+       struct gta04_transport_data *transport_data = NULL;
+
+       transport_data = malloc(sizeof(struct gta04_transport_data));
+       memset(transport_data, 0, sizeof(struct gta04_transport_data));
+
+       *sdata = (void *) transport_data;
+
+       return 0;
+}
+
+int gta04_transport_sdata_destroy(void *sdata)
+{
+       if(sdata == NULL)
+               return 0;
+
+       free(sdata);
+
+       return 0;
+}
+
+int gta04_transport_find_node(char **tty_node, char *name)
+{
+       char *tty_sysfs_node = NULL;
+       char *buf = NULL;
+       int name_length;
+       int fd = -1;
+       int i;
+
+       if(tty_node == NULL || name == NULL)
+               return -1;
+
+       name_length = strlen(name);
+       buf = calloc(1, name_length);
+
+       for(i=0 ; i < TTY_NODE_MAX ; i++) {
+               asprintf(&tty_sysfs_node, "%s/%s%d/%s",
+                       TTY_SYSFS_BASE, TTY_NODE_BASE, i, TTY_HSOTYPE);
+
+               fd = open(tty_sysfs_node, O_RDONLY);
+               if(fd < 0) {
+                       free(tty_sysfs_node);
+                       continue;
+               }
+
+               read(fd, buf, name_length);
+               if(strncmp(name, buf, name_length) == 0) {
+                       asprintf(tty_node, "%s/%s%d", TTY_DEV_BASE, TTY_NODE_BASE, i);
+
+                       free(tty_sysfs_node);
+                       return 0;
+               } else {
+                       free(tty_sysfs_node);
+               }
+       }
+
+       *tty_node = NULL;
+
+       return -1;
+}
+
+int gta04_transport_open(void *sdata)
+{
+       struct gta04_transport_data *transport_data = NULL;
+       struct termios term;
+       char *dev_node = NULL;
+       int fd = -1;
+       int rc = -1;
+
+       if(sdata == NULL)
+               return -1;
+
+       transport_data = (struct gta04_transport_data *) sdata;
+
+       // Open Modem node
+       if(transport_data->modem_fd <= 0) {
+               rc = gta04_transport_find_node(&dev_node, "Modem");
+               if(rc < 0) {
+                       LOGE("Unable to find Modem node, aborting!");
+                       goto failure;
+               }
+
+               fd = open(dev_node, O_RDWR | O_NOCTTY | O_NDELAY);
+               if(fd < 0) {
+                       LOGE("Unable to open Modem node, aborting!");
+                       goto failure;
+               }
+
+               rc = tcgetattr(fd, &term);
+               if(rc < 0) {
+                       LOGE("Unable to get Modem note attrs, aborting!");
+                       goto failure;
+               }
+
+               term.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
+               cfsetispeed(&term, B115200);
+               cfsetospeed(&term, B115200);
+
+               rc = tcsetattr(fd, TCSANOW, &term);
+               if(rc < 0) {
+                       LOGE("Unable to set Modem note attrs, aborting!");
+                       goto failure;
+               }
+
+               LOGD("Opened Modem node");
+               transport_data->modem_fd = fd;
+       }
+
+       // Open Application node
+       if(transport_data->application_fd <= 0) {
+               rc = gta04_transport_find_node(&dev_node, "Application");
+               if(rc < 0) {
+                       LOGE("Unable to find Application node, aborting!");
+                       goto failure;
+               }
+
+               fd = open(dev_node, O_RDWR | O_NOCTTY | O_NDELAY);
+               if(fd < 0) {
+                       LOGE("Unable to open Application node, aborting!");
+                       goto failure;
+               }
+
+               rc = tcgetattr(fd, &term);
+               if(rc < 0) {
+                       LOGE("Unable to get Application note attrs, aborting!");
+                       goto failure;
+               }
+
+               term.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
+               cfsetispeed(&term, B115200);
+               cfsetospeed(&term, B115200);
+
+               rc = tcsetattr(fd, TCSANOW, &term);
+               if(rc < 0) {
+                       LOGE("Unable to set Application note attrs, aborting!");
+                       goto failure;
+               }
+
+               LOGD("Opened Application node");
+               transport_data->application_fd = fd;
+       }
+
+       return 0;
+
+failure:
+       if(dev_node != NULL)
+               free(dev_node);
+
+       return -1;
+}
+
+int gta04_transport_close(void *sdata)
+{
+       struct gta04_transport_data *transport_data = NULL;
+
+       if(sdata == NULL)
+               return -1;
+
+       transport_data = (struct gta04_transport_data *) sdata;
+
+       if(transport_data->modem_fd > 0)
+               close(transport_data->modem_fd);
+
+       if(transport_data->application_fd > 0)
+               close(transport_data->application_fd);
+
+       return 0;
+}
+
+int gta04_transport_send(void *sdata, void *data, int length)
+{
+       struct gta04_transport_data *transport_data = NULL;
+
+       // Written data count
+       int wc;
+       // Min count
+       int mc;
+       // Total written data count
+       int tc = 0;
+
+       if(sdata == NULL || data == NULL || length <= 0)
+               return -1;
+
+       transport_data = (struct gta04_transport_data *) sdata;
+
+       if(transport_data->modem_fd < 0)
+               return -1;
+
+       mc = length;
+       while(mc > 0) {
+               // Outgoing AT data must be written to the Modem node apparently
+               wc = write(transport_data->modem_fd, data + (length - mc), mc);
+               if(wc < 0)
+                       return -1;
+
+               tc += wc;
+               mc -= wc;
+       }
+
+       return tc;
+}
+
+int gta04_transport_recv(void *sdata, void **data, int length)
+{
+       struct gta04_transport_data *transport_data = NULL;
+       char *buffer;
+       int fd;
+
+       // Read data count
+       int rc;
+       // Min count
+       int mc;
+       // Total read data count
+       int tc = 0;
+
+       if(sdata == NULL)
+               return -1;
+
+       transport_data = (struct gta04_transport_data *) sdata;
+
+       if(transport_data->modem_fd < 0)
+               return -1;
+       if(transport_data->application_fd < 0)
+               return -1;
+
+       if(transport_data->modem_ac > 0) {
+               fd = transport_data->modem_fd;
+               mc = transport_data->modem_ac;
+       } else if(transport_data->application_ac > 0) {
+               fd = transport_data->application_fd;
+               mc = transport_data->application_ac;
+       }
+
+       if(fd < 0)
+               return -1;
+
+       if(length == 1 && mc == 1) {
+               // Read an unknown number of bytes
+
+               buffer = (char *) calloc(1, mc);
+
+               rc = read(fd, (void *) buffer, RECV_BYTES_MAX);
+               if(rc < 0) {
+                       free(buffer);
+                       return -1;
+               }
+
+               tc = rc;
+       } else {
+               // Read the exact number of bytes
+
+               buffer = (char *) calloc(1, mc);
+
+               while(mc > 0) {
+                       rc = read(fd, (void *) (buffer + tc), mc - tc);
+                       if(rc < 0) {
+                               free(buffer);
+                               return -1;
+                       }
+
+                       tc += rc;
+                       mc -= rc;
+               }
+
+               if(tc > length)
+                       tc = length;
+       }
+
+       *data = (void *) buffer;
+
+       if(transport_data->modem_ac > 0)
+               transport_data->modem_ac = 0;
+       else if(transport_data->application_ac > 0)
+               transport_data->application_ac = 0;
+
+       return tc;
+}
+
+int gta04_transport_recv_poll(void *sdata)
+{
+       struct gta04_transport_data *transport_data = NULL;
+       fd_set fds;
+
+       if(sdata == NULL)
+               return -1;
+
+       transport_data = (struct gta04_transport_data *) sdata;
+
+       if(transport_data->modem_fd < 0)
+               return -1;
+       if(transport_data->application_fd < 0)
+               return -1;
+
+       FD_ZERO(&fds);
+       FD_SET(transport_data->modem_fd, &fds);
+       FD_SET(transport_data->application_fd, &fds);
+
+       select(FD_SETSIZE, &fds, NULL, NULL, NULL);
+
+       // Process one at a time
+       if(FD_ISSET(transport_data->modem_fd, &fds)) {
+               transport_data->modem_ac = 1;
+       } else if(FD_ISSET(transport_data->application_fd, &fds)) {
+               transport_data->application_ac = 1;
+       }
+
+       return 1;
+}
+
+int gta04_dummy(void *sdata)
+{
+       return 0;
+}
+
+struct ril_device_power_handlers gta04_power_handlers = {
+       .sdata = NULL,
+       .sdata_create = gta04_dummy,
+       .sdata_destroy = gta04_dummy,
+       .power_on = gta04_dummy,
+       .power_off = gta04_dummy,
+       .suspend = gta04_dummy,
+       .resume = gta04_dummy,
+       .boot = gta04_power_boot,
+};
+
+struct ril_device_transport_handlers gta04_transport_handlers = {
+       .sdata = NULL,
+       .sdata_create = gta04_transport_sdata_create,
+       .sdata_destroy = gta04_transport_sdata_destroy,
+       .open = gta04_transport_open,
+       .close = gta04_transport_close,
+       .send = gta04_transport_send,
+       .recv = gta04_transport_recv,
+       .recv_poll = gta04_transport_recv_poll,
+};
+
+struct ril_device_handlers gta04_handlers = {
+       .power = &gta04_power_handlers,
+       .transport = &gta04_transport_handlers,
+};
+
+struct ril_device gta04_device = {
+       .name = "Goldelico GTA04",
+       .type = DEV_GSM,
+       .sdata = NULL,
+       .handlers = &gta04_handlers,
+};
+
+void ril_device_register(struct ril_device **ril_device_p)
+{
+       *ril_device_p = &gta04_device;
+}
diff --git a/device/gta04/gta04.h b/device/gta04/gta04.h
new file mode 100644 (file)
index 0000000..3da0b9c
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * This file is part of hayes-ril.
+ *
+ * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hayes-ril.h>
+
+#ifndef _HAYES_RIL_GTA04_H
+#define _HAYES_RIL_GTA04_H
+
+#define TTY_SYSFS_BASE "/sys/class/tty"
+#define TTY_DEV_BASE   "/dev"
+#define TTY_HSOTYPE    "hsotype"
+#define TTY_NODE_BASE  "ttyHS"
+#define TTY_NODE_MAX   6
+
+#define RECV_BYTES_MAX 0x1000
+
+struct gta04_transport_data {
+       // File descriptors
+       int modem_fd;
+       int application_fd;
+
+       // Available data counts
+       int modem_ac;
+       int application_ac;
+};
+
+#endif