SRS: srs-client library, proper structures for protocol data
authorPaul Kocialkowski <contact@paulk.fr>
Thu, 7 Mar 2013 13:41:30 +0000 (14:41 +0100)
committerPaul Kocialkowski <contact@paulk.fr>
Thu, 7 Mar 2013 13:41:30 +0000 (14:41 +0100)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
Android.mk
include/samsung-ril-socket.h
srs-client/include/srs-client.h [new file with mode: 0644]
srs-client/srs-client.c [new file with mode: 0644]
srs.c

index 78e9a5f..6e8539e 100644 (file)
@@ -17,7 +17,7 @@
 # along with samsung-ril.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
@@ -113,3 +113,19 @@ else
        LOCAL_MODULE:= samsung-ril
        include $(BUILD_EXECUTABLE)
 endif
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := srs-client/srs-client.c
+
+LOCAL_C_INCLUDES := \
+       $(LOCAL_PATH)/include \
+       $(LOCAL_PATH)/srs-client/include \
+
+LOCAL_SHARED_LIBRARIES := liblog libcutils
+
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libsrs-client
+
+include $(BUILD_SHARED_LIBRARY)
index c7b5e0d..59be2f2 100644 (file)
 
 #define SRS_CONTROL_CAFFE              0xCAFFE
 
+struct srs_header {
+       unsigned int length;
+       unsigned char group;
+       unsigned char index;
+} __attribute__((__packed__));
+
+struct srs_message {
+       unsigned short command;
+       int length;
+       void *data;
+};
+
+
 enum srs_snd_type {
        SRS_SND_TYPE_VOICE,
        SRS_SND_TYPE_SPEAKER,
@@ -66,16 +79,16 @@ struct srs_snd_call_volume {
        int volume;
 } __attribute__((__packed__));
 
-struct srs_header {
-       unsigned int length;
-       unsigned char group;
-       unsigned char index;
+struct srs_snd_call_audio_path {
+       enum srs_snd_path path;
 } __attribute__((__packed__));
 
-struct srs_message {
-       unsigned short command;
-       int data_len;
-       void *data;
+struct srs_snd_call_clock_sync {
+       unsigned char sync;
+} __attribute__((__packed__));
+
+struct srs_control_ping {
+       int caffe;
 } __attribute__((__packed__));
 
 #endif
diff --git a/srs-client/include/srs-client.h b/srs-client/include/srs-client.h
new file mode 100644 (file)
index 0000000..b98e5e9
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * This file is part of samsung-ril.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@oaulk.fr>
+ *
+ * samsung-ril 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * samsung-ril 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 samsung-ril.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <pthread.h>
+
+#include <samsung-ril-socket.h>
+
+#ifndef _SRS_CLIENT_H_
+#define _SRS_CLIENT_H_
+
+#define SRS_CLIENT_TIMEOUT     500000
+
+#define SRS_CLIENT_LOCK(client) pthread_mutex_lock(&(client->mutex))
+#define SRS_CLIENT_UNLOCK(client) pthread_mutex_unlock(&(client->mutex))
+
+typedef void (*srs_client_thread_cb)(struct srs_message *message);
+
+struct srs_client {
+       int fd;
+
+       pthread_mutex_t mutex;
+       pthread_t thread;
+       int thread_run;
+
+       srs_client_thread_cb thread_cb;
+};
+
+int srs_client_recv_message(struct srs_client *client, struct srs_message *message);
+int srs_client_send_message(struct srs_client *client, struct srs_message *message);
+int srs_client_send(struct srs_client *client, unsigned short command, void *data, int length);
+
+int srs_client_open(struct srs_client *client);
+int srs_client_close(struct srs_client *client);
+int srs_client_create(struct srs_client **client_p);
+int srs_client_destroy(struct srs_client *client);
+
+int srs_client_thread_start(struct srs_client *client,
+       srs_client_thread_cb cb);
+int srs_client_thread_stop(struct srs_client *client);
+
+int srs_client_ping(struct srs_client *client);
+
+#endif
diff --git a/srs-client/srs-client.c b/srs-client/srs-client.c
new file mode 100644 (file)
index 0000000..dd408eb
--- /dev/null
@@ -0,0 +1,365 @@
+/**
+ * This file is part of samsung-ril.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@oaulk.fr>
+ *
+ * samsung-ril 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * samsung-ril 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 samsung-ril.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/select.h>
+
+#include <signal.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <cutils/sockets.h>
+
+#include <telephony/ril.h>
+
+#include <samsung-ril-socket.h>
+#include <srs-client.h>
+
+/*
+ * SRS Client fops
+ */
+
+int srs_client_recv_message(struct srs_client *client, struct srs_message *message)
+{
+       struct srs_header *header_p;
+       struct srs_header header;
+       void *data = NULL;
+       int length = 0;
+
+       struct timeval timeout;
+       fd_set fds;
+       int rc;
+
+       if (client == NULL || message == NULL || client->fd < 0)
+               return -EINVAL;
+
+       memset(message, 0, sizeof(struct srs_message));
+       memset(&header, 0, sizeof(header));
+
+       timeout.tv_sec = (SRS_CLIENT_TIMEOUT - SRS_CLIENT_TIMEOUT % 1000000) / 1000000;
+       timeout.tv_usec = SRS_CLIENT_TIMEOUT % 1000000;
+
+       FD_ZERO(&fds);
+       FD_SET(client->fd, &fds);
+
+       rc = select(client->fd + 1, &fds, NULL, NULL, &timeout);
+       if (rc == 0) {
+               rc = 0;
+               goto done;
+       } else if (rc < 0 || !FD_ISSET(client->fd, &fds))
+               goto error;
+
+       SRS_CLIENT_LOCK(client);
+       rc = read(client->fd, &header, sizeof(header));
+       SRS_CLIENT_UNLOCK(client);
+
+       if (rc != sizeof(header))
+               goto error;
+
+       header_p = &header;
+       message->command = SRS_COMMAND(header_p);
+
+       length = header.length - sizeof(header);
+       if (length > 0) {
+               data = calloc(1, length);
+               if (data == NULL)
+                       goto error;
+
+               FD_ZERO(&fds);
+               FD_SET(client->fd, &fds);
+
+               rc = select(client->fd + 1, &fds, NULL, NULL, &timeout);
+               if (rc <= 0 || !FD_ISSET(client->fd, &fds))
+                       goto error;
+
+               SRS_CLIENT_LOCK(client);
+               rc = read(client->fd, data, length);
+               SRS_CLIENT_UNLOCK(client);
+
+               if (rc != length)
+                       goto error;
+
+               message->data = data;
+               message->length = length;
+       }
+
+       rc = header.length;
+       goto done;
+
+error:
+       rc = -1;
+
+       if (data != NULL)
+               free(data);
+
+done:
+       return rc;
+}
+
+int srs_client_send_message(struct srs_client *client, struct srs_message *message)
+{
+       struct srs_header header;
+       unsigned char *p = NULL;
+       void *data = NULL;
+       int length = 0;
+
+       struct timeval timeout;
+       fd_set fds;
+       int rc;
+
+       if (client == NULL || message == NULL || client->fd < 0)
+               return -EINVAL;
+
+       memset(&header, 0, sizeof(header));
+       header.length = message->length + sizeof(header);
+       header.group = SRS_GROUP(message->command);
+       header.index = SRS_INDEX(message->command);
+
+       length = header.length;
+       data = calloc(1, length);
+       if (data == NULL)
+               goto error;
+
+       p = (unsigned char *) data;
+       memcpy(p, &header, sizeof(header));
+       p += sizeof(header);
+       if (message->data != NULL && message->length > 0) {
+               memcpy(p, message->data, message->length);
+               p += message->length;
+       }
+
+       timeout.tv_sec = (SRS_CLIENT_TIMEOUT - SRS_CLIENT_TIMEOUT % 1000000) / 1000000;
+       timeout.tv_usec = SRS_CLIENT_TIMEOUT % 1000000;
+
+       FD_ZERO(&fds);
+       FD_SET(client->fd, &fds);
+
+       rc = select(client->fd + 1, NULL, &fds, NULL, &timeout);
+       if (rc <= 0 || !FD_ISSET(client->fd, &fds))
+               goto error;
+
+       SRS_CLIENT_LOCK(client);
+       rc = write(client->fd, data, length);
+       SRS_CLIENT_UNLOCK(client);
+
+       if (rc != length)
+               goto error;
+
+       rc = length;
+       goto done;
+
+error:
+       rc = -1;
+
+done:
+       if (data != NULL)
+               free(data);
+
+       return rc;
+}
+
+int srs_client_send(struct srs_client *client, unsigned short command, void *data, int length)
+{
+       struct srs_message message;
+
+       memset(&message, 0, sizeof(message));
+       message.command = command;
+       message.data = data;
+       message.length = length;
+
+       return srs_client_send_message(client, &message);
+}
+
+int srs_client_open(struct srs_client *client)
+{
+       int fd;
+
+       if (client == NULL)
+               return -EINVAL;
+#if RIL_VERSION >= 6
+       fd = socket_local_client(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+#else
+       fd = socket_local_client(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+#endif
+       if (fd < 0) {
+               client->fd = -1;
+               return -1;
+       }
+
+       client->fd = fd;
+       return 0;
+}
+
+int srs_client_close(struct srs_client *client)
+{
+       if (client == NULL || client->fd < 0)
+               return -EINVAL;
+
+       close(client->fd);
+       client->fd = -1;
+
+       return 0;
+}
+
+int srs_client_create(struct srs_client **client_p)
+{
+       struct srs_client *client;
+
+       if (client_p == NULL)
+               return -EINVAL;
+
+       client = calloc(1, sizeof(struct srs_client));
+       if (client == NULL) {
+               *client_p = NULL;
+               return -1;
+       }
+
+       client->fd = -1;
+       pthread_mutex_init(&(client->mutex), NULL);
+
+       *client_p = client;
+
+       return 0;
+}
+
+int srs_client_destroy(struct srs_client *client)
+{
+       if (client == NULL)
+               return -EINVAL;
+
+       pthread_mutex_destroy(&(client->mutex));
+
+       free(client);
+
+       return 0;
+}
+
+/*
+ * SRS Client thread
+ */
+
+void *srs_client_thread(void *data)
+{
+       struct srs_message message;
+       struct srs_client *client;
+       int rc;
+
+       if (data == NULL)
+               return NULL;
+
+       client = (struct srs_client *) data;
+
+       if (client->thread_cb == NULL)
+               goto done;
+
+       while (client->thread_run) {
+               rc = srs_client_recv_message(client, &message);
+               if (rc < 0)
+                       goto done;
+
+               client->thread_cb(&message);
+       }
+
+done:
+       client->thread_run = 0;
+
+       return NULL;
+}
+
+int srs_client_thread_start(struct srs_client *client,
+       srs_client_thread_cb cb)
+{
+       pthread_attr_t attr;
+       int rc;
+
+       if (client == NULL || cb == NULL)
+               return -EINVAL;
+
+       client->thread_cb = cb;
+       client->thread_run = 1;
+
+       pthread_attr_init(&attr);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+       rc = pthread_create(&(client->thread), &attr, srs_client_thread, (void *) client);
+       if (rc != 0)
+               return -1;
+
+       return 0;
+}
+
+int srs_client_thread_stop(struct srs_client *client)
+{
+       if (client == NULL)
+               return -EINVAL;
+
+       client->thread_run = 0;
+
+       return 0;
+}
+
+/*
+ * SRS Client inline
+ */
+
+int srs_client_ping(struct srs_client *client)
+{
+       struct srs_message message;
+       struct srs_control_ping ping;
+       struct srs_control_ping *ping_p;
+       int rc;
+
+       if (client == NULL)
+               return -1;
+
+       memset(&message, 0, sizeof(message));
+
+       ping.caffe = SRS_CONTROL_CAFFE;
+       rc = srs_client_send(client, SRS_CONTROL_PING, &ping, sizeof(ping));
+       if (rc < 0)
+               goto error;
+
+       rc = srs_client_recv_message(client, &message);
+       if (rc < 0 || message.length <= 0 || message.data == NULL)
+               goto error;
+
+       ping_p = (struct srs_control_ping *) message.data;
+       if (ping_p->caffe != SRS_CONTROL_CAFFE)
+               goto error;
+
+       rc = 0;
+       goto done;
+
+error:
+       rc = -1;
+
+done:
+       if (message.data != NULL)
+               free(message.data);
+
+       return rc;
+}
diff --git a/srs.c b/srs.c
index 38b74d7..3a32b5a 100644 (file)
--- a/srs.c
+++ b/srs.c
@@ -195,7 +195,7 @@ int srs_client_send_message(struct srs_client_data *client_data, struct srs_mess
                return -1;
 
        memset(&header, 0, sizeof(header));
-       header.length = message->data_len + sizeof(header);
+       header.length = message->length + sizeof(header);
        header.group = SRS_GROUP(message->command);
        header.index = SRS_INDEX(message->command);
 
@@ -204,7 +204,7 @@ int srs_client_send_message(struct srs_client_data *client_data, struct srs_mess
                return -1;
 
        memcpy(data, &header, sizeof(header));
-       memcpy((void *) ((char *) data + sizeof(header)), message->data, message->data_len);
+       memcpy((void *) ((char *) data + sizeof(header)), message->data, message->length);
 
        memset(&timeout, 0, sizeof(timeout));
        timeout.tv_usec = 300;
@@ -248,7 +248,7 @@ int srs_client_send(struct srs_client_data *client_data, unsigned short command,
        memset(&message, 0, sizeof(message));
        message.command = command;
        message.data = data;
-       message.data_len = length;
+       message.length = length;
 
        RIL_CLIENT_LOCK(client_data->client);
        rc = srs_client_send_message(client_data, &message);
@@ -277,7 +277,7 @@ int srs_send(unsigned short command, void *data, int length)
 
        client_data = (struct srs_client_data *) ril_data.srs_client->data;
 
-       LOGD("SEND SRS: fd=%d command=%d data_len=%d", client_data->client_fd, command, length);
+       LOGD("SEND SRS: fd=%d command=%d length=%d", client_data->client_fd, command, length);
        if (data != NULL && length > 0) {
                LOGD("==== SRS DATA DUMP ====");
                hex_dump(data, length);
@@ -329,10 +329,10 @@ int srs_client_recv(struct srs_client_data *client_data, struct srs_message *mes
 
        memset(message, 0, sizeof(struct srs_message));
        message->command = SRS_COMMAND(header);
-       message->data_len = header->length - sizeof(struct srs_header);
-       if (message->data_len > 0) {
-               message->data = calloc(1, message->data_len);
-               memcpy(message->data, (void *) ((char *) data + sizeof(struct srs_header)), message->data_len);
+       message->length = header->length - sizeof(struct srs_header);
+       if (message->length > 0) {
+               message->data = calloc(1, message->length);
+               memcpy(message->data, (void *) ((char *) data + sizeof(struct srs_header)), message->length);
        } else {
                message->data = NULL;
        }
@@ -349,7 +349,7 @@ void srs_control_ping(struct srs_message *message)
 {
        int caffe;
 
-       if (message == NULL || message->data == NULL || message->data_len < (int) sizeof(int))
+       if (message == NULL || message->data == NULL || message->length < (int) sizeof(int))
                return;
 
        caffe=*((int *) message->data);
@@ -430,10 +430,10 @@ void *srs_client_read_loop(void *data)
                        }
                        RIL_CLIENT_UNLOCK(client_data->client);
 
-                       LOGD("RECV SRS: fd=%d command=%d data_len=%d", fd, message.command, message.data_len);
-                       if (message.data != NULL && message.data_len > 0) {
+                       LOGD("RECV SRS: fd=%d command=%d length=%d", fd, message.command, message.length);
+                       if (message.data != NULL && message.length > 0) {
                                LOGD("==== SRS DATA DUMP ====");
-                               hex_dump(message.data, message.data_len);
+                               hex_dump(message.data, message.length);
                                LOGD("=======================");
                        }