diff options
-rw-r--r-- | Android.mk | 18 | ||||
-rw-r--r-- | include/samsung-ril-socket.h | 29 | ||||
-rw-r--r-- | srs-client/include/srs-client.h | 60 | ||||
-rw-r--r-- | srs-client/srs-client.c | 365 | ||||
-rw-r--r-- | srs.c | 24 |
5 files changed, 475 insertions, 21 deletions
@@ -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) diff --git a/include/samsung-ril-socket.h b/include/samsung-ril-socket.h index c7b5e0d..59be2f2 100644 --- a/include/samsung-ril-socket.h +++ b/include/samsung-ril-socket.h @@ -40,6 +40,19 @@ #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 index 0000000..b98e5e9 --- /dev/null +++ b/srs-client/include/srs-client.h @@ -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 index 0000000..dd408eb --- /dev/null +++ b/srs-client/srs-client.c @@ -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; +} @@ -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("======================="); } |