summaryrefslogtreecommitdiffstats
path: root/call.c
diff options
context:
space:
mode:
Diffstat (limited to 'call.c')
-rw-r--r--call.c683
1 files changed, 499 insertions, 184 deletions
diff --git a/call.c b/call.c
index 680aba5..6a3ffb9 100644
--- a/call.c
+++ b/call.c
@@ -2,7 +2,7 @@
* This file is part of Samsung-RIL.
*
* Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
- * 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
@@ -18,10 +18,12 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
-#define LOG_TAG "RIL-CALL"
+#include <stdlib.h>
+
+#define LOG_TAG "RIL"
#include <utils/Log.h>
-#include "samsung-ril.h"
+#include <samsung-ril.h>
unsigned char ril2ipc_call_identity(int clir)
{
@@ -33,28 +35,26 @@ unsigned char ril2ipc_call_identity(int clir)
case 2:
return IPC_CALL_IDENTITY_HIDE;
default:
- RIL_LOGE("Unknown call identity: 0x%x", clir);
return IPC_CALL_IDENTITY_DEFAULT;
}
}
-unsigned char ipc2ril_call_list_entry_state(unsigned char call_state)
+unsigned char ipc2ril_call_list_entry_state(unsigned char status)
{
- switch (call_state) {
- case IPC_CALL_LIST_ENTRY_STATE_ACTIVE:
+ switch (status) {
+ case IPC_CALL_LIST_ENTRY_STATUS_ACTIVE:
return RIL_CALL_ACTIVE;
- case IPC_CALL_LIST_ENTRY_STATE_HOLDING:
+ case IPC_CALL_LIST_ENTRY_STATUS_HOLDING:
return RIL_CALL_HOLDING;
- case IPC_CALL_LIST_ENTRY_STATE_DIALING:
+ case IPC_CALL_LIST_ENTRY_STATUS_DIALING:
return RIL_CALL_DIALING;
- case IPC_CALL_LIST_ENTRY_STATE_ALERTING:
+ case IPC_CALL_LIST_ENTRY_STATUS_ALERTING:
return RIL_CALL_ALERTING;
- case IPC_CALL_LIST_ENTRY_STATE_INCOMING:
+ case IPC_CALL_LIST_ENTRY_STATUS_INCOMING:
return RIL_CALL_INCOMING;
- case IPC_CALL_LIST_ENTRY_STATE_WAITING:
+ case IPC_CALL_LIST_ENTRY_STATUS_WAITING:
return RIL_CALL_WAITING;
default:
- RIL_LOGE("Unknown call list entry state: 0x%x", call_state);
return -1;
}
}
@@ -67,303 +67,618 @@ RIL_LastCallFailCause ipc2ril_call_fail_cause(unsigned char end_cause)
return CALL_FAIL_NORMAL;
case IPC_CALL_END_CAUSE_UNSPECIFIED:
default:
- RIL_LOGE("Unknown call fail cause: 0x%x", end_cause);
return CALL_FAIL_ERROR_UNSPECIFIED;
}
}
-void ipc_call_incoming(struct ipc_message_info *info)
+int ril_request_dial(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_call_outgoing_data request_data;
+ RIL_Dial *dial = NULL;
+ unsigned char identity;
+ unsigned char prefix;
+ int rc;
+
+ if (data == NULL || size < sizeof(RIL_Dial))
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ dial = (RIL_Dial *) data;
+
+ if (dial->address == NULL)
+ goto error;
+
+ identity = ril2ipc_call_identity(dial->clir);
+ prefix = dial->address[0] == '+' ? IPC_CALL_PREFIX_INTL : IPC_CALL_PREFIX_NONE;
+
+ rc = ipc_call_outgoing_setup(&request_data, IPC_CALL_TYPE_VOICE, identity, prefix, dial->address);
+ if (rc < 0)
+ goto error;
+
+ free(dial->address);
+ dial = NULL;
+
+ rc = ipc_gen_phone_res_expect_complete(ipc_fmt_request_seq(token), IPC_CALL_OUTGOING);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_CALL_OUTGOING, IPC_TYPE_EXEC, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (dial != NULL && dial->address != NULL)
+ free(dial->address);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ipc_call_incoming(struct ipc_message *message)
{
ril_request_unsolicited(RIL_UNSOL_CALL_RING, NULL, 0);
ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+
+ return 0;
}
-void ipc_call_status(struct ipc_message_info *info)
+int ril_request_hangup(void *data, size_t size, RIL_Token token)
{
- struct ipc_call_status *call_status;
+ int hangup;
+ int rc;
- if (info->data == NULL || info->length < sizeof(struct ipc_call_status))
- return;
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- call_status = (struct ipc_call_status *) info->data;
+ hangup = 1;
+ ril_request_data_set_uniq(RIL_REQUEST_HANGUP, &hangup, sizeof(hangup));
- RIL_LOGD("Updating call status data");
- memcpy(&(ril_data.state.call_status), call_status, sizeof(struct ipc_call_status));
+ rc = ipc_gen_phone_res_expect_complete(ipc_fmt_request_seq(token), IPC_CALL_RELEASE);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_CALL_RELEASE, IPC_TYPE_EXEC, NULL, 0);
+ if (rc < 0)
+ goto error;
ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ ril_request_data_free(RIL_REQUEST_HANGUP);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
}
-void ril_request_dial(RIL_Token t, void *data, size_t length)
+int ril_request_answer(void *data, size_t size, RIL_Token token)
{
- RIL_Dial *dial;
- struct ipc_call_outgoing call;
- int clir;
+ int rc;
- if (data == NULL || length < sizeof(RIL_Dial))
- goto error;
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- dial = (RIL_Dial *) data;
+ rc = ipc_gen_phone_res_expect_complete(ipc_fmt_request_seq(token), IPC_CALL_ANSWER);
+ if (rc < 0)
+ goto error;
- if (strlen(dial->address) > sizeof(call.number)) {
- printf("Outgoing call number too long\n");
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_CALL_ANSWER, IPC_TYPE_EXEC, NULL, 0);
+ if (rc < 0)
goto error;
- }
- memset(&call, 0, sizeof(call));
- call.type = IPC_CALL_TYPE_VOICE;
- call.identity = ril2ipc_call_identity(dial->clir);
- call.prefix = dial->address[0] == '+' ? IPC_CALL_PREFIX_INTL : IPC_CALL_PREFIX_NONE;
- call.length = strlen(dial->address);
- memcpy(call.number, dial->address, strlen(dial->address));
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
- ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_OUTGOING);
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
- ipc_fmt_send(IPC_CALL_OUTGOING, IPC_TYPE_EXEC, (unsigned char *) &call, sizeof(call), ril_request_get_id(t));
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
+ rc = RIL_REQUEST_COMPLETED;
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+complete:
+ return rc;
+}
+
+int ipc_call_status(struct ipc_message *message)
+{
+ struct ipc_call_status_data *data;
+ int fail_cause;
+ void *hangup_data;
+ size_t hangup_size;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_call_status_data))
+ return -1;
+
+ data = (struct ipc_call_status_data *) message->data;
+
+ // Nobody will ask for a call fail cause when we hangup ourselves
+ hangup_size = ril_request_data_size_get(RIL_REQUEST_HANGUP);
+ hangup_data = ril_request_data_get(RIL_REQUEST_HANGUP);
+
+ if (data->status == IPC_CALL_STATUS_RELEASED && (hangup_data == NULL || hangup_size == 0)) {
+ fail_cause = ipc2ril_call_fail_cause(data->end_cause);
+
+ ril_request_data_set_uniq(RIL_REQUEST_LAST_CALL_FAIL_CAUSE, &fail_cause, sizeof(fail_cause));
+ } else if (hangup_data != NULL && hangup_size > 0) {
+ free(hangup_data);
+ }
+
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+
+ return 0;
}
-void ril_request_get_current_calls(RIL_Token t)
+int ril_request_last_call_fail_cause(void *data, size_t size, RIL_Token token)
{
- ipc_fmt_send_get(IPC_CALL_LIST, ril_request_get_id(t));
+ void *fail_cause_data;
+ size_t fail_cause_size;
+ int fail_cause;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ fail_cause_size = ril_request_data_size_get(RIL_REQUEST_LAST_CALL_FAIL_CAUSE);
+ fail_cause_data = ril_request_data_get(RIL_REQUEST_LAST_CALL_FAIL_CAUSE);
+
+ if (fail_cause_data == NULL || fail_cause_size < sizeof(fail_cause)) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ fail_cause = *((int *) fail_cause_data);
+
+ ril_request_complete(token, RIL_E_SUCCESS, &fail_cause, sizeof(fail_cause));
+
+ free(fail_cause_data);
+
+ return RIL_REQUEST_COMPLETED;
}
-void ipc_call_list(struct ipc_message_info *info)
+int ipc_call_list(struct ipc_message *message)
{
struct ipc_call_list_entry *entry;
+ RIL_Call **calls = NULL;
+ size_t calls_size;
+ unsigned int calls_count = 0;
unsigned char count;
+ unsigned char index;
char *number;
- RIL_Call **current_calls = NULL;
- int i;
+ int rc;
- if (info->data == NULL || info->length < sizeof(unsigned char))
- goto error;
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_call_list_header))
+ return -1;
- if (info->type != IPC_TYPE_RESP)
- return;
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
- count = *((unsigned char *) info->data);
+ count = ipc_call_list_count_extract(message->data, message->size);
if (count == 0) {
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0);
- return;
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0);
+ return 0;
}
- current_calls = (RIL_Call **) calloc(1, count * sizeof(RIL_Call *));
- entry = (struct ipc_call_list_entry *) ((char *) info->data + sizeof(unsigned char));
+ calls_size = count * sizeof(RIL_Call *);
+ calls = (RIL_Call **) calloc(1, calls_size);
+
+ for (index = 0; index < count; index++) {
+ entry = ipc_call_list_entry_extract(message->data, message->size, index);
+ if (entry == NULL)
+ goto error;
- for (i = 0 ; i < count ; i++) {
- if (((int) entry - (int) info->data) >= (int) info->length)
+ number = ipc_call_list_entry_number_extract(entry);
+ if (number == NULL)
goto error;
- number = ((char *) entry) + sizeof(struct ipc_call_list_entry);
-
- current_calls[i] = (RIL_Call *) calloc(1, sizeof(RIL_Call));
-
- current_calls[i]->state = ipc2ril_call_list_entry_state(entry->state);
- current_calls[i]->index = entry->idx;
- current_calls[i]->toa = (entry->number_len > 0 && number[0] == '+') ? 145 : 129;
- current_calls[i]->isMpty = entry->mpty;
- current_calls[i]->isMT = (entry->term == IPC_CALL_TERM_MT);
- current_calls[i]->als = 0;
- current_calls[i]->isVoice = (entry->type == IPC_CALL_TYPE_VOICE);
- current_calls[i]->isVoicePrivacy = 0;
- current_calls[i]->number = strdup(number);
- current_calls[i]->numberPresentation = (entry->number_len > 0) ? 0 : 2;
- current_calls[i]->name = NULL;
- current_calls[i]->namePresentation = 2;
- current_calls[i]->uusInfo = NULL;
-
- entry = (struct ipc_call_list_entry *) (number + entry->number_len);
+ calls[index] = (RIL_Call *) calloc(1, sizeof(RIL_Call));
+ calls[index]->state = ipc2ril_call_list_entry_state(entry->status);
+ calls[index]->index = entry->id;
+ calls[index]->isMpty = entry->mpty;
+ calls[index]->isMT = entry->term == IPC_CALL_TERM_MT;
+ calls[index]->als = 0;
+ calls[index]->isVoice = entry->type == IPC_CALL_TYPE_VOICE;
+ calls[index]->isVoicePrivacy = 0;
+ calls[index]->number = strdup(number);
+ calls[index]->numberPresentation = (entry->number_length > 0) ? 0 : 2;
+ calls[index]->name = NULL;
+ calls[index]->namePresentation = 2;
+ calls[index]->uusInfo = NULL;
+
+ if (entry->number_length > 0 && number != NULL && number[0] == '+')
+ calls[index]->toa = 145;
+ else
+ calls[index]->toa = 129;
+
+ calls_count++;
}
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, current_calls, (count * sizeof(RIL_Call *)));
+ calls_size = calls_count * sizeof(RIL_Call *);
- for (i = 0 ; i < count ; i++) {
- if (current_calls[i]->number != NULL)
- free(current_calls[i]->number);
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) calls, calls_size);
- free(current_calls[i]);
- }
+ goto complete;
- free(current_calls);
+error:
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
+complete:
+ if (calls != NULL && calls_size > 0) {
+ for (index = 0; index < calls_count; index++) {
+ if (calls[index] == NULL)
+ continue;
-error:
- if (current_calls != NULL) {
- for (i = 0 ; i < count ; i++) {
- if (current_calls[i]->number != NULL)
- free(current_calls[i]->number);
+ if (calls[index]->number != NULL)
+ free(calls[index]->number);
- free(current_calls[i]);
+ free(calls[index]);
}
- free(current_calls);
+ free(calls);
}
- if (info->type == IPC_TYPE_RESP)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ return 0;
}
-void ril_request_hangup(RIL_Token t)
+int ril_request_get_current_calls(void *data, size_t size, RIL_Token token)
{
- ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_RELEASE);
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_SUCCESS, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
- ipc_fmt_send_exec(IPC_CALL_RELEASE, ril_request_get_id(t));
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_CALL_LIST, IPC_TYPE_GET, NULL, 0);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+ return RIL_REQUEST_HANDLED;
}
-
-void ril_request_answer(RIL_Token t)
+int ipc_call_cont_dtmf_callback(struct ipc_message *message)
{
- ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_ANSWER);
+ struct ipc_gen_phone_res_data *data;
+ void *dtmf_data;
+ size_t dtmf_size;
+ char tone;
+ int rc;
- ipc_fmt_send_exec(IPC_CALL_ANSWER, ril_request_get_id(t));
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data))
+ return -1;
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+ data = (struct ipc_gen_phone_res_data *) message->data;
+
+ rc = ipc_gen_phone_res_check(data);
+ if (rc < 0)
+ goto error;
+
+ dtmf_size = ril_request_data_size_get(RIL_REQUEST_DTMF_START);
+ dtmf_data = ril_request_data_get(RIL_REQUEST_DTMF_START);
+
+ if (dtmf_data != NULL && dtmf_size >= sizeof(tone)) {
+ tone = *((char *) dtmf_data);
+
+ // Register a new DTMF tone
+ ril_request_data_set(RIL_REQUEST_DTMF_START, dtmf_data, dtmf_size);
+
+ free(dtmf_data);
+
+ rc = ril_request_dtmf_start_complete(message->aseq, tone);
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_DTMF_START);
+ goto error;
+ }
+ }
+
+ dtmf_size = ril_request_data_size_get(RIL_REQUEST_DTMF);
+ dtmf_data = ril_request_data_get(RIL_REQUEST_DTMF);
+
+ if (dtmf_data != NULL && dtmf_size >= sizeof(tone)) {
+ tone = *((char *) dtmf_data);
+
+ free(dtmf_data);
+
+ rc = ril_request_dtmf_complete(message->aseq, tone);
+ if (rc < 0)
+ goto error;
+ }
+
+ goto complete;
+
+error:
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ return 0;
}
-void ril_request_last_call_fail_cause(RIL_Token t)
+int ipc_call_burst_dtmf(struct ipc_message *message)
{
- RIL_LastCallFailCause fail_cause;
- struct ipc_call_status *call_status = &(ril_data.state.call_status);
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_call_burst_dtmf_response_data))
+ return -1;
- fail_cause = ipc2ril_call_fail_cause(call_status->end_cause);
+ if (!ipc_seq_valid(message->aseq))
+ return 0;
- // Empty global call_status
- memset(call_status, 0, sizeof(struct ipc_call_status));
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0);
- ril_request_complete(t, RIL_E_SUCCESS, &fail_cause, sizeof(RIL_LastCallFailCause));
+ return 0;
}
-void ril_request_dtmf(RIL_Token t, void *data, int length)
+int ril_request_dtmf_complete(unsigned char aseq, char tone)
{
- struct ipc_call_cont_dtmf cont_dtmf;
- unsigned char tone;
- unsigned char count;
+ struct ipc_call_burst_dtmf_request_entry entry;
+ void *request_data = NULL;
+ size_t request_size = 0;
+ int rc;
- unsigned char *burst;
- int burst_length;
+ memset(&entry, 0, sizeof(entry));
+ entry.status = IPC_CALL_DTMF_STATUS_START;
+ entry.tone = tone;
- int i;
+ request_size = ipc_call_burst_dtmf_size_setup(&entry, 1);
+ if (request_size == 0)
+ goto error;
- if (data == NULL || length < (int) sizeof(unsigned char))
+ request_data = ipc_call_burst_dtmf_setup(&entry, 1);
+ if (request_data == NULL)
goto error;
- tone = *((unsigned char *) data);
- count = 1;
+ rc = ipc_gen_phone_res_expect_abort(aseq, IPC_CALL_BURST_DTMF);
+ if (rc < 0)
+ goto error;
- if (ril_data.state.dtmf_tone != 0) {
- RIL_LOGD("Another tone wasn't stopped, stopping it before anything");
+ rc = ipc_fmt_send(aseq, IPC_CALL_BURST_DTMF, IPC_TYPE_EXEC, request_data, request_size);
+ if (rc < 0)
+ goto error;
- cont_dtmf.state = IPC_CALL_DTMF_STATE_STOP;
- cont_dtmf.tone = 0;
+ rc = 0;
+ goto complete;
- ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (void *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t));
+error:
+ rc = -1;
- usleep(300);
- }
+complete:
+ if (request_data != NULL && request_size > 0)
+ free(request_data);
- burst_length = sizeof(struct ipc_call_cont_dtmf) * count + 1;
- burst = calloc(1, burst_length);
+ return rc;
+}
- burst[0] = count;
+int ril_request_dtmf(void *data, size_t size, RIL_Token token)
+{
+ struct ril_request *request;
+ void *dtmf_data;
+ size_t dtmf_size;
+ char tone;
+ int rc;
- // Apparently, it's possible to set multiple DTMF tones on this message
- for (i = 0 ; i < count ; i++) {
- cont_dtmf.state = IPC_CALL_DTMF_STATE_START;
- cont_dtmf.tone = tone;
+ if (data == NULL || size < sizeof(char))
+ goto error;
- memcpy(burst + 1 + sizeof(struct ipc_call_cont_dtmf) * i, &cont_dtmf, sizeof(cont_dtmf));
- }
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- ipc_gen_phone_res_expect_to_abort(ril_request_get_id(t), IPC_CALL_BURST_DTMF);
+ request = ril_request_find_request_status(RIL_REQUEST_DTMF, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
- ipc_fmt_send(IPC_CALL_BURST_DTMF, IPC_TYPE_EXEC, burst, burst_length, ril_request_get_id(t));
+ request = ril_request_find_request_status(RIL_REQUEST_DTMF_START, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
- free(burst);
+ request = ril_request_find_request_status(RIL_REQUEST_DTMF_STOP, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
- return;
+ tone = *((char *) data);
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
+ // A previous DTMF tone was started
+ dtmf_size = ril_request_data_size_get(RIL_REQUEST_DTMF_START);
+ dtmf_data = ril_request_data_get(RIL_REQUEST_DTMF_START);
-void ipc_call_burst_dtmf(struct ipc_message_info *info)
-{
- unsigned char code;
+ if (dtmf_data != NULL && dtmf_size >= sizeof(tone)) {
+ free(dtmf_data);
- if (info->data == NULL || info->length < sizeof(unsigned char))
- goto error;
+ // Let the callback know what to do after completing the previous DTMF tone
+ ril_request_data_set(RIL_REQUEST_DTMF, data, size);
- code = *((unsigned char *) info->data);
+ rc = ril_request_dtmf_stop_complete(ipc_fmt_request_seq(token), 1);
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_DTMF);
+ goto error;
+ }
- // This apparently should return 1, or perhaps that is the DTMF tones count
- if (code == 0) {
- RIL_LOGD("Apparently, something went wrong with DTMF burst (code=0x%x)", code);
- goto error;
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
}
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0);
+ rc = ril_request_dtmf_complete(ipc_fmt_request_seq(token), tone);
+ if (rc < 0)
+ goto error;
- return;
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ril_request_dtmf_start_complete(unsigned char aseq, char tone)
+{
+ struct ipc_call_cont_dtmf_data request_data;
+ int rc;
+
+ memset(&request_data, 0, sizeof(request_data));
+ request_data.status = IPC_CALL_DTMF_STATUS_START;
+ request_data.tone = tone;
+
+ rc = ipc_gen_phone_res_expect_complete(aseq, IPC_CALL_CONT_DTMF);
+ if (rc < 0)
+ return -1;
+
+ rc = ipc_fmt_send(aseq, IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ return -1;
+
+ return 0;
}
-void ril_request_dtmf_start(RIL_Token t, void *data, int length)
+int ril_request_dtmf_start(void *data, size_t size, RIL_Token token)
{
- struct ipc_call_cont_dtmf cont_dtmf;
- unsigned char tone;
+ struct ril_request *request;
+ void *dtmf_data;
+ size_t dtmf_size;
+ char tone;
+ int rc;
- if (data == NULL || length < (int) sizeof(unsigned char))
+ if (data == NULL || size < sizeof(char))
goto error;
- tone = *((unsigned char *) data);
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- if (ril_data.state.dtmf_tone != 0) {
- RIL_LOGD("Another tone wasn't stopped, stopping it before anything");
+ request = ril_request_find_request_status(RIL_REQUEST_DTMF, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
- cont_dtmf.state = IPC_CALL_DTMF_STATE_STOP;
- cont_dtmf.tone = 0;
+ request = ril_request_find_request_status(RIL_REQUEST_DTMF_START, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
- ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (unsigned char *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t));
+ request = ril_request_find_request_status(RIL_REQUEST_DTMF_STOP, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
- usleep(300);
- }
+ tone = *((char *) data);
- ril_data.state.dtmf_tone = cont_dtmf.tone;
+ // A previous DTMF tone was started
+ dtmf_size = ril_request_data_size_get(RIL_REQUEST_DTMF_START);
+ dtmf_data = ril_request_data_get(RIL_REQUEST_DTMF_START);
- cont_dtmf.state = IPC_CALL_DTMF_STATE_START;
- cont_dtmf.tone = tone;
+ if (dtmf_data != NULL && dtmf_size >= sizeof(tone)) {
+ free(dtmf_data);
- ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_CONT_DTMF);
+ // Let the callback know what to do after completing the previous DTMF tone
+ ril_request_data_set(RIL_REQUEST_DTMF_START, data, size);
- ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (unsigned char *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t));
+ rc = ril_request_dtmf_stop_complete(ipc_fmt_request_seq(token), 1);
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_DTMF_START);
+ goto error;
+ }
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+ }
+
+ // Register a new DTMF tone
+ ril_request_data_set(RIL_REQUEST_DTMF_START, data, size);
+
+ rc = ril_request_dtmf_start_complete(ipc_fmt_request_seq(token), tone);
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_DTMF_START);
+ goto error;
+ }
- return;
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
}
-void ril_request_dtmf_stop(RIL_Token t)
+int ril_request_dtmf_stop_complete(unsigned char aseq, int callback)
{
- struct ipc_call_cont_dtmf cont_dtmf;
+ struct ipc_call_cont_dtmf_data request_data;
+ int rc;
+
+ memset(&request_data, 0, sizeof(request_data));
+ request_data.status = IPC_CALL_DTMF_STATUS_STOP;
+ request_data.tone = 0;
+
+ if (callback)
+ rc = ipc_gen_phone_res_expect_callback(aseq, IPC_CALL_CONT_DTMF, ipc_call_cont_dtmf_callback);
+ else
+ rc = ipc_gen_phone_res_expect_complete(aseq, IPC_CALL_CONT_DTMF);
- ril_data.state.dtmf_tone = 0;
+ if (rc < 0)
+ return -1;
- cont_dtmf.state = IPC_CALL_DTMF_STATE_STOP;
- cont_dtmf.tone = 0;
+ rc = ipc_fmt_send(aseq, IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ return -1;
- ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_CONT_DTMF);
+ return 0;
+}
+
+int ril_request_dtmf_stop(void *data, size_t size, RIL_Token token)
+{
+ struct ril_request *request;
+ void *dtmf_data;
+ size_t dtmf_size;
+ int rc;
+
+ request = ril_request_find_request_status(RIL_REQUEST_DTMF, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_DTMF_START, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_DTMF_STOP, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ // Clear the DTMF tone
+ dtmf_size = ril_request_data_size_get(RIL_REQUEST_DTMF_START);
+ dtmf_data = ril_request_data_get(RIL_REQUEST_DTMF_START);
+
+ if (dtmf_data != NULL && dtmf_size >= sizeof(char))
+ free(dtmf_data);
+
+ rc = ril_request_dtmf_stop_complete(ipc_fmt_request_seq(token), 0);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
- ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (unsigned char *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t));
+ return RIL_REQUEST_HANDLED;
}