Device: Various improvements: added missing functions, mutex, threaded recv loop
authorPaul Kocialkowski <contact@paulk.fr>
Tue, 17 Jul 2012 22:16:16 +0000 (00:16 +0200)
committerPaul Kocialkowski <contact@paulk.fr>
Wed, 18 Jul 2012 14:34:02 +0000 (16:34 +0200)
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 <contact@paulk.fr>
device.c
hayes-ril.c
hayes-ril.h

index 6e1e089..e4fd1f1 100644 (file)
--- a/device.c
+++ b/device.c
  * limitations under the License.
  */
 
+#include <pthread.h>
+
 #define LOG_TAG "RIL-DEV"
 #include <utils/Log.h>
 
 #include <hayes-ril.h>
 
-// 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;
+}
index 28d9954..7fd6656 100644 (file)
@@ -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;
 }
index 55120cb..1966ff6 100644 (file)
@@ -3,10 +3,6 @@
  *
  * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
  * 
- * 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