diff options
author | Paul Kocialkowski <contact@paulk.fr> | 2014-08-07 13:12:15 +0200 |
---|---|---|
committer | Paul Kocialkowski <contact@paulk.fr> | 2014-08-07 13:12:15 +0200 |
commit | a7ff1df1869ce543171a6ee92cbf821647b1bf7d (patch) | |
tree | 659e315b3d609f0f9e661d4de21b52077e6e2b81 /client.c | |
parent | c8408cd2c116b0b99a399282032b6607a1318b84 (diff) | |
download | hardware_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.c | 243 |
1 files changed, 159 insertions, 84 deletions
@@ -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; } |