From a3fb74d143f112bcfe9daf63e6703288f3b4234b Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Wed, 18 Jul 2012 00:16:16 +0200 Subject: [PATCH] Device: Various improvements: added missing functions, mutex, threaded recv loop This commit introduces the following changes: * Moved init functions to ril_device_init * Added deinit and data_destroy functions * Added mutex for send/recv * Added missing close function * Added device polling function * Added threaded recv loop Signed-off-by: Paul Kocialkowski --- device.c | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- hayes-ril.c | 26 ++---- hayes-ril.h | 21 +++-- 3 files changed, 288 insertions(+), 34 deletions(-) diff --git a/device.c b/device.c index 6e1e089..e4fd1f1 100644 --- a/device.c +++ b/device.c @@ -16,12 +16,55 @@ * limitations under the License. */ +#include + #define LOG_TAG "RIL-DEV" #include #include -// Create shared data for all the handlers +int ril_device_init(struct ril_device *ril_device_p) +{ + int rc; + + rc = ril_device_data_create(ril_device_p); + if(rc < 0) { + LOGE("Failed to create device data!"); + return -1; + } + + rc = ril_device_power_on(ril_device_p); + if(rc < 0) { + LOGE("Failed to power on device!"); + return -1; + } + + rc = ril_device_boot(ril_device_p); + if(rc < 0) { + LOGE("Failed to boot device!"); + return -1; + } + + rc = ril_device_open(ril_device_p); + if(rc < 0) { + LOGE("Failed to open device!"); + return -1; + } + + return 0; +} + +int ril_device_deinit(struct ril_device *ril_device_p) +{ + ril_device_close(ril_device_p); + + ril_device_power_off(ril_device_p); + + ril_device_data_destroy(ril_device_p); + + return 0; +} + int ril_device_data_create(struct ril_device *ril_device_p) { int rc; @@ -36,39 +79,87 @@ int ril_device_data_create(struct ril_device *ril_device_p) return -1; } - if(ril_device_p->handlers->power->sdata_create == NULL || - ril_device_p->handlers->power->sdata_destroy == NULL) { + if(ril_device_p->handlers->power->sdata_create == NULL) { LOGE("Missing device power data handlers!"); return -1; } + LOGD("Creating data for power handlers..."); + rc = ril_device_p->handlers->power->sdata_create(&ril_device_p->handlers->power->sdata); + if(rc < 0) { + LOGE("Creating data for power handlers failed!"); + return -1; + } + if(ril_device_p->handlers->transport == NULL) { LOGE("Missing device transport handlers!"); return -1; } - if(ril_device_p->handlers->transport->sdata_create == NULL || - ril_device_p->handlers->transport->sdata_destroy == NULL) { + if(ril_device_p->handlers->transport->sdata_create == NULL) { LOGE("Missing device transport data handlers!"); return -1; } - // iface + LOGD("Creating data for transport handlers..."); + ril_device_p->handlers->transport->sdata_create(&ril_device_p->handlers->transport->sdata); + if(rc < 0) { + LOGE("Creating data for transport handlers failed!"); + return -1; + } + + LOGD("Creating mutex for transport handlers..."); + pthread_mutex_init(&(ril_device_p->handlers->transport->mutex), NULL); - LOGD("Creating data for power handlers..."); - rc = ril_device_p->handlers->power->sdata_create(&ril_device_p->handlers->power->sdata); + return 0; +} + +int ril_device_data_destroy(struct ril_device *ril_device_p) +{ + int rc; + + if(ril_device_p->handlers == NULL) { + LOGE("Missing device handlers!"); + return -1; + } + + if(ril_device_p->handlers->power == NULL) { + LOGE("Missing device power handlers!"); + return -1; + } + + if(ril_device_p->handlers->power->sdata_destroy == NULL) { + LOGE("Missing device power data handlers!"); + return -1; + } + + LOGD("Destroying data for power handlers..."); + rc = ril_device_p->handlers->power->sdata_destroy(&ril_device_p->handlers->power->sdata); if(rc < 0) { - LOGE("Creating data for power handlers failed!"); + LOGE("Destroying data for power handlers failed!"); return -1; } - LOGD("Creating data for transport handlers..."); - ril_device_p->handlers->transport->sdata_create(&ril_device_p->handlers->transport->sdata); + if(ril_device_p->handlers->transport == NULL) { + LOGE("Missing device transport handlers!"); + return -1; + } + + if(ril_device_p->handlers->transport->sdata_destroy == NULL) { + LOGE("Missing device transport data handlers!"); + return -1; + } + + LOGD("Destroying data for transport handlers..."); + ril_device_p->handlers->transport->sdata_destroy(&ril_device_p->handlers->transport->sdata); if(rc < 0) { - LOGE("Creating data for transport handlers failed!"); + LOGE("Destroying data for transport handlers failed!"); return -1; } + LOGD("Destroying mutex for transport handlers..."); + pthread_mutex_destroy(&(ril_device_p->handlers->transport->mutex)); + return 0; } @@ -172,6 +263,31 @@ int ril_device_open(struct ril_device *ril_device_p) return rc; } +int ril_device_close(struct ril_device *ril_device_p) +{ + int rc; + + if(ril_device_p->handlers == NULL) { + LOGE("Missing device handlers!"); + return -1; + } + + if(ril_device_p->handlers->transport == NULL) { + LOGE("Missing device transport handlers!"); + return -1; + } + + if(ril_device_p->handlers->transport->close == NULL) { + LOGE("Missing device transport close handler!"); + return -1; + } + + LOGD("Closing modem..."); + + rc = ril_device_p->handlers->transport->close(ril_device_p->handlers->transport->sdata); + return rc; +} + int ril_device_send(struct ril_device *ril_device_p, void *data, int length) { int rc; @@ -191,7 +307,10 @@ int ril_device_send(struct ril_device *ril_device_p, void *data, int length) return -1; } + RIL_DEVICE_LOCK(ril_device_p); rc = ril_device_p->handlers->transport->send(ril_device_p->handlers->transport->sdata, data, length); + RIL_DEVICE_UNLOCK(ril_device_p); + return rc; } @@ -214,6 +333,138 @@ int ril_device_recv(struct ril_device *ril_device_p, void **data, int length) return -1; } + RIL_DEVICE_LOCK(ril_device_p); rc = ril_device_p->handlers->transport->recv(ril_device_p->handlers->transport->sdata, data, length); + RIL_DEVICE_UNLOCK(ril_device_p); + + return rc; +} + +int ril_device_recv_poll(struct ril_device *ril_device_p) +{ + int rc; + + if(ril_device_p->handlers == NULL) { + LOGE("Missing device handlers!"); + return -1; + } + + if(ril_device_p->handlers->transport == NULL) { + LOGE("Missing device transport handlers!"); + return -1; + } + + if(ril_device_p->handlers->transport->recv_poll == NULL) { + LOGE("Missing device transport recv poll handler!"); + return -1; + } + + rc = ril_device_p->handlers->transport->recv_poll(ril_device_p->handlers->transport->sdata); return rc; } + +int ril_device_recv_loop(struct ril_device *ril_device_p) +{ + // TODO: AT message structure + char *data; + int count; + int rc; + int i; + + // Return error after 5 consecutive poll/read failures + for(i=5 ; i > 0 ; i--) { + while(1) { + rc = ril_device_recv_poll(ril_device_p); + if(rc < 0) { + LOGE("Polling from transport recv failed!"); + break; + } + + count = rc; + + rc = ril_device_recv(ril_device_p, &data, count); + if(rc < 0) { + LOGE("Reading from transport recv failed!"); + break; + } + if(rc == 0) LOGE("WERE GOING MAD!!! READING 0 BYTES!!!"); //FIXME + + // Read works now + if(i != 5) + i = 5; + + LOGD("GOT: '%s'", data); + + //TODO: Convert AT string to AT structures + free(data); + + //TODO: Dispatch AT structures with multi-message handling (dispatch each) + //TODO: Free AT structures + } + + // When poll/read failed, close and reopen the device + ril_device_close(ril_device_p); + usleep(500); + ril_device_open(ril_device_p); + + RIL_DEVICE_UNLOCK(ril_device_p); + } + + return -1; +} + +void *ril_device_recv_thread(void *data) +{ + struct ril_device *ril_device_p = (struct ril_device *) data; + int rc; + int i; + + for(i = 5 ; i > 0 ; i--) { + rc = ril_device_recv_loop(ril_device_p); + if(rc < 0) { + LOGE("Recv loop failed too many times, restarting..."); + + rc = ril_device_deinit(ril_device_p); + if(rc < 0) + break; + + usleep(500); + + rc = ril_device_init(ril_device_p); + if(rc < 0) + break; + } + } + + LOGE("Recv thread failed too many times, stopping it all..."); + ril_device_deinit(ril_device_p); + + return NULL; +} + +int ril_device_recv_thread_start(struct ril_device *ril_device_p) +{ + pthread_attr_t attr; + int rc; + + if(ril_device_p->handlers == NULL) { + LOGE("Missing device handlers!"); + return -1; + } + + if(ril_device_p->handlers->transport == NULL) { + LOGE("Missing device transport handlers!"); + return -1; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + rc = pthread_create(&(ril_device_p->handlers->transport->recv_thread), &attr, ril_device_recv_thread, (void *) ril_device_p); + if(rc != 0) { + LOGE("Creating transport recv thread failed!"); + return -1; + } + + return 0; +} diff --git a/hayes-ril.c b/hayes-ril.c index 28d9954..7fd6656 100644 --- a/hayes-ril.c +++ b/hayes-ril.c @@ -52,31 +52,23 @@ const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **a LOGD("Starting %s for device: %s", RIL_VERSION_STRING, ril_device->name); - rc = ril_device_data_create(ril_device); + rc = ril_device_init(ril_device); if(rc < 0) { - goto failure; - } + LOGE("Failed to init device!"); + ril_device_deinit(ril_device); - rc = ril_device_power_on(ril_device); - if(rc < 0) { - goto failure; + return NULL; } - rc = ril_device_boot(ril_device); + rc = ril_device_recv_thread_start(ril_device); if(rc < 0) { - goto failure; - } + LOGE("Failed to start device thread!"); + ril_device_deinit(ril_device); - rc = ril_device_open(ril_device); - if(rc < 0) { - goto failure; + return NULL; } - LOGD("Init process done"); + LOGD("Initialization complete"); return &ril_ops; - -failure: - LOGE("Failure, aborting!"); - return NULL; } diff --git a/hayes-ril.h b/hayes-ril.h index 55120cb..1966ff6 100644 --- a/hayes-ril.h +++ b/hayes-ril.h @@ -3,10 +3,6 @@ * * Copyright (C) 2012 Paul Kocialkowski * - * Based on htcgeneric-ril, reference-ril: - * Copyright 2006-2011, htcgeneric-ril contributors - * Copyright 2006, The Android Open Source Project - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -23,6 +19,9 @@ #ifndef _HAYES_RIL_H_ #define _HAYES_RIL_H_ +#define RIL_DEVICE_LOCK(ril_device_p) pthread_mutex_lock(&(ril_device_p->handlers->transport->mutex)); +#define RIL_DEVICE_UNLOCK(ril_device_p) pthread_mutex_unlock(&(ril_device_p->handlers->transport->mutex)); + #define DEV_GSM RIL_DEVICE_TYPE_GSM #define DEV_CDMA RIL_DEVICE_TYPE_CDMA @@ -58,7 +57,10 @@ struct ril_device_transport_handlers { int (*send)(void *sdata, void **data, int length); int (*recv)(void *sdata, void **data, int length); - int (*poll)(void *sdata); + int (*recv_poll)(void *sdata); + + pthread_t recv_thread; + pthread_mutex_t mutex; }; struct ril_device_handlers { @@ -76,11 +78,20 @@ struct ril_device { // Device void ril_device_register(struct ril_device **ril_device_p); +int ril_device_init(struct ril_device *ril_device_p); +int ril_device_deinit(struct ril_device *ril_device_p); + int ril_device_data_create(struct ril_device *ril_device_p); +int ril_device_data_destroy(struct ril_device *ril_device_p); +int ril_device_boot(struct ril_device *ril_device_p); int ril_device_boot(struct ril_device *ril_device_p); int ril_device_power_on(struct ril_device *ril_device_p); int ril_device_power_off(struct ril_device *ril_device_p); int ril_device_open(struct ril_device *ril_device_p); +int ril_device_close(struct ril_device *ril_device_p); int ril_device_send(struct ril_device *ril_device_p, void *data, int length); int ril_device_recv(struct ril_device *ril_device_p, void **data, int length); +int ril_device_recv_poll(struct ril_device *ril_device_p); +int ril_device_recv_thread_start(struct ril_device *ril_device_p); + #endif -- 2.11.0