diff options
author | Alexander Tarasikov <alexander.tarasikov@gmail.com> | 2012-08-27 01:05:35 +0400 |
---|---|---|
committer | Alexander Tarasikov <alexander.tarasikov@gmail.com> | 2012-08-27 01:05:35 +0400 |
commit | 4e7ae4c51022ba448c3bb6f9fd92d290b609c696 (patch) | |
tree | 12eefa14b9a5bdfc06c9e63d51d233b017279ca2 | |
parent | 1fbf7af4be21dd47ea9a39582d3909a742bbbb5d (diff) | |
download | hardware_ril_samsung-ril-4e7ae4c51022ba448c3bb6f9fd92d290b609c696.zip hardware_ril_samsung-ril-4e7ae4c51022ba448c3bb6f9fd92d290b609c696.tar.gz hardware_ril_samsung-ril-4e7ae4c51022ba448c3bb6f9fd92d290b609c696.tar.bz2 |
Rework SRS to support multiple clients
This fixes deadlocks on Galaxy Nexus (Tuna)
when GPS/NFC libraries open the socket thus preventing
in-call audio from functioning
-rw-r--r-- | samsung-ril.c | 4 | ||||
-rw-r--r-- | samsung-ril.h | 2 | ||||
-rw-r--r-- | srs.c | 224 | ||||
-rw-r--r-- | srs.h | 16 |
4 files changed, 113 insertions, 133 deletions
diff --git a/samsung-ril.c b/samsung-ril.c index 4b9b0ff..f3332be 100644 --- a/samsung-ril.c +++ b/samsung-ril.c @@ -309,12 +309,12 @@ void ipc_rfs_dispatch(struct ipc_message_info *info) ril_unlock(); } -void srs_dispatch(struct srs_message *message) +void srs_dispatch(int fd, struct srs_message *message) { ril_lock(); switch(message->command) { case SRS_CONTROL_PING: - srs_control_ping(message); + srs_control_ping(fd, message); break; case SRS_SND_SET_CALL_CLOCK_SYNC: srs_snd_set_call_clock_sync(message); diff --git a/samsung-ril.h b/samsung-ril.h index 493fb43..45e0e44 100644 --- a/samsung-ril.h +++ b/samsung-ril.h @@ -200,7 +200,7 @@ int ril_modem_check(void); void ipc_fmt_dispatch(struct ipc_message_info *info); void ipc_rfs_dispatch(struct ipc_message_info *info); -void srs_dispatch(struct srs_message *message); +void srs_dispatch(int fd, struct srs_message *message); /* GEN */ @@ -34,27 +34,7 @@ #include "samsung-ril.h" #include "util.h" -struct srs_server *srs_server_new(void) -{ - struct srs_server *srs_server; - - srs_server = malloc(sizeof(struct srs_server)); - memset(srs_server, 0, sizeof(struct srs_server)); - srs_server->server_fd = -1; - srs_server->client_fd = -1; - - return srs_server; -} - -void srs_server_free(struct srs_server *srs_server) -{ - if(srs_server == NULL) - return; - - free(srs_server); -} - -int srs_server_send_message(struct srs_server *srs_server, struct srs_message *message) +static int srs_server_send_message(int client_fd, struct srs_message *message) { fd_set fds; @@ -73,41 +53,39 @@ int srs_server_send_message(struct srs_server *srs_server, struct srs_message *m message->data, message->data_len); FD_ZERO(&fds); - FD_SET(srs_server->client_fd, &fds); + FD_SET(client_fd, &fds); select(FD_SETSIZE, NULL, &fds, NULL, NULL); - write(srs_server->client_fd, data, header.length); + write(client_fd, data, header.length); free(data); return 0; } -int srs_server_send(unsigned short command, void *data, int data_len) +static int srs_server_send(int fd, unsigned short command, void *data, + int data_len) { - struct srs_server *srs_server; struct srs_message message; int rc; - srs_server = (struct srs_server *) (srs_client->object); - message.command = command; message.data = data; message.data_len = data_len; - rc = srs_server_send_message(srs_server, &message); + rc = srs_server_send_message(fd, &message); return rc; } -int srs_server_recv(struct srs_server *srs_server, struct srs_message *message) +static int srs_server_recv(int client_fd, struct srs_message *message) { void *raw_data = malloc(SRS_DATA_MAX_SIZE); struct srs_header *header; int rc; - rc = read(srs_server->client_fd, raw_data, SRS_DATA_MAX_SIZE); + rc = read(client_fd, raw_data, SRS_DATA_MAX_SIZE); if(rc < (int)sizeof(struct srs_header)) { return -1; } @@ -126,31 +104,7 @@ int srs_server_recv(struct srs_server *srs_server, struct srs_message *message) return 0; } -int srs_server_accept(struct srs_server *srs_server) -{ - int client_fd = -1; - struct sockaddr_un client_addr; - int client_addr_len; - - if(srs_server->client_fd > 0) { - return 0; - } - - client_fd = accept(srs_server->server_fd, - (struct sockaddr*) &client_addr, &client_addr_len); - - if(client_fd > 0) { - srs_server->client_fd = client_fd; - srs_server->client_addr = client_addr; - srs_server->client_addr_len = client_addr_len; - - return 0; - } - - return -1; -} - -void srs_control_ping(struct srs_message *message) +void srs_control_ping(int fd, struct srs_message *message) { int caffe; @@ -160,11 +114,11 @@ void srs_control_ping(struct srs_message *message) caffe=*((int *) message->data); if(caffe == SRS_CONTROL_CAFFE) { - srs_server_send(SRS_CONTROL_PING, &caffe, sizeof(caffe)); + srs_server_send(fd, SRS_CONTROL_PING, &caffe, sizeof(caffe)); } } -int srs_server_open(struct srs_server *srs_server) +static int srs_server_open(void) { int server_fd = -1; @@ -174,27 +128,69 @@ int srs_server_open(struct srs_server *srs_server) unlink(SRS_SOCKET_NAME); server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); - if(server_fd > 0) + if(server_fd >= 0) break; t++; } - - if(server_fd < 0) - return -1; - - srs_server->server_fd = server_fd; - return 0; + return server_fd; } -int srs_read_loop(struct ril_client *client) +static void* srs_process_client(void *pfd) { - struct srs_server *srs_server; struct srs_message srs_message; fd_set fds; + int client_fd = -1; + if (!pfd) { + LOGE("SRS client data is NULL"); + goto fail; + } + + client_fd = ((int*)pfd)[0]; + + while (1) { + if (client_fd < 0) + break; + + FD_ZERO(&fds); + FD_SET(client_fd, &fds); + + select(FD_SETSIZE, &fds, NULL, NULL, NULL); + + if (FD_ISSET(client_fd, &fds)) { + if (srs_server_recv(client_fd, &srs_message) < 0) { + LOGE("SRS recv failed, aborting!"); + break; + } + + LOGD("SRS recv: command=%d data_len=%d", + srs_message.command, srs_message.data_len); + hex_dump(srs_message.data, srs_message.data_len); + + srs_dispatch(client_fd, &srs_message); + + if (srs_message.data != NULL) + free(srs_message.data); + } + } + +fail: + if(client_fd >= 0) { + close(client_fd); + } + + LOGE("SRS server client ended!"); + return NULL; +} + +static int srs_read_loop(struct ril_client *client) +{ int rc; + struct sockaddr_un client_addr; + int client_addr_len; + if(client == NULL) { LOGE("client is NULL, aborting!"); return -1; @@ -205,84 +201,82 @@ int srs_read_loop(struct ril_client *client) return -1; } - srs_server = (struct srs_server *) client->object; + int server_fd = ((int*)client->object)[0]; while(1) { - if(srs_server->server_fd < 0) { + if(server_fd < 0) { LOGE("SRS client server_fd is negative, aborting!"); return -1; } - rc = srs_server_accept(srs_server); - - LOGE("SRS server accept!"); - - FD_ZERO(&fds); - FD_SET(srs_server->client_fd, &fds); - - while(1) { - if(srs_server->client_fd < 0) - break; - - select(FD_SETSIZE, &fds, NULL, NULL, NULL); - - if(FD_ISSET(srs_server->client_fd, &fds)) { - if(srs_server_recv(srs_server, &srs_message) < 0) { - LOGE("SRS recv failed, aborting!"); - break; - } - - LOGD("SRS recv: command=%d data_len=%d", srs_message.command, srs_message.data_len); - hex_dump(srs_message.data, srs_message.data_len); - - srs_dispatch(&srs_message); - - if(srs_message.data != NULL) - free(srs_message.data); - } + rc = accept(server_fd, (struct sockaddr*)&client_addr, + &client_addr_len); + if (rc < 0) { + LOGE("SRS Failed to accept errno %d error %s", + errno, strerror(errno)); + return -1; } - - if(srs_server->client_fd > 0) { - close(srs_server->client_fd); - srs_server->client_fd = -1; + LOGI("SRS accepted fd %d", rc); + int *pfd = (int*)malloc(sizeof(int)); + if (!pfd) { + LOGE("out of memory for the client socket"); + close(rc); + return -1; } + *pfd = rc; - LOGE("SRS server client ended!"); + pthread_t t; + if (pthread_create(&t, NULL, srs_process_client, pfd)) { + LOGE("SRS failed to start client thread errno %d error %s", + errno, strerror(errno)); + close(rc); + return -1; + } } return 0; } -int srs_create(struct ril_client *client) +static int srs_create(struct ril_client *client) { - struct srs_server *srs_server; + int *srs_server = NULL; LOGD("Creating new SRS client"); - srs_server = srs_server_new(); - client->object = (void *) srs_server; + srs_server = malloc(sizeof(int)); + if (!srs_server) { + LOGE("SRS out of memory for server fd"); + goto fail; + } - if(srs_server_open(srs_server) < 0) { + client->object = (void *) srs_server; + if((*srs_server = srs_server_open()) < 0) { LOGE("%s: samsung-ril-socket server open failed", __FUNCTION__); - return -1; + goto fail; } return 0; + +fail: + if (srs_server) { + free(srs_server); + } + return -1; } -int srs_destroy(struct ril_client *client) +static int srs_destroy(struct ril_client *client) { - struct srs_server *srs_server = (struct srs_server *) client->object; - - if(srs_server == NULL) + if (!client) { return 0; + } - if(srs_server->client_fd) - close(srs_server->client_fd); - - close(srs_server->server_fd); + int *srs_server = (int*) client->object; + if (!srs_server) { + return 0; + } - srs_server_free(srs_server); + close(*srs_server); + free(srs_server); return 0; } @@ -30,21 +30,7 @@ #include <samsung-ril-socket.h> -struct srs_server { - int server_fd; - int client_fd; - struct sockaddr_un client_addr; - int client_addr_len; -}; - extern struct ril_client_funcs srs_client_funcs; - -struct srs_server *srs_server_new(void); -int srs_server_send(unsigned short command, void *data, int data_len); -int srs_server_recv(struct srs_server *srs_server, struct srs_message *message); -int srs_server_accept(struct srs_server *srs_server); -int srs_server_open(struct srs_server *srs_server); - -void srs_control_ping(struct srs_message *message); +extern void srs_control_ping(int fd, struct srs_message *message); #endif |