diff options
Diffstat (limited to 'call.c')
-rw-r--r-- | call.c | 318 |
1 files changed, 157 insertions, 161 deletions
@@ -24,13 +24,24 @@ #include "samsung-ril.h" -/* - * Format conversion utils - */ +unsigned char ril2ipc_call_identity(int clir) +{ + switch (clir) { + case 0: + return IPC_CALL_IDENTITY_DEFAULT; + case 1: + return IPC_CALL_IDENTITY_SHOW; + case 2: + return IPC_CALL_IDENTITY_HIDE; + default: + LOGE("Unknown call identity: 0x%x", clir); + return IPC_CALL_IDENTITY_DEFAULT; + } +} unsigned char ipc2ril_call_list_entry_state(unsigned char call_state) { - switch(call_state) { + switch (call_state) { case IPC_CALL_LIST_ENTRY_STATE_ACTIVE: return RIL_CALL_ACTIVE; case IPC_CALL_LIST_ENTRY_STATE_HOLDING: @@ -44,223 +55,184 @@ unsigned char ipc2ril_call_list_entry_state(unsigned char call_state) case IPC_CALL_LIST_ENTRY_STATE_WAITING: return RIL_CALL_WAITING; default: - LOGE("Unknown IPC_CALL_LIST_ENTRY_STATE!"); + LOGE("Unknown call list entry state: 0x%x", call_state); return -1; } } RIL_LastCallFailCause ipc2ril_call_fail_cause(unsigned char end_cause) { - switch(end_cause) { + switch (end_cause) { case IPC_CALL_END_CAUSE_NORMAL: case IPC_CALL_END_CAUSE_REJECTED: return CALL_FAIL_NORMAL; case IPC_CALL_END_CAUSE_UNSPECIFIED: default: + LOGE("Unknown call fail cause: 0x%x", end_cause); return CALL_FAIL_ERROR_UNSPECIFIED; } } -/* - * In: RIL_UNSOL_CALL_RING - * Ring indication for an incoming call (eg, RING or CRING event). - */ void ipc_call_incoming(struct ipc_message_info *info) { ril_request_unsolicited(RIL_UNSOL_CALL_RING, NULL, 0); - /* FIXME: Do we really need to send this? */ ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0); } -/* - * In: IPC_CALL_STATUS - * Indicates that a call's status has changed - * - * RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED - * Indicate when call state has changed - */ void ipc_call_status(struct ipc_message_info *info) { - struct ipc_call_status *call_status = - (struct ipc_call_status *) info->data; + struct ipc_call_status *call_status; - memcpy(&(ril_data.state.call_status), call_status, sizeof(struct ipc_call_status)); + if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_call_status)) + return; + + call_status = (struct ipc_call_status *) info->data; - LOGD("Updating Call Status data"); + LOGD("Updating call status data"); + memcpy(&(ril_data.state.call_status), call_status, sizeof(struct ipc_call_status)); ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0); } -/* - * In: RIL_REQUEST_DIAL - * Initiate voice call - * - * Out: IPC_CALL_OUTGOING - */ -void ril_request_dial(RIL_Token t, void *data, size_t datalen) +void ril_request_dial(RIL_Token t, void *data, size_t length) { - const RIL_Dial *dial = (const RIL_Dial*)data; + RIL_Dial *dial; struct ipc_call_outgoing call; int clir; + if (data == NULL || length < sizeof(RIL_Dial)) + goto error; + + dial = (RIL_Dial *) data; + if (strlen(dial->address) > sizeof(call.number)) { printf("Outgoing call number too long\n"); - return; - } - - /* FIXME: separate method? */ - switch(dial->clir) { - case 0: - clir = IPC_CALL_IDENTITY_DEFAULT; - break; - case 1: - clir = IPC_CALL_IDENTITY_SHOW; - break; - case 2: - clir = IPC_CALL_IDENTITY_HIDE; - break; - default: - clir = IPC_CALL_IDENTITY_DEFAULT; - break; + goto error; } - memset(&call, 0x00, sizeof(call)); - + memset(&call, 0, sizeof(call)); call.type = IPC_CALL_TYPE_VOICE; - call.identity = clir; + 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)); + ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_OUTGOING); + ipc_fmt_send(IPC_CALL_OUTGOING, IPC_TYPE_EXEC, (unsigned char *) &call, sizeof(call), ril_request_get_id(t)); - /* FIXME: This should actually be sent based on the response from baseband */ - ril_request_complete(t, RIL_E_SUCCESS, NULL, 0); + return; + +error: + ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); } -/* - * In: RIL_REQUEST_GET_CURRENT_CALLS - * Requests current call list - * - * Out: IPC_CALL_LIST GET - * Requests a list of active calls - */ void ril_request_get_current_calls(RIL_Token t) { ipc_fmt_send_get(IPC_CALL_LIST, ril_request_get_id(t)); } -/* - * In: IPC_CALL_LIST GET - * Provides a list of active calls - * - * Out: RIL_REQUEST_GET_CURRENT_CALLS - * Requests current call list - */ void ipc_call_list(struct ipc_message_info *info) { struct ipc_call_list_entry *entry; - unsigned char num_entries; - char *number, *number_ril; + unsigned char count; + char *number; + RIL_Call **current_calls = NULL; int i; - num_entries = *((unsigned char *) info->data); + if (info == NULL || info->data == NULL || info->length < sizeof(unsigned char)) + goto error; - if (num_entries == 0) { - // Don't bother with mem alloc + if (info->type != IPC_TYPE_RESP) + return; + count = *((unsigned char *) info->data); + if (count == 0) { ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0); return; } - entry = (struct ipc_call_list_entry *) ((char *) info->data + 1); + current_calls = (RIL_Call **) calloc(1, count * sizeof(RIL_Call *)); + entry = (struct ipc_call_list_entry *) ((char *) info->data + sizeof(unsigned char)); - RIL_Call **calls = (RIL_Call **) malloc(num_entries * sizeof(RIL_Call *)); + for (i=0 ; i < count ; i++) { + if (((int) entry - (int) info->data) >= (int) info->length) + goto error; - for (i = 0; i < num_entries; i++) { - RIL_Call *call = (RIL_Call *) malloc(sizeof(RIL_Call)); + number = ((char *) entry) + sizeof(struct ipc_call_list_entry); - /* Number is located after call list entry */ - number = ((char *) entry) + sizeof(*entry); + current_calls[i] = (RIL_Call *) calloc(1, sizeof(RIL_Call)); - number_ril = (char *) malloc(entry->number_len + 1); - memset(number_ril, 0, (entry->number_len + 1)); - memcpy(number_ril, number, entry->number_len); + 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; - call->state = ipc2ril_call_list_entry_state(entry->state); - call->index = (entry->idx+1); - call->toa = (entry->number_len > 0 && number[0] == '+') ? 145 : 129; - call->isMpty = entry->mpty; - call->isMT = (entry->term == IPC_CALL_TERM_MT); - call->als = 0; - call->isVoice = (entry->type == IPC_CALL_TYPE_VOICE); - call->isVoicePrivacy = 0; - call->number = number_ril; - call->numberPresentation = (entry->number_len > 0) ? 0 : 2; - call->name = NULL; - call->namePresentation = 2; - call->uusInfo = NULL; + entry = (struct ipc_call_list_entry *) (number + entry->number_len); + } - calls[i] = call; + ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, current_calls, (count * sizeof(RIL_Call *))); - /* Next entry after current number */ - entry = (struct ipc_call_list_entry *) (number + entry->number_len); + for (i=0 ; i < count ; i++) { + if (current_calls[i]->number != NULL) + free(current_calls[i]->number); + + free(current_calls[i]); } - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, calls, (num_entries * sizeof(RIL_Call *))); + free(current_calls); + + return; - for (i = 0; i < num_entries; i++) { - free(calls[i]); +error: + if (current_calls != NULL) { + for (i=0 ; i < count ; i++) { + if (current_calls[i]->number != NULL) + free(current_calls[i]->number); + + free(current_calls[i]); + } + + free(current_calls); } - free(calls); + if (info != NULL && info->type == IPC_TYPE_RESP) + ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); } -/* - * In: RIL_REQUEST_HANGUP - * Hang up a specific line (like AT+CHLD=1x) - * - * Out: IPC_CALL_RELEASE EXEC - */ void ril_request_hangup(RIL_Token t) { - ipc_fmt_send_exec(IPC_CALL_RELEASE, ril_request_get_id(t)); + ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_RELEASE); - /* FIXME: This should actually be sent based on the response from baseband */ - ril_request_complete(t, RIL_E_SUCCESS, NULL, 0); + ipc_fmt_send_exec(IPC_CALL_RELEASE, ril_request_get_id(t)); - /* FIXME: Do we really need to send this? */ ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0); } -/* - * In: RIL_REQUEST_ANSWER - * Answer incoming call - * - * Out: IPC_CALL_ANSWER - */ + void ril_request_answer(RIL_Token t) { - ipc_fmt_send_exec(IPC_CALL_ANSWER, ril_request_get_id(t)); + ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_ANSWER); - /* FIXME: This should actually be sent based on the response from baseband */ - ril_request_complete(t, RIL_E_SUCCESS, NULL, 0); + ipc_fmt_send_exec(IPC_CALL_ANSWER, ril_request_get_id(t)); - /* FIXME: Do we really need to send this? */ ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0); } -/* - * In: RIL_REQUEST_LAST_CALL_FAIL_CAUSE - * Reason why last call was terminated - */ void ril_request_last_call_fail_cause(RIL_Token t) { RIL_LastCallFailCause fail_cause; - struct ipc_call_status *call_status = - &(ril_data.state.call_status); + struct ipc_call_status *call_status = &(ril_data.state.call_status); fail_cause = ipc2ril_call_fail_cause(call_status->end_cause); @@ -270,26 +242,25 @@ void ril_request_last_call_fail_cause(RIL_Token t) ril_request_complete(t, RIL_E_SUCCESS, &fail_cause, sizeof(RIL_LastCallFailCause)); } -/* - * In: IPC_CALL_BURST_DTMF - * Send DTMF burst. RILJ only sends 1 DTMF tone to send at a time. - * - * Out: IPC_CALL_BURST_DTMF - * It should be possible to send multiple DTMF tones at once in this message. - * First byte should be DTMF tones count. - */ void ril_request_dtmf(RIL_Token t, void *data, int length) { struct ipc_call_cont_dtmf cont_dtmf; + unsigned char tone; + unsigned char count; unsigned char *burst; - int burst_len; + int burst_length; - unsigned char dtmf_count = 1; int i; + if (data == NULL || length < (int) sizeof(unsigned char)) + goto error; + + tone = *((unsigned char *) data); + count = 1; + if (ril_data.state.dtmf_tone != 0) { - LOGD("Another tone wasn't stopped, stopping that one before anything"); + LOGD("Another tone wasn't stopped, stopping it before anything"); cont_dtmf.state = IPC_CALL_DTMF_STATE_STOP; cont_dtmf.tone = 0; @@ -299,76 +270,101 @@ void ril_request_dtmf(RIL_Token t, void *data, int length) usleep(300); } - burst_len = sizeof(struct ipc_call_cont_dtmf) * dtmf_count + 1; - burst = malloc(burst_len); - memset(burst, 0, burst_len); + burst_length = sizeof(struct ipc_call_cont_dtmf) * count + 1; + burst = calloc(1, burst_length); - burst[0] = dtmf_count; - - for (i=0 ; i < dtmf_count ; i++) { - // Apparently, it's possible to set multiple DTMF tones on this message + burst[0] = count; + // 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 = ((char *) data)[0]; + cont_dtmf.tone = tone; memcpy(burst + 1 + sizeof(struct ipc_call_cont_dtmf) * i, &cont_dtmf, sizeof(cont_dtmf)); } ipc_gen_phone_res_expect_to_abort(ril_request_get_id(t), IPC_CALL_BURST_DTMF); - ipc_fmt_send(IPC_CALL_BURST_DTMF, IPC_TYPE_EXEC, (void *) burst, burst_len, ril_request_get_id(t)); + ipc_fmt_send(IPC_CALL_BURST_DTMF, IPC_TYPE_EXEC, burst, burst_length, ril_request_get_id(t)); free(burst); + + return; + +error: + ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); } void ipc_call_burst_dtmf(struct ipc_message_info *info) { - unsigned char ret = *((unsigned char *) info->data); + unsigned char code; - // This apparently should return 1, or perhaps that is the DTMF tones count - if (ret == 0) { - LOGD("Apparently, something went wrong with DTMF burst"); + if (info == NULL || info->data == NULL || info->length < sizeof(unsigned char)) + goto error; - ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); + code = *((unsigned char *) info->data); + + // This apparently should return 1, or perhaps that is the DTMF tones count + if (code == 0) { + LOGD("Apparently, something went wrong with DTMF burst (code=0x%x)", code); + goto error; } ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0); + + return; + +error: + if (info != NULL) + ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0); } void ril_request_dtmf_start(RIL_Token t, void *data, int length) { struct ipc_call_cont_dtmf cont_dtmf; + unsigned char tone; + + if (data == NULL || length < (int) sizeof(unsigned char)) + goto error; + + tone = *((unsigned char *) data); if (ril_data.state.dtmf_tone != 0) { - LOGD("Another tone wasn't stopped, stopping that one before anything"); + LOGD("Another tone wasn't stopped, stopping it before anything"); cont_dtmf.state = IPC_CALL_DTMF_STATE_STOP; cont_dtmf.tone = 0; - ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (void *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t)); + ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (unsigned char *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t)); usleep(300); } - cont_dtmf.state = IPC_CALL_DTMF_STATE_START; - cont_dtmf.tone = ((unsigned char *)data)[0]; - ril_data.state.dtmf_tone = cont_dtmf.tone; + cont_dtmf.state = IPC_CALL_DTMF_STATE_START; + cont_dtmf.tone = tone; + ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_CONT_DTMF); - ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (void *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t)); + ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (unsigned char *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t)); + + return; + +error: + ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0); } void ril_request_dtmf_stop(RIL_Token t) { struct ipc_call_cont_dtmf cont_dtmf; - cont_dtmf.state = IPC_CALL_DTMF_STATE_STOP; - cont_dtmf.tone = 0; ril_data.state.dtmf_tone = 0; + cont_dtmf.state = IPC_CALL_DTMF_STATE_STOP; + cont_dtmf.tone = 0; + ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_CALL_CONT_DTMF); - ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (void *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t)); + ipc_fmt_send(IPC_CALL_CONT_DTMF, IPC_TYPE_SET, (unsigned char *) &cont_dtmf, sizeof(cont_dtmf), ril_request_get_id(t)); } |