summaryrefslogtreecommitdiffstats
path: root/client.c
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2014-08-07 13:12:15 +0200
committerPaul Kocialkowski <contact@paulk.fr>2014-08-07 13:12:15 +0200
commita7ff1df1869ce543171a6ee92cbf821647b1bf7d (patch)
tree659e315b3d609f0f9e661d4de21b52077e6e2b81 /client.c
parentc8408cd2c116b0b99a399282032b6607a1318b84 (diff)
downloadhardware_replicant_libsamsung-ril-a7ff1df1869ce543171a6ee92cbf821647b1bf7d.tar.gz
hardware_replicant_libsamsung-ril-a7ff1df1869ce543171a6ee92cbf821647b1bf7d.tar.bz2
hardware_replicant_libsamsung-ril-a7ff1df1869ce543171a6ee92cbf821647b1bf7d.zip
Samsung-RIL rewrite: harder, better, probably not faster but definitely stronger
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
Diffstat (limited to 'client.c')
-rw-r--r--client.c243
1 files changed, 159 insertions, 84 deletions
diff --git a/client.c b/client.c
index 92ebc2c..1e06554 100644
--- a/client.c
+++ b/client.c
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * Copyright (C) 2011-2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2011-2014 Paul Kocialkowski <contact@paulk.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
@@ -17,101 +17,115 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
#include <pthread.h>
#define LOG_TAG "RIL"
#include <utils/Log.h>
-#include "samsung-ril.h"
+#include <samsung-ril.h>
-struct ril_client *ril_client_new(struct ril_client_funcs *client_funcs)
+struct ril_client *ril_client_find_id(int id)
{
- struct ril_client *ril_client;
- int rc;
+ unsigned int i;
- ril_client = calloc(1, sizeof(struct ril_client));
+ if (ril_clients == NULL || ril_clients_count == 0)
+ return NULL;
- if (client_funcs != NULL) {
- ril_client->funcs.create = client_funcs->create;
- ril_client->funcs.destroy = client_funcs->destroy;
- ril_client->funcs.read_loop = client_funcs->read_loop;
- }
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
- pthread_mutex_init(&(ril_client->mutex), NULL);
+ if (ril_clients[i]->id == id)
+ return ril_clients[i];
+ }
- return ril_client;
+ return NULL;
}
-int ril_client_free(struct ril_client *client)
+int ril_client_create(struct ril_client *client)
{
+ int rc;
+
if (client == NULL)
return -1;
- pthread_mutex_destroy(&(client->mutex));
+ client->data = NULL;
+ pthread_mutex_init(&client->mutex, NULL);
+
+ if (client->handlers != NULL && client->handlers->create != NULL) {
+ rc = client->handlers->create(client);
+ if (rc < 0) {
+ RIL_LOGE("Creating %s client failed", client->name);
+ return -1;
+ }
+ }
- free(client);
+ RIL_LOGD("Created %s client", client->name);
return 0;
}
-int ril_client_create(struct ril_client *client)
+int ril_client_destroy(struct ril_client *client)
{
int rc;
- int c;
- if (client == NULL || client->funcs.create == NULL)
+ if (client == NULL)
return -1;
- for (c = RIL_CLIENT_MAX_TRIES ; c > 0 ; c--) {
- RIL_LOGD("Creating RIL client inners, try #%d", RIL_CLIENT_MAX_TRIES - c + 1);
+ if (client->handlers != NULL && client->handlers->destroy != NULL) {
+ rc = client->handlers->destroy(client);
+ if (rc < 0) {
+ RIL_LOGE("Destroying %s client failed", client->name);
+ return -1;
+ }
+ }
- rc = client->funcs.create(client);
- if (rc < 0)
- RIL_LOGE("RIL client inners creation failed");
- else
- break;
+ pthread_mutex_destroy(&client->mutex);
- usleep(500000);
- }
+ RIL_LOGD("Destroyed %s client", client->name);
+
+ return 0;
+}
- if (c == 0) {
- RIL_LOGE("RIL client inners creation failed too many times");
- client->state = RIL_CLIENT_ERROR;
+int ril_client_open(struct ril_client *client)
+{
+ int rc = 0;
+
+ if (client == NULL)
+ return -1;
+
+ if (client->handlers == NULL || client->handlers->open == NULL)
+ return -1;
+
+ rc = client->handlers->open(client);
+ if (rc < 0) {
+ RIL_LOGE("Opening %s client failed", client->name);
return -1;
}
- client->state = RIL_CLIENT_CREATED;
+ RIL_LOGD("Opened %s client", client->name);
return 0;
}
-int ril_client_destroy(struct ril_client *client)
+int ril_client_close(struct ril_client *client)
{
int rc;
- int c;
- if (client == NULL || client->funcs.destroy == NULL)
+ if (client == NULL)
return -1;
- for (c = RIL_CLIENT_MAX_TRIES ; c > 0 ; c--) {
- RIL_LOGD("Destroying RIL client inners, try #%d", RIL_CLIENT_MAX_TRIES - c + 1);
-
- rc = client->funcs.destroy(client);
- if (rc < 0)
- RIL_LOGE("RIL client inners destroying failed");
- else
- break;
-
- usleep(500000);
- }
+ if (client->handlers == NULL || client->handlers->close == NULL)
+ return -1;
- if (c == 0) {
- RIL_LOGE("RIL client inners destroying failed too many times");
- client->state = RIL_CLIENT_ERROR;
+ rc = client->handlers->close(client);
+ if (rc < 0) {
+ RIL_LOGE("Closing %s client failed", client->name);
return -1;
}
- client->state = RIL_CLIENT_DESTROYED;
+ RIL_LOGD("Closed %s client", client->name);
return 0;
}
@@ -120,69 +134,130 @@ void *ril_client_thread(void *data)
{
struct ril_client *client;
int rc;
- int c;
- if (data == NULL)
+ if (data == NULL || ril_data == NULL)
return NULL;
client = (struct ril_client *) data;
- if (client->funcs.read_loop == NULL)
- return NULL;
+ client->failures = 0;
- for (c = RIL_CLIENT_MAX_TRIES ; c > 0 ; c--) {
- client->state = RIL_CLIENT_READY;
+ do {
+ if (client->failures) {
+ usleep(RIL_CLIENT_RETRY_DELAY);
- rc = client->funcs.read_loop(client);
- if (rc < 0) {
- client->state = RIL_CLIENT_ERROR;
+ rc = ril_client_close(client);
+ if (rc < 0)
+ goto failure;
- RIL_LOGE("RIL client read loop failed");
+ if (client->failures > 1) {
+ rc = ril_client_destroy(client);
+ if (rc < 0)
+ goto failure;
- ril_client_destroy(client);
- ril_client_create(client);
+ rc = ril_client_create(client);
+ if (rc < 0)
+ goto failure;
+ }
- continue;
- } else {
- client->state = RIL_CLIENT_CREATED;
+ rc = ril_client_open(client);
+ if (rc < 0)
+ goto failure;
+ }
+
+ rc = client->handlers->loop(client);
+ if (rc < 0) {
+ RIL_LOGE("%s client loop failed", client->name);
+
+ if (client->critical) {
+ RIL_LOCK();
+ ril_radio_state_update(RADIO_STATE_UNAVAILABLE);
+ RIL_UNLOCK();
+ }
- RIL_LOGD("RIL client read loop ended");
+ goto failure;
+ } else {
+ RIL_LOGE("%s client loop terminated", client->name);
break;
}
- }
-
- if (c == 0) {
- RIL_LOGE("RIL client read loop failed too many times");
- client->state = RIL_CLIENT_ERROR;
- }
- // Destroy everything here
+failure:
+ client->failures++;
+ } while (client->failures < RIL_CLIENT_RETRY_COUNT);
- rc = ril_client_destroy(client);
- if (rc < 0)
- RIL_LOGE("RIL client destroy failed");
+ ril_client_close(client);
+ ril_client_destroy(client);
- rc = ril_client_free(client);
- if (rc < 0)
- RIL_LOGE("RIL client free failed");
+ RIL_LOGD("Stopped %s client loop", client->name);
- return 0;
+ return NULL;
}
-int ril_client_thread_start(struct ril_client *client)
+int ril_client_loop(struct ril_client *client)
{
pthread_attr_t attr;
int rc;
+ if (client == NULL)
+ return -1;
+
+ if (client->handlers == NULL || client->handlers->loop == NULL)
+ return -1;
+
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- rc = pthread_create(&(client->thread), &attr, ril_client_thread, (void *) client);
-
+ rc = pthread_create(&client->thread, &attr, ril_client_thread, (void *) client);
if (rc != 0) {
- RIL_LOGE("RIL client thread creation failed");
+ RIL_LOGE("Starting %s client loop failed", client->name);
return -1;
}
+ RIL_LOGD("Started %s client loop", client->name);
+
+ return 0;
+}
+
+int ril_client_request_register(struct ril_client *client, int request,
+ RIL_Token token)
+{
+ int rc = 0;
+
+ if (client == NULL || client->callbacks == NULL || client->callbacks->request_register == NULL)
+ return -1;
+
+ rc = client->callbacks->request_register(client, request, token);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int ril_client_request_unregister(struct ril_client *client, int request,
+ RIL_Token token)
+{
+ int rc = 0;
+
+ if (client == NULL || client->callbacks == NULL || client->callbacks->request_unregister == NULL)
+ return -1;
+
+ rc = client->callbacks->request_unregister(client, request, token);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int ril_client_flush(struct ril_client *client)
+{
+ int rc = 0;
+
+ if (client == NULL || client->callbacks == NULL || client->callbacks->flush == NULL)
+ return -1;
+
+ rc = client->callbacks->flush(client);
+ if (rc < 0)
+ return -1;
+
return 0;
}