Call: Completed implementation (ingoing/outgoing works)
authorPaul Kocialkowski <contact@paulk.fr>
Tue, 31 Jul 2012 21:26:08 +0000 (23:26 +0200)
committerPaul Kocialkowski <contact@paulk.fr>
Tue, 31 Jul 2012 21:26:08 +0000 (23:26 +0200)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
call.c
hayes-ril.c
hayes-ril.h

diff --git a/call.c b/call.c
index 00e2be7..dde4918 100644 (file)
--- a/call.c
+++ b/call.c
 
 #include <hayes-ril.h>
 
+/*
+ * Calls list
+ */
+
+RIL_CallState at2ril_call_state(int state)
+{
+       switch(state) {
+               case 0:
+                       return RIL_CALL_ACTIVE;
+               case 1:
+                       return RIL_CALL_HOLDING;
+               case 2:
+                       return RIL_CALL_DIALING;
+               case 3:
+                       return RIL_CALL_ALERTING;
+               case 4:
+                       return RIL_CALL_INCOMING;
+               case 5:
+                       return RIL_CALL_WAITING;
+               default:
+                       return -1;
+       }
+}
+
+void at2ril_call_list(RIL_Call *call, char *data)
+{
+       struct at_response_data **response_data = NULL;
+       int response_data_count = 0;
+       char *number = NULL;
+       int state = 0;
+       int mode = 0;
+
+       response_data_count = at_response_data_process(&response_data, data, strlen(data));
+       if(response_data_count < 7)
+               goto error;
+
+       // 1,0,2,0,0,"0557514206",129
+
+       if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
+               goto error;
+       call->index = response_data[0]->value.n;
+
+       if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
+               goto error;
+       call->isMT = response_data[1]->value.n;
+
+       if(response_data[2]->type != AT_RESPONSE_DATA_NUMERIC)
+               goto error;
+       state = response_data[2]->value.n;
+       call->state = at2ril_call_state(state);
+
+       if(response_data[3]->type != AT_RESPONSE_DATA_NUMERIC)
+               goto error;
+       mode = response_data[3]->value.n;
+       call->isVoice = (mode == 0);
+
+       if(response_data[4]->type != AT_RESPONSE_DATA_NUMERIC)
+               goto error;
+       call->isMpty = response_data[4]->value.n;
+
+       if(response_data[5]->type != AT_RESPONSE_DATA_STRING)
+               goto error;
+       number = strdup(response_data[5]->value.s);
+       if(number != NULL && strspn(number, "+0123456789") == 0)
+               number = NULL;
+       call->number = number;
+
+       if(response_data[6]->type != AT_RESPONSE_DATA_NUMERIC)
+               goto error;
+       call->toa = response_data[6]->value.n;
+
+       at_response_data_free(response_data, response_data_count);
+
+       return;
+
+error:
+       LOGE("Error while parsing call list!");
+       at_response_data_free(response_data, response_data_count);
+}
+
 int at_clcc_expect(struct at_response *response, void *data, RIL_Token t)
 {
        RIL_Call **calls = NULL;
        int calls_count = 0;
+       int poll = 0;
        int i;
 
+       struct timeval poll_interval = {0, 500000};
+
        if(response->status == AT_STATUS_UNDEF)
                return AT_RESPONSE_UNHANDELD_REASON_STATUS;
 
-       LOGD("GOT AT CLCC response");
+       LOGE("Caught valid AT+CLCC unsol!");
 
        if(at_status_error(response->status)) {
                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
        }
 
-       // TODO: count calls
-       for(i=0 ; i < response->data_count ; i++) {
-               LOGD("CLCC data: %s", response->data[i]);
+       calls_count = response->data_count;
+       if(calls_count > 0) {
+               calls = calloc(1, sizeof(RIL_Call *) * calls_count);
+
+               LOGD("Got %d call(s) ingoing!", calls_count);
+
+               for(i=0 ; i < calls_count ; i++) {
+                       calls[i] = calloc(1, sizeof(RIL_Call));
+                       at2ril_call_list(calls[i], response->data[i]);
+
+                       if(calls[i]->state != RIL_CALL_ACTIVE && calls[i]->state != RIL_CALL_HOLDING)
+                               poll = 1;
+               }
+
+               RIL_requestTimedCallback(ril_call_state_changed, NULL, &poll_interval);
        }
 
-       calls = calloc(1, sizeof(RIL_Call) * calls_count);
+       RIL_onRequestComplete(t, RIL_E_SUCCESS, calls, sizeof(RIL_Call *) * calls_count);
 
-       // TODO: copy calls
+       for(i=0 ; i < calls_count ; i++) {
+               if(calls[i] != NULL) {
+                       if(calls[i]->number != NULL)
+                               free(calls[i]->number);
+                       free(calls[i]);
+               }
+       }
 
-       RIL_onRequestComplete(t, RIL_E_SUCCESS, calls, sizeof(RIL_Call) * calls_count);
+       if(calls != NULL)
+               free(calls);
 
        return AT_RESPONSE_HANDLED_OK;
 }
@@ -63,3 +165,110 @@ void ril_request_get_current_calls(RIL_Token t, void *data, size_t length)
        }
        at_send_expect_to_func("AT+CLCC", NULL, NULL, t, at_clcc_expect);
 }
+
+void ril_call_state_changed(void *data)
+{
+       RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+}
+
+void at_cring(struct at_response *response)
+{
+       RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+}
+
+void ril_request_anwswer(RIL_Token t, void *data, size_t length)
+{
+       int status;
+
+       status = at_send_expect_status("ATA", NULL);
+
+       if(at_status_error(status))
+               RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+       else
+               RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+/*
+ * Dial
+ */
+
+void ril_request_dial(RIL_Token t, void *data, size_t length)
+{
+       RIL_Dial *dial;
+       char *command = NULL;
+       char *clir = NULL;
+       int status = AT_STATUS_UNDEF;
+
+       dial = (RIL_Dial *) data;
+
+       switch(dial->clir) {
+               case 1: clir = "I"; break;  // invocation
+               case 2: clir = "i"; break;  // suppression
+               default:
+               case 0: clir = ""; break;   // subscription default
+       }
+
+       asprintf(&command, "ATD%s%s;", dial->address, clir);
+
+       status = at_send_expect_status(command, NULL);
+
+       free(command);
+
+       if(at_status_error(status))
+               RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+       else
+               RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+void no_carrier_unexpect(struct at_response *response)
+{
+       // This comes to notify call end
+       RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+}
+
+void ril_request_hangup(RIL_Token t, void *data, size_t length)
+{
+       char *command = NULL;
+       int index = 0;
+       int status = AT_STATUS_UNDEF;
+
+       index = *((int *) data);
+
+       asprintf(&command, "AT+CHLD=1%d", index);
+
+       status = at_send_expect_status(command, NULL);
+
+       free(command);
+
+       if(at_status_error(status))
+               RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+       else
+               RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+void at_chld_request(RIL_Token t, char *data)
+{
+       int status;
+
+       status = at_send_expect_status("AT+CHLD", data);
+
+       if(at_status_error(status))
+               RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+       else
+               RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+}
+
+void ril_request_hangup_waiting_or_background(RIL_Token t, void *data, size_t length)
+{
+       at_chld_request(t, "0");
+}
+
+void ril_request_hangup_foreground_resume_background(RIL_Token t, void *data, size_t length)
+{
+       at_chld_request(t, "1");
+}
+
+void ril_request_switch_waiting_or_holding_and_active(RIL_Token t, void *data, size_t length)
+{
+       at_chld_request(t, "2");
+}
index b397350..e03a510 100644 (file)
@@ -28,7 +28,9 @@ struct ril_device *ril_device;
 struct ril_globals ril_globals;
 
 struct ril_dispatch_unsol ril_dispatch_unsol[] = {
-       { "AT+CREG", at_creg_unexpect }
+       { "AT+CREG",    at_creg_unexpect },
+       { "NO CARRIER", no_carrier_unexpect },
+       { "AT+CRING",   at_cring }
 };
 
 void ril_on_request(int request, void *data, size_t length, RIL_Token t)
@@ -62,6 +64,24 @@ void ril_on_request(int request, void *data, size_t length, RIL_Token t)
                case RIL_REQUEST_GET_CURRENT_CALLS:
                        ril_request_get_current_calls(t, data, length);
                        break;
+               case RIL_REQUEST_DIAL:
+                       ril_request_dial(t, data, length);
+                       break;
+               case RIL_REQUEST_ANSWER:        
+                       ril_request_anwswer(t, data, length);
+                       break;
+               case RIL_REQUEST_HANGUP:
+                       ril_request_hangup(t, data, length);
+                       break;
+               case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
+                       ril_request_hangup_waiting_or_background(t, data, length);
+                       break;
+               case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
+                       ril_request_hangup_foreground_resume_background(t, data, length);
+                       break;
+               case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
+                       ril_request_switch_waiting_or_holding_and_active(t, data, length);
+                       break;
                default:
                        LOGE("Request not implemented: %d\n", request);
                        RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
index 8180089..51f9c04 100644 (file)
@@ -143,6 +143,15 @@ void ril_data_log(char *data, int length);
 
 // Call
 void ril_request_get_current_calls(RIL_Token t, void *data, size_t length);
+void ril_call_state_changed(void *data);
+void at_cring(struct at_response *response);
+void ril_request_anwswer(RIL_Token t, void *data, size_t length);
+void ril_request_dial(RIL_Token t, void *data, size_t length);
+void no_carrier_unexpect(struct at_response *response);
+void ril_request_hangup(RIL_Token t, void *data, size_t length);
+void ril_request_hangup_waiting_or_background(RIL_Token t, void *data, size_t length);
+void ril_request_hangup_foreground_resume_background(RIL_Token t, void *data, size_t length);
+void ril_request_switch_waiting_or_holding_and_active(RIL_Token t, void *data, size_t length);
 
 // Power
 void ril_request_radio_power(RIL_Token t, void *data, size_t length);