summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2014-08-07 13:12:15 +0200
committerPaul Kocialkowski <contact@paulk.fr>2014-08-07 13:12:15 +0200
commita7ff1df1869ce543171a6ee92cbf821647b1bf7d (patch)
tree659e315b3d609f0f9e661d4de21b52077e6e2b81
parentc8408cd2c116b0b99a399282032b6607a1318b84 (diff)
downloadhardware_ril_samsung-ril-a7ff1df1869ce543171a6ee92cbf821647b1bf7d.zip
hardware_ril_samsung-ril-a7ff1df1869ce543171a6ee92cbf821647b1bf7d.tar.gz
hardware_ril_samsung-ril-a7ff1df1869ce543171a6ee92cbf821647b1bf7d.tar.bz2
Samsung-RIL rewrite: harder, better, probably not faster but definitely stronger
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
-rw-r--r--Android.mk44
-rw-r--r--call.c683
-rw-r--r--client.c243
-rw-r--r--data.c1049
-rw-r--r--disp.c160
-rw-r--r--gen.c275
-rw-r--r--gprs.c1075
-rw-r--r--include/plmn_list.h611
-rwxr-xr-xinclude/plmn_list.sh31
-rw-r--r--include/ril_oem.h52
-rw-r--r--include/samsung-ril-socket.h84
-rw-r--r--include/sim.h60
-rw-r--r--ipc.c1106
-rw-r--r--ipc.h110
-rw-r--r--misc.c362
-rw-r--r--net.c916
-rw-r--r--network.c1168
-rw-r--r--oem.c238
-rw-r--r--power.c117
-rw-r--r--pwr.c110
-rw-r--r--rfs.c148
-rw-r--r--samsung-ril.c1812
-rw-r--r--samsung-ril.h716
-rw-r--r--sat.c166
-rw-r--r--sec.c981
-rw-r--r--sim.c1303
-rw-r--r--sms.c1041
-rw-r--r--snd.c132
-rw-r--r--sound.c159
-rw-r--r--srs-client/include/srs-client.h47
-rw-r--r--srs-client/srs-client.c551
-rw-r--r--srs.c1181
-rw-r--r--srs.h95
-rw-r--r--ss.c251
-rw-r--r--svc.c244
-rw-r--r--util.c486
-rw-r--r--utils.c247
-rw-r--r--utils.h (renamed from util.h)36
38 files changed, 10318 insertions, 7772 deletions
diff --git a/Android.mk b/Android.mk
index 08b4f48..29f0c24 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,7 +1,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
@@ -25,38 +25,32 @@ LOCAL_SRC_FILES := \
client.c \
ipc.c \
srs.c \
- util.c \
- gen.c \
- pwr.c \
- disp.c \
- misc.c \
- sat.c \
- ss.c \
- sec.c \
- svc.c \
- net.c \
- sms.c \
+ utils.c \
+ power.c \
call.c \
- snd.c \
- gprs.c \
- rfs.c
+ sms.c \
+ sim.c \
+ network.c \
+ sound.c \
+ misc.c \
+ oem.c \
+ data.c \
+ rfs.c \
+ gen.c
LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH) \
+ $(LOCAL_PATH)/include \
external/libsamsung-ipc/include \
- $(LOCAL_PATH)/include
+ hardware/libhardware_legacy/include \
+ system/core/include
-LOCAL_CFLAGS := -D_GNU_SOURCE -DRIL_SHLIB
+LOCAL_CFLAGS := -DRIL_SHLIB
-# Disable STK
-LOCAL_CFLAGS += -DDISABLE_STK
-
-# Samsung-RIL only supports IPC V4
-LOCAL_CFLAGS += -DDEVICE_IPC_V4
-
-LOCAL_SHARED_LIBRARIES := libcutils libnetutils libutils liblog
+LOCAL_SHARED_LIBRARIES := libcutils libnetutils libutils liblog libpower
LOCAL_STATIC_LIBRARIES := libsamsung-ipc
-LOCAL_PRELINK_MODULE := false
+LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libsamsung-ril
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;
}
diff --git a/client.c b/client.c
index 92ebc2c..1e06554 100644
--- a/client.c
+++ b/client.c
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * 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
@@ -17,101 +17,115 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
#include <pthread.h>
#define LOG_TAG "RIL"
#include <utils/Log.h>
-#include "samsung-ril.h"
+#include <samsung-ril.h>
-struct ril_client *ril_client_new(struct ril_client_funcs *client_funcs)
+struct ril_client *ril_client_find_id(int id)
{
- struct ril_client *ril_client;
- int rc;
+ unsigned int i;
- ril_client = calloc(1, sizeof(struct ril_client));
+ if (ril_clients == NULL || ril_clients_count == 0)
+ return NULL;
- if (client_funcs != NULL) {
- ril_client->funcs.create = client_funcs->create;
- ril_client->funcs.destroy = client_funcs->destroy;
- ril_client->funcs.read_loop = client_funcs->read_loop;
- }
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
- pthread_mutex_init(&(ril_client->mutex), NULL);
+ if (ril_clients[i]->id == id)
+ return ril_clients[i];
+ }
- return ril_client;
+ return NULL;
}
-int ril_client_free(struct ril_client *client)
+int ril_client_create(struct ril_client *client)
{
+ int rc;
+
if (client == NULL)
return -1;
- pthread_mutex_destroy(&(client->mutex));
+ client->data = NULL;
+ pthread_mutex_init(&client->mutex, NULL);
+
+ if (client->handlers != NULL && client->handlers->create != NULL) {
+ rc = client->handlers->create(client);
+ if (rc < 0) {
+ RIL_LOGE("Creating %s client failed", client->name);
+ return -1;
+ }
+ }
- free(client);
+ RIL_LOGD("Created %s client", client->name);
return 0;
}
-int ril_client_create(struct ril_client *client)
+int ril_client_destroy(struct ril_client *client)
{
int rc;
- int c;
- if (client == NULL || client->funcs.create == NULL)
+ if (client == NULL)
return -1;
- for (c = RIL_CLIENT_MAX_TRIES ; c > 0 ; c--) {
- RIL_LOGD("Creating RIL client inners, try #%d", RIL_CLIENT_MAX_TRIES - c + 1);
+ if (client->handlers != NULL && client->handlers->destroy != NULL) {
+ rc = client->handlers->destroy(client);
+ if (rc < 0) {
+ RIL_LOGE("Destroying %s client failed", client->name);
+ return -1;
+ }
+ }
- rc = client->funcs.create(client);
- if (rc < 0)
- RIL_LOGE("RIL client inners creation failed");
- else
- break;
+ pthread_mutex_destroy(&client->mutex);
- usleep(500000);
- }
+ RIL_LOGD("Destroyed %s client", client->name);
+
+ return 0;
+}
- if (c == 0) {
- RIL_LOGE("RIL client inners creation failed too many times");
- client->state = RIL_CLIENT_ERROR;
+int ril_client_open(struct ril_client *client)
+{
+ int rc = 0;
+
+ if (client == NULL)
+ return -1;
+
+ if (client->handlers == NULL || client->handlers->open == NULL)
+ return -1;
+
+ rc = client->handlers->open(client);
+ if (rc < 0) {
+ RIL_LOGE("Opening %s client failed", client->name);
return -1;
}
- client->state = RIL_CLIENT_CREATED;
+ RIL_LOGD("Opened %s client", client->name);
return 0;
}
-int ril_client_destroy(struct ril_client *client)
+int ril_client_close(struct ril_client *client)
{
int rc;
- int c;
- if (client == NULL || client->funcs.destroy == NULL)
+ if (client == NULL)
return -1;
- for (c = RIL_CLIENT_MAX_TRIES ; c > 0 ; c--) {
- RIL_LOGD("Destroying RIL client inners, try #%d", RIL_CLIENT_MAX_TRIES - c + 1);
-
- rc = client->funcs.destroy(client);
- if (rc < 0)
- RIL_LOGE("RIL client inners destroying failed");
- else
- break;
-
- usleep(500000);
- }
+ if (client->handlers == NULL || client->handlers->close == NULL)
+ return -1;
- if (c == 0) {
- RIL_LOGE("RIL client inners destroying failed too many times");
- client->state = RIL_CLIENT_ERROR;
+ rc = client->handlers->close(client);
+ if (rc < 0) {
+ RIL_LOGE("Closing %s client failed", client->name);
return -1;
}
- client->state = RIL_CLIENT_DESTROYED;
+ RIL_LOGD("Closed %s client", client->name);
return 0;
}
@@ -120,69 +134,130 @@ void *ril_client_thread(void *data)
{
struct ril_client *client;
int rc;
- int c;
- if (data == NULL)
+ if (data == NULL || ril_data == NULL)
return NULL;
client = (struct ril_client *) data;
- if (client->funcs.read_loop == NULL)
- return NULL;
+ client->failures = 0;
- for (c = RIL_CLIENT_MAX_TRIES ; c > 0 ; c--) {
- client->state = RIL_CLIENT_READY;
+ do {
+ if (client->failures) {
+ usleep(RIL_CLIENT_RETRY_DELAY);
- rc = client->funcs.read_loop(client);
- if (rc < 0) {
- client->state = RIL_CLIENT_ERROR;
+ rc = ril_client_close(client);
+ if (rc < 0)
+ goto failure;
- RIL_LOGE("RIL client read loop failed");
+ if (client->failures > 1) {
+ rc = ril_client_destroy(client);
+ if (rc < 0)
+ goto failure;
- ril_client_destroy(client);
- ril_client_create(client);
+ rc = ril_client_create(client);
+ if (rc < 0)
+ goto failure;
+ }
- continue;
- } else {
- client->state = RIL_CLIENT_CREATED;
+ rc = ril_client_open(client);
+ if (rc < 0)
+ goto failure;
+ }
+
+ rc = client->handlers->loop(client);
+ if (rc < 0) {
+ RIL_LOGE("%s client loop failed", client->name);
+
+ if (client->critical) {
+ RIL_LOCK();
+ ril_radio_state_update(RADIO_STATE_UNAVAILABLE);
+ RIL_UNLOCK();
+ }
- RIL_LOGD("RIL client read loop ended");
+ goto failure;
+ } else {
+ RIL_LOGE("%s client loop terminated", client->name);
break;
}
- }
-
- if (c == 0) {
- RIL_LOGE("RIL client read loop failed too many times");
- client->state = RIL_CLIENT_ERROR;
- }
- // Destroy everything here
+failure:
+ client->failures++;
+ } while (client->failures < RIL_CLIENT_RETRY_COUNT);
- rc = ril_client_destroy(client);
- if (rc < 0)
- RIL_LOGE("RIL client destroy failed");
+ ril_client_close(client);
+ ril_client_destroy(client);
- rc = ril_client_free(client);
- if (rc < 0)
- RIL_LOGE("RIL client free failed");
+ RIL_LOGD("Stopped %s client loop", client->name);
- return 0;
+ return NULL;
}
-int ril_client_thread_start(struct ril_client *client)
+int ril_client_loop(struct ril_client *client)
{
pthread_attr_t attr;
int rc;
+ if (client == NULL)
+ return -1;
+
+ if (client->handlers == NULL || client->handlers->loop == NULL)
+ return -1;
+
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- rc = pthread_create(&(client->thread), &attr, ril_client_thread, (void *) client);
-
+ rc = pthread_create(&client->thread, &attr, ril_client_thread, (void *) client);
if (rc != 0) {
- RIL_LOGE("RIL client thread creation failed");
+ RIL_LOGE("Starting %s client loop failed", client->name);
return -1;
}
+ RIL_LOGD("Started %s client loop", client->name);
+
+ return 0;
+}
+
+int ril_client_request_register(struct ril_client *client, int request,
+ RIL_Token token)
+{
+ int rc = 0;
+
+ if (client == NULL || client->callbacks == NULL || client->callbacks->request_register == NULL)
+ return -1;
+
+ rc = client->callbacks->request_register(client, request, token);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int ril_client_request_unregister(struct ril_client *client, int request,
+ RIL_Token token)
+{
+ int rc = 0;
+
+ if (client == NULL || client->callbacks == NULL || client->callbacks->request_unregister == NULL)
+ return -1;
+
+ rc = client->callbacks->request_unregister(client, request, token);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int ril_client_flush(struct ril_client *client)
+{
+ int rc = 0;
+
+ if (client == NULL || client->callbacks == NULL || client->callbacks->flush == NULL)
+ return -1;
+
+ rc = client->callbacks->flush(client);
+ if (rc < 0)
+ return -1;
+
return 0;
}
diff --git a/data.c b/data.c
new file mode 100644
index 0000000..1aa69d1
--- /dev/null
+++ b/data.c
@@ -0,0 +1,1049 @@
+/*
+ * This file is part of Samsung-RIL.
+ *
+ * Copyright (C) 2011-2014 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2011 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Samsung-RIL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
+#include <netutils/ifc.h>
+
+#include <samsung-ril.h>
+#include <utils.h>
+
+int ipc2ril_gprs_fail_cause(unsigned char fail_cause)
+{
+ switch (fail_cause) {
+ case IPC_GPRS_FAIL_CAUSE_NONE:
+ case IPC_GPRS_FAIL_CAUSE_REL_BY_USER:
+ case IPC_GPRS_FAIL_CAUSE_REGULAR_DEACTIVATION:
+ return PDP_FAIL_NONE;
+ case IPC_GPRS_FAIL_CAUSE_INSUFFICIENT_RESOURCE:
+ return PDP_FAIL_INSUFFICIENT_RESOURCES;
+ case IPC_GPRS_FAIL_CAUSE_UNKNOWN_APN:
+ return PDP_FAIL_MISSING_UKNOWN_APN;
+ case IPC_GPRS_FAIL_CAUSE_UNKNOWN_PDP_ADDRESS:
+ return PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE;
+ case IPC_GPRS_FAIL_CAUSE_USER_AUTH_FAILED:
+ return PDP_FAIL_USER_AUTHENTICATION;
+ case IPC_GPRS_FAIL_CAUSE_ACT_REJ_GGSN:
+ return PDP_FAIL_ACTIVATION_REJECT_GGSN;
+ case IPC_GPRS_FAIL_CAUSE_ACT_REJ_UNSPECIFIED:
+ return PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED;
+ case IPC_GPRS_FAIL_CAUSE_SVC_OPTION_NOT_SUPPORTED:
+ return PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED;
+ case IPC_GPRS_FAIL_CAUSE_SVC_NOT_SUBSCRIBED:
+ return PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED;
+ case IPC_GPRS_FAIL_CAUSE_SVC_OPT_OUT_ORDER:
+ return PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER;
+ case IPC_GPRS_FAIL_CAUSE_NSAPI_USED:
+ return PDP_FAIL_NSAPI_IN_USE;
+ case IPC_GPRS_FAIL_CAUSE_NETWORK_FAILURE:
+ return PDP_FAIL_DATA_REGISTRATION_FAIL;
+ case IPC_GPRS_FAIL_CAUSE_UNKOWN_PDP_CONTEXT:
+ case IPC_GPRS_FAIL_CAUSE_INVALID_MSG:
+ case IPC_GPRS_FAIL_CAUSE_PROTOCOL_ERROR:
+ return PDP_FAIL_PROTOCOL_ERRORS;
+ case IPC_GPRS_FAIL_CAUSE_MOBILE_FAILURE_ERROR:
+ return PDP_FAIL_SIGNAL_LOST;
+ case IPC_GPRS_FAIL_CAUSE_UNKNOWN_ERROR:
+ default:
+ return PDP_FAIL_ERROR_UNSPECIFIED;
+ }
+}
+
+int ril_data_connection_register(unsigned int cid, char *apn, char *username,
+ char *password, char *iface)
+{
+ struct ril_data_connection *data_connection;
+ struct list_head *list_end;
+ struct list_head *list;
+ unsigned int i;
+
+ if (apn == NULL || ril_data == NULL)
+ return -1;
+
+ data_connection = (struct ril_data_connection *) calloc(1, sizeof(struct ril_data_connection));
+ data_connection->cid = cid;
+ data_connection->enabled = 0;
+ data_connection->apn = apn;
+ data_connection->username = username;
+ data_connection->password = password;
+ data_connection->iface = iface;
+
+ list_end = ril_data->data_connections;
+ while (list_end != NULL && list_end->next != NULL)
+ list_end = list_end->next;
+
+ list = list_head_alloc(list_end, NULL, (void *) data_connection);
+
+ if (ril_data->data_connections == NULL)
+ ril_data->data_connections = list;
+
+ return 0;
+}
+
+int ril_data_connection_unregister(struct ril_data_connection *data_connection)
+{
+ struct list_head *list;
+ unsigned int i;
+
+ if (data_connection == NULL || ril_data == NULL)
+ return -1;
+
+ list = ril_data->data_connections;
+ while (list != NULL) {
+ if (list->data == (void *) data_connection) {
+ memset(data_connection, 0, sizeof(struct ril_data_connection));
+ free(data_connection);
+
+ if (list == ril_data->data_connections)
+ ril_data->data_connections = list->next;
+
+ list_head_free(list);
+
+ break;
+ }
+
+list_continue:
+ list = list->next;
+ }
+
+ return 0;
+}
+
+int ril_data_connection_flush(void)
+{
+ struct ril_data_connection *data_connection;
+ struct list_head *list;
+ struct list_head *list_next;
+
+ if (ril_data == NULL)
+ return -1;
+
+ list = ril_data->data_connections;
+ while (list != NULL) {
+ if (list->data != NULL) {
+ data_connection = (struct ril_data_connection *) list->data;
+
+ ril_data_connection_stop(data_connection);
+
+ memset(data_connection, 0, sizeof(struct ril_data_connection));
+ free(data_connection);
+ }
+
+ if (list == ril_data->data_connections)
+ ril_data->data_connections = list->next;
+
+ list_next = list->next;
+
+ list_head_free(list);
+
+list_continue:
+ list = list_next;
+ }
+
+ return 0;
+}
+
+struct ril_data_connection *ril_data_connection_find_cid(unsigned int cid)
+{
+ struct ril_data_connection *data_connection;
+ struct list_head *list;
+
+ if (ril_data == NULL)
+ return NULL;
+
+ list = ril_data->data_connections;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ data_connection = (struct ril_data_connection *) list->data;
+
+ if (data_connection->cid == cid)
+ return data_connection;
+
+list_continue:
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+struct ril_data_connection *ril_data_connection_find_token(RIL_Token token)
+{
+ struct ril_data_connection *data_connection;
+ struct list_head *list;
+
+ if (ril_data == NULL)
+ return NULL;
+
+ list = ril_data->data_connections;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ data_connection = (struct ril_data_connection *) list->data;
+
+ if (data_connection->token == token)
+ return data_connection;
+
+list_continue:
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+struct ril_data_connection *ril_data_connection_start(char *apn, char *username,
+ char *password)
+{
+ struct ril_data_connection *data_connection;
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
+ struct ipc_client_gprs_capabilities gprs_capabilities;
+ char *iface = NULL;
+ unsigned int cid;
+ unsigned int i;
+ int rc;
+
+ if (apn == NULL)
+ goto error;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ goto error;
+
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+ if (ipc_fmt_data->ipc_client == NULL)
+ goto error;
+
+ rc = ipc_client_gprs_get_capabilities(ipc_fmt_data->ipc_client, &gprs_capabilities);
+ if (rc < 0)
+ goto error;
+
+ for (i = 0; i < gprs_capabilities.cid_count; i++) {
+ data_connection = ril_data_connection_find_cid(i + 1);
+ if (data_connection == NULL)
+ break;
+ }
+
+ cid = i + 1;
+
+ if (cid > gprs_capabilities.cid_count) {
+ RIL_LOGE("%s: No place left for a new data connection", __func__);
+ goto error;
+ }
+
+ iface = ipc_client_gprs_get_iface(ipc_fmt_data->ipc_client, cid);
+ if (iface == NULL)
+ goto error;
+
+ rc = ril_data_connection_register(cid, apn, username, password, iface);
+ if (rc < 0)
+ goto error;
+
+ data_connection = ril_data_connection_find_cid(cid);
+ if (data_connection == NULL)
+ goto error;
+
+ RIL_LOGD("Starting new data connection with cid: %d and iface: %s", cid, iface);
+
+ goto complete;
+
+error:
+ if (iface != NULL)
+ free(iface);
+
+ data_connection = NULL;
+
+complete:
+ return data_connection;
+}
+
+int ril_data_connection_stop(struct ril_data_connection *data_connection)
+{
+ int rc;
+
+ if (data_connection == NULL)
+ return -1;
+
+ if (data_connection->apn != NULL)
+ free(data_connection->apn);
+
+ if (data_connection->username != NULL)
+ free(data_connection->username);
+
+ if (data_connection->password != NULL)
+ free(data_connection->password);
+
+ if (data_connection->iface != NULL)
+ free(data_connection->iface);
+
+ if (data_connection->ip != NULL)
+ free(data_connection->ip);
+
+ if (data_connection->gateway != NULL)
+ free(data_connection->gateway);
+
+ if (data_connection->subnet_mask != NULL)
+ free(data_connection->subnet_mask);
+
+ if (data_connection->dns1 != NULL)
+ free(data_connection->dns1);
+
+ if (data_connection->dns2 != NULL)
+ free(data_connection->dns2);
+
+ rc = ril_data_connection_unregister(data_connection);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int ril_data_connection_enable(struct ril_data_connection *data_connection)
+{
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
+ in_addr_t ip_addr;
+ in_addr_t gateway_addr;
+ in_addr_t subnet_mask_addr;
+ in_addr_t dns1_addr;
+ in_addr_t dns2_addr;
+ int rc;
+
+ if (data_connection == NULL || data_connection->iface == NULL || data_connection->ip == NULL || data_connection->gateway == NULL || data_connection->subnet_mask == NULL)
+ return -1;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+ if (ipc_fmt_data->ipc_client == NULL)
+ return -1;
+
+ rc = ipc_client_gprs_activate(ipc_fmt_data->ipc_client, data_connection->cid);
+ if (rc < 0)
+ return -1;
+
+ ip_addr = inet_addr(data_connection->ip);
+ gateway_addr = inet_addr(data_connection->gateway);
+ subnet_mask_addr = inet_addr(data_connection->subnet_mask);
+
+ if (data_connection->dns1 != NULL)
+ dns1_addr = inet_addr(data_connection->dns1);
+ else
+ dns1_addr = 0;
+
+ if (data_connection->dns2 != NULL)
+ dns2_addr = inet_addr(data_connection->dns2);
+ else
+ dns2_addr = 0;
+
+ rc = ifc_configure(data_connection->iface, ip_addr, ipv4NetmaskToPrefixLength(subnet_mask_addr), gateway_addr, dns1_addr, dns2_addr);
+ if (rc < 0)
+ return -1;
+
+ data_connection->enabled = 1;
+
+ RIL_LOGD("%s: Enabled data connection with cid %d", __func__, data_connection->cid);
+
+ return 0;
+}
+
+int ril_data_connection_disable(struct ril_data_connection *data_connection)
+{
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
+ int rc;
+
+ if (data_connection == NULL || data_connection->iface == NULL)
+ return -1;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+ if (ipc_fmt_data->ipc_client == NULL)
+ return -1;
+
+ rc = ifc_reset_connections(data_connection->iface, RESET_IPV4_ADDRESSES);
+ if (rc < 0)
+ return -1;
+
+ rc = ifc_disable(data_connection->iface);
+ if (rc < 0)
+ return -1;
+
+ rc = ipc_client_gprs_deactivate(ipc_fmt_data->ipc_client, data_connection->cid);
+ if (rc < 0)
+ return -1;
+
+ data_connection->enabled = 0;
+
+ RIL_LOGD("%s: Disabled data connection with cid %d", __func__, data_connection->cid);
+
+ return 0;;
+}
+
+int ipc_gprs_define_pdp_context_callback(struct ipc_message *message)
+{
+ struct ipc_gprs_pdp_context_request_set_data request_data;
+ struct ril_data_connection *data_connection;
+ struct ipc_gen_phone_res_data *data;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data))
+ return -1;
+
+ data = (struct ipc_gen_phone_res_data *) message->data;
+
+ data_connection = ril_data_connection_find_token(ipc_fmt_request_token(message->aseq));
+ if (data_connection == NULL) {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ return 0;
+ }
+
+ rc = ipc_gen_phone_res_check(data);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_gprs_pdp_context_request_set_setup(&request_data, 1, data_connection->cid, data_connection->username, data_connection->password);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_gen_phone_res_expect_callback(message->aseq, IPC_GPRS_PDP_CONTEXT, ipc_gprs_pdp_context_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(message->aseq, IPC_GPRS_PDP_CONTEXT, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ goto complete;
+
+error:
+ ril_data_connection_stop(data_connection);
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ return 0;
+}
+
+int ril_request_setup_data_call(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_gprs_define_pdp_context_data request_data;
+ struct ril_data_connection *data_connection = NULL;
+ struct ril_request *request;
+ char *apn = NULL;
+ char *username = NULL;
+ char *password = NULL;
+ char **values = NULL;
+ unsigned int i;
+ int rc;
+
+ if (data == NULL || size < 6 * sizeof(char *))
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ request = ril_request_find_request_status(RIL_REQUEST_SETUP_DATA_CALL, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+
+ if (values[2] == NULL) {
+ RIL_LOGE("%s: No APN was provided", __func__);
+ goto error;
+ }
+
+ apn = strdup(values[2]);
+
+ if (values[3] != NULL)
+ username = strdup(values[3]);
+
+ if (values[4] != NULL)
+ password = strdup(values[4]);
+
+ strings_array_free(values, size);
+ values = NULL;
+
+ RIL_LOGD("Setting up data connection to APN: %s with username/password: %s/%s", apn, username, password);
+
+ data_connection = ril_data_connection_start(apn, username, password);
+ if (data_connection == NULL)
+ goto error;
+
+ data_connection->token = token;
+
+ rc = ipc_gprs_define_pdp_context_setup(&request_data, 1, data_connection->cid, data_connection->apn);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_GPRS_DEFINE_PDP_CONTEXT, ipc_gprs_define_pdp_context_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_GPRS_DEFINE_PDP_CONTEXT, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ if (data_connection != NULL) {
+ ril_data_connection_stop(data_connection);
+ } else {
+ if (apn != NULL)
+ free(apn);
+
+ if (username != NULL)
+ free(username);
+
+ if (password != NULL)
+ free(password);
+ }
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ipc_gprs_ps(struct ipc_message *message)
+{
+ struct ipc_gprs_ps_data *data;
+ struct ril_data_connection *data_connection;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gprs_ps_data))
+ return -1;
+
+ data = (struct ipc_gprs_ps_data *) message->data;
+
+ data_connection = ril_data_connection_find_cid(data->cid);
+ if (data_connection == NULL)
+ return 0;
+
+ data_connection->attached = !!data->attached;
+
+ return 0;
+}
+
+int ipc_gprs_pdp_context(struct ipc_message *message)
+{
+ struct ipc_gprs_pdp_context_request_get_data *data;
+ struct ril_data_connection *data_connection;
+#if RIL_VERSION >= 6
+ RIL_Data_Call_Response_v6 response[3];
+#else
+ RIL_Data_Call_Response response[3];
+#endif
+ unsigned int entries_count;
+ unsigned int index = 0;
+ size_t size;
+ unsigned int i;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gprs_pdp_context_request_get_data))
+ return -1;
+
+ data = (struct ipc_gprs_pdp_context_request_get_data *) message->data;
+
+ entries_count = sizeof(data->entries) / sizeof(struct ipc_gprs_pdp_context_request_get_entry);
+
+ memset(&response, 0, sizeof(response));
+
+ for (i = 0; i < entries_count; i++) {
+ if (!data->entries[i].active)
+ continue;
+
+ data_connection = ril_data_connection_find_cid(data->entries[i].cid);
+ if (data_connection == NULL)
+ continue;
+
+#if RIL_VERSION >= 6
+ response[index].status = PDP_FAIL_NONE;
+#endif
+ response[index].cid = data->entries[i].cid;
+
+ if (data_connection->enabled)
+ response[index].active = 2;
+ else
+ response[index].active = 0;
+
+ response[index].type = strdup("IP");
+#if RIL_VERSION >= 6
+ if (data_connection->iface != NULL)
+ response[index].ifname = strdup(data_connection->iface);
+
+ if (data_connection->ip != NULL)
+ response[index].addresses = strdup(data_connection->ip);
+
+ asprintf(&response[index].dnses, "%s %s", data_connection->dns1, data_connection->dns2);
+
+ if (data_connection->gateway != NULL)
+ response[index].gateways = strdup(data_connection->gateway);
+#else
+ if (data_connection->apn != NULL)
+ response[index].apn = strdup(data_connection->apn);
+
+ if (data_connection->ip != NULL)
+ response[index].address = strdup(data_connection->ip);
+#endif
+
+ index++;
+ }
+
+#if RIL_VERSION >= 6
+ size = index * sizeof(RIL_Data_Call_Response_v6);
+#else
+ size = index * sizeof(RIL_Data_Call_Response);
+#endif
+
+ if (!ipc_seq_valid(message->aseq))
+ ril_request_unsolicited(RIL_UNSOL_DATA_CALL_LIST_CHANGED, &response, size);
+ else
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &response, size);
+
+ for (i = 0; i < index; i++) {
+ if (response[i].type != NULL)
+ free(response[i].type);
+
+#if RIL_VERSION >= 6
+ if (response[i].ifname != NULL)
+ free(response[i].ifname);
+
+ if (response[i].addresses != NULL)
+ free(response[i].addresses);
+
+ if (response[i].dnses != NULL)
+ free(response[i].dnses);
+
+ if (response[i].gateways != NULL)
+ free(response[i].gateways);
+#else
+ if (response[i].apn != NULL)
+ free(response[i].apn);
+
+ if (response[i].address != NULL)
+ free(response[i].address);
+#endif
+ }
+
+ return 0;
+}
+
+int ril_request_data_call_list(void *data, size_t size, RIL_Token token)
+{
+ 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;
+ }
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_GPRS_PDP_CONTEXT, IPC_TYPE_GET, NULL, 0);
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ipc_gprs_pdp_context_callback(struct ipc_message *message)
+{
+ struct ril_data_connection *data_connection;
+ struct ipc_gen_phone_res_data *data;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data))
+ return -1;
+
+ data = (struct ipc_gen_phone_res_data *) message->data;
+
+ data_connection = ril_data_connection_find_token(ipc_fmt_request_token(message->aseq));
+ if (data_connection == NULL) {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ return 0;
+ }
+
+ rc = ipc_gen_phone_res_check(data);
+ if (rc < 0)
+ goto error;
+
+ goto complete;
+
+error:
+ ril_data_connection_stop(data_connection);
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ return 0;
+}
+
+int ril_request_deactivate_data_call(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_gprs_pdp_context_request_set_data request_data;
+ struct ril_data_connection *data_connection = NULL;
+ struct ril_request *request;
+ char **values = NULL;
+ unsigned int cid;
+ unsigned int i;
+ int rc;
+
+ if (data == NULL || size < 2 * sizeof(char *))
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_DEACTIVATE_DATA_CALL, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+
+ if (values[0] == NULL) {
+ RIL_LOGE("%s: No cid was provided", __func__);
+ goto error;
+ }
+
+ cid = (unsigned int) atoi(values[0]);
+
+ strings_array_free(values, size);
+ values = NULL;
+
+ data_connection = ril_data_connection_find_cid(cid);
+ if (data_connection == NULL)
+ goto error;
+
+ data_connection->token = token;
+
+ rc = ipc_gprs_pdp_context_request_set_setup(&request_data, 0, data_connection->cid, NULL, NULL);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_GPRS_PDP_CONTEXT, ipc_gprs_pdp_context_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_GPRS_PDP_CONTEXT, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ if (data_connection != NULL)
+ ril_data_connection_stop(data_connection);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ipc_gprs_ip_configuration(struct ipc_message *message)
+{
+ struct ipc_gprs_ip_configuration_data *data;
+ struct ril_data_connection *data_connection;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gprs_ip_configuration_data))
+ return -1;
+
+ data = (struct ipc_gprs_ip_configuration_data *) message->data;
+
+ data_connection = ril_data_connection_find_cid(data->cid);
+ if (data_connection == NULL) {
+ if (ipc_seq_valid(message->aseq))
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ return 0;
+ }
+
+ if (data_connection->ip != NULL)
+ free(data_connection->ip);
+
+ asprintf(&data_connection->ip, "%i.%i.%i.%i", data->ip[0], data->ip[1], data->ip[2], data->ip[3]);
+
+ if (data_connection->gateway != NULL)
+ free(data_connection->gateway);
+
+ asprintf(&data_connection->gateway, "%i.%i.%i.%i", data->ip[0], data->ip[1], data->ip[2], data->ip[3]);
+
+ if (data_connection->subnet_mask != NULL)
+ free(data_connection->subnet_mask);
+
+ asprintf(&data_connection->subnet_mask, "255.255.255.255");
+
+ if (data_connection->dns1 != NULL)
+ free(data_connection->dns1);
+
+ asprintf(&data_connection->dns1, "%i.%i.%i.%i", data->dns1[0], data->dns1[1], data->dns1[2], data->dns1[3]);
+
+ if (data_connection->dns2 != NULL)
+ free(data_connection->dns2);
+
+ asprintf(&data_connection->dns2, "%i.%i.%i.%i", data->dns2[0], data->dns2[1], data->dns2[2], data->dns2[3]);
+
+ return 0;
+}
+
+int ipc_gprs_hsdpa_status(struct ipc_message *message)
+{
+ struct ipc_gprs_hsdpa_status_data *data;
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gprs_hsdpa_status_data))
+ return -1;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_gprs_hsdpa_status_data *) message->data;
+
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+
+ if (ipc_fmt_data->hsdpa_status_data.status != data->status) {
+ ipc_fmt_data->hsdpa_status_data.status = data->status;
+
+#if RIL_VERSION >= 6
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
+#else
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
+#endif
+ }
+
+ return 0;
+}
+
+int ipc_gprs_call_status(struct ipc_message *message)
+{
+#if RIL_VERSION >= 6
+ RIL_Data_Call_Response_v6 response;
+#else
+ char *setup_data_call_response[3];
+#endif
+ struct ipc_gprs_call_status_data *data;
+ struct ril_data_connection *data_connection;
+ struct ril_request *request;
+ int fail_cause;
+ unsigned int i;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gprs_call_status_data))
+ return -1;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0)
+ return 0;
+
+ data = (struct ipc_gprs_call_status_data *) message->data;
+
+ data_connection = ril_data_connection_find_cid(data->cid);
+ if (data_connection == NULL) {
+ RIL_LOGE("%s: Finding data connection with cid: %d failed", __func__, data->cid);
+
+ if (ipc_seq_valid(message->aseq))
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ return 0;
+ }
+
+ request = ril_request_find_token(data_connection->token);
+
+ if (data->status == IPC_GPRS_STATUS_ENABLED) {
+ if (data_connection->enabled) {
+ if (request != NULL && request->request == RIL_REQUEST_DEACTIVATE_DATA_CALL)
+ goto error;
+ else
+ RIL_LOGD("%s: Data connection with cid %d is already enabled", __func__, data_connection->cid);
+ } else {
+ rc = ril_data_connection_enable(data_connection);
+ if (rc < 0)
+ goto error;
+
+ if (request != NULL && request->request == RIL_REQUEST_SETUP_DATA_CALL) {
+ memset(&response, 0, sizeof(response));
+#if RIL_VERSION >= 6
+ response.status = ipc2ril_gprs_fail_cause(data->fail_cause);
+ response.cid = data_connection->cid;
+ response.active = 2;
+ response.type = strdup("IP");
+
+ if (data_connection->iface != NULL)
+ response.ifname = strdup(data_connection->iface);
+
+ if (data_connection->ip != NULL)
+ response.addresses = strdup(data_connection->ip);
+
+ asprintf(&response.dnses, "%s %s", data_connection->dns1, data_connection->dns2);
+
+ if (data_connection->gateway != NULL)
+ response.gateways = strdup(data_connection->gateway);
+#else
+ asprintf(&response[0], "%d", gprs_connection->cid);
+
+ if (data_connection->iface != NULL)
+ response[1] = strdup(data_connection->iface);
+
+ if (data_connection->ip != NULL)
+ response[2] = strdup(data_connection->ip);
+#endif
+
+ ril_request_complete(data_connection->token, RIL_E_SUCCESS, &response, sizeof(response));
+ data_connection->token = NULL;
+
+#if RIL_VERSION >= 6
+ if (response.type != NULL)
+ free(response.type);
+
+ if (response.ifname != NULL)
+ free(response.ifname);
+
+ if (response.addresses != NULL)
+ free(response.addresses);
+
+ if (response.gateways != NULL)
+ free(response.gateways);
+
+ if (response.dnses != NULL)
+ free(response.dnses);
+#else
+ for (i = 0; i < 3; i++) {
+ if (reponse[i] != NULL)
+ free(response[i]);
+ }
+#endif
+ } else {
+ RIL_LOGD("%s: Data connection with cid: %d got unexpectedly enabled", __func__, data_connection->cid);
+ }
+ }
+ } else if (data->status == IPC_GPRS_STATUS_DISABLED || data->status == IPC_GPRS_STATUS_NOT_ENABLED) {
+ if (data_connection->enabled) {
+ rc = ril_data_connection_disable(data_connection);
+ if (rc < 0)
+ goto error;
+
+ ril_data_connection_stop(data_connection);
+
+ if (request != NULL && request->request == RIL_REQUEST_DEACTIVATE_DATA_CALL)
+ ril_request_complete(request->token, RIL_E_SUCCESS, NULL, 0);
+ else
+ RIL_LOGD("%s: Data connection with cid: %d got unexpectedly disabled", __func__, data->cid);
+ } else {
+ if (request != NULL && request->request == RIL_REQUEST_SETUP_DATA_CALL) {
+#if RIL_VERSION >= 6
+ memset(&response, 0, sizeof(response));
+ response.status = ipc2ril_gprs_fail_cause(data->fail_cause);
+
+ ril_request_complete(request->token, RIL_E_SUCCESS, (void *) &response, sizeof(response));
+ // Avoid completing the request twice
+ request = NULL;
+#else
+ fail_cause = ipc2ril_gprs_fail_cause(data->fail_cause);
+
+ ril_request_data_set_uniq(RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE, (void *) &fail_cause, sizeof(fail_cause));
+#endif
+ goto error;
+ } else {
+ RIL_LOGD("%s: Data connection with cid: %d is already disabled", __func__, data_connection->cid);
+ }
+ }
+ }
+
+ if (request == NULL) {
+ rc = ipc_fmt_send(0, IPC_GPRS_PDP_CONTEXT, IPC_TYPE_GET, NULL, 0);
+ if (rc < 0)
+ goto error;
+ }
+
+ goto complete;
+
+error:
+ ril_data_connection_stop(data_connection);
+
+ if (request != NULL)
+ ril_request_complete(request->token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ return 0;
+}
+
+int ril_request_last_data_call_fail_cause(void *data, size_t size,
+ RIL_Token token)
+{
+ 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_DATA_CALL_FAIL_CAUSE);
+ fail_cause_data = ril_request_data_get(RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE);
+
+ if (fail_cause_data != NULL && fail_cause_size >= sizeof(int)) {
+ fail_cause = *((int *) fail_cause_data);
+ free(fail_cause_data);
+ } else {
+ fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
+ }
+
+ ril_request_complete(token, RIL_E_SUCCESS, (void *) &fail_cause, sizeof(fail_cause));
+
+ return RIL_REQUEST_COMPLETED;
+}
diff --git a/disp.c b/disp.c
deleted file mode 100644
index 9f6a56a..0000000
--- a/disp.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * 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>
- *
- * Based on CyanogenMod Smdk4210RIL implementation
- * Copyright (C) 2011 The CyanogenMod Project
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define LOG_TAG "RIL-DISP"
-#include <utils/Log.h>
-
-#include "samsung-ril.h"
-#include "util.h"
-
-#if RIL_VERSION >= 6
-void ipc2ril_rssi(unsigned char rssi, RIL_SignalStrength_v6 *ss)
-#else
-void ipc2ril_rssi(unsigned char rssi, RIL_SignalStrength *ss)
-#endif
-{
- int asu = 0;
-
- if (ss == NULL)
- return;
-
- if (rssi > 0x6f) {
- asu = 0;
- } else {
- asu = (((rssi - 0x71) * -1) - ((rssi - 0x71) * -1) % 2) / 2;
- if (asu > 31)
- asu = 31;
- }
-
- RIL_LOGD("Signal Strength is %d\n", asu);
-
-#if RIL_VERSION >= 6
- memset(ss, 0, sizeof(RIL_SignalStrength_v6));
- memset(&ss->LTE_SignalStrength, -1, sizeof(ss->LTE_SignalStrength));
-#else
- memset(ss, 0, sizeof(RIL_SignalStrength));
-#endif
-
- ss->GW_SignalStrength.signalStrength = asu;
- ss->GW_SignalStrength.bitErrorRate = 99;
-}
-
-#if RIL_VERSION >= 6
-void ipc2ril_bars(unsigned char bars, RIL_SignalStrength_v6 *ss)
-#else
-void ipc2ril_bars(unsigned char bars, RIL_SignalStrength *ss)
-#endif
-{
- int asu = 0;
-
- if (ss == NULL)
- return;
-
- switch (bars) {
- case 0 : asu = 1; break;
- case 1 : asu = 3; break;
- case 2 : asu = 5; break;
- case 3 : asu = 8; break;
- case 4 : asu = 12; break;
- case 5 : asu = 15; break;
- default : asu = bars; break;
- }
-
- RIL_LOGD("Signal Strength is %d\n", asu);
-
-#if RIL_VERSION >= 6
- memset(ss, 0, sizeof(RIL_SignalStrength_v6));
- memset(&ss->LTE_SignalStrength, -1, sizeof(ss->LTE_SignalStrength));
-#else
- memset(ss, 0, sizeof(RIL_SignalStrength));
-#endif
-
- ss->GW_SignalStrength.signalStrength = asu;
- ss->GW_SignalStrength.bitErrorRate = 99;
-}
-
-void ril_request_signal_strength(RIL_Token t)
-{
- unsigned char request = 1;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- ipc_fmt_send(IPC_DISP_ICON_INFO, IPC_TYPE_GET, &request, sizeof(request), ril_request_get_id(t));
-}
-
-void ipc_disp_icon_info(struct ipc_message_info *info)
-{
- struct ipc_disp_icon_info *icon_info;
-#if RIL_VERSION >= 6
- RIL_SignalStrength_v6 ss;
-#else
- RIL_SignalStrength ss;
-#endif
-
- if (info->data == NULL || info->length < sizeof(struct ipc_disp_icon_info))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, RIL_TOKEN_NULL))
- return;
-
- icon_info = (struct ipc_disp_icon_info *) info->data;
-
- if (info->type == IPC_TYPE_RESP) {
- ipc2ril_rssi(icon_info->rssi, &ss);
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &ss, sizeof(ss));
-
- } else {
- ipc2ril_bars(icon_info->bars, &ss);
- ril_request_unsolicited(RIL_UNSOL_SIGNAL_STRENGTH, &ss, sizeof(ss));
- }
-
- return;
-
-error:
- if (info->type == IPC_TYPE_RESP)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_disp_rssi_info(struct ipc_message_info *info)
-{
- struct ipc_disp_rssi_info *rssi_info;
-#if RIL_VERSION >= 6
- RIL_SignalStrength_v6 ss;
-#else
- RIL_SignalStrength ss;
-#endif
- int rssi;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_disp_rssi_info))
- return;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, RIL_TOKEN_NULL))
- return;
-
- rssi_info = (struct ipc_disp_rssi_info *) info->data;
-
- ipc2ril_rssi(rssi_info->rssi, &ss);
-
- ril_request_unsolicited(RIL_UNSOL_SIGNAL_STRENGTH, &ss, sizeof(ss));
-}
diff --git a/gen.c b/gen.c
index 596560c..8bfdb13 100644
--- a/gen.c
+++ b/gen.c
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * 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
@@ -17,178 +17,263 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
-#define LOG_TAG "RIL-GEN"
-#include <utils/Log.h>
+#include <stdlib.h>
-#include "samsung-ril.h"
-#include "util.h"
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
-/*
- * IPC_GEN_PHONE_RES has shared aseq (in the header), group, index and type (in the data)
- * with the original request it responds to.
- * On this implementation, we just check aseq and command (group and index).
- * aseq permits to identify the queued request and do what's wanted.
- * It can be either call a function with the struct ipc_message_info,
- * complete the request to RILJ (with or without an error),
- * return to RILJ if there is an error in this response.
- *
- * It would have been possible to deal with group, index and type only and use
- * callback functions. Though, what is currently being used is more a "standard"
- * error catch system, that requires less code (no particular function), while
- * it also permits using custom functions, when IPC_GEN_PHONE_RES code is
- * request-specific.
- *
- * On a custom function, don't forget to get a clean new aseq if you're going to
- * send some data to the modem, just liek this:
- * aseq = ril_request_reg_id(ril_request_get_token(info->aseq));
- *
- * Please use the GEN_PHONE_RES engine as often as possible!
- */
+#include <samsung-ril.h>
+#include <utils.h>
-/*
- * GEN expects functions
- */
-
-int ipc_gen_phone_res_expect_register(unsigned char aseq, unsigned short command,
- void (*func)(struct ipc_message_info *info), int complete, int abort)
+int ipc_gen_phone_res_expect_register(struct ril_client *client,
+ unsigned char aseq, unsigned short command,
+ int (*callback)(struct ipc_message *message),
+ int complete, int abort)
{
- struct ipc_gen_phone_res_expect_info *expect;
+ struct ipc_gen_phone_res_expect *expect;
+ struct ipc_fmt_data *data;
struct list_head *list_end;
struct list_head *list;
- expect = calloc(1, sizeof(struct ipc_gen_phone_res_expect_info));
- if (expect == NULL)
+ if (client == NULL || client->data == NULL)
return -1;
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
+
+ expect = calloc(1, sizeof(struct ipc_gen_phone_res_expect));
expect->aseq = aseq;
expect->command = command;
- expect->func = func;
+ expect->callback = callback;
expect->complete = complete;
expect->abort = abort;
- list_end = ril_data.generic_responses;
+ list_end = data->gen_phone_res_expect;
while (list_end != NULL && list_end->next != NULL)
list_end = list_end->next;
- list = list_head_alloc((void *) expect, list_end, NULL);
+ list = list_head_alloc(list_end, NULL, (void *) expect);
+
+ if (data->gen_phone_res_expect == NULL)
+ data->gen_phone_res_expect = list;
- if (ril_data.generic_responses == NULL)
- ril_data.generic_responses = list;
+ RIL_CLIENT_UNLOCK(client);
return 0;
}
-void ipc_gen_phone_res_expect_unregister(struct ipc_gen_phone_res_expect_info *expect)
+int ipc_gen_phone_res_expect_unregister(struct ril_client *client,
+ struct ipc_gen_phone_res_expect *expect)
{
+ struct ipc_fmt_data *data;
struct list_head *list;
- if (expect == NULL)
- return;
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
- list = ril_data.generic_responses;
+ list = data->gen_phone_res_expect;
while (list != NULL) {
if (list->data == (void *) expect) {
- memset(expect, 0, sizeof(struct ipc_gen_phone_res_expect_info));
+ memset(expect, 0, sizeof(struct ipc_gen_phone_res_expect));
free(expect);
- if (list == ril_data.generic_responses)
- ril_data.generic_responses = list->next;
+ if (list == data->gen_phone_res_expect)
+ data->gen_phone_res_expect = list->next;
list_head_free(list);
break;
}
+
list_continue:
list = list->next;
}
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
}
-struct ipc_gen_phone_res_expect_info *ipc_gen_phone_res_expect_info_find_aseq(unsigned char aseq)
+int ipc_gen_phone_res_expect_flush(struct ril_client *client)
{
- struct ipc_gen_phone_res_expect_info *expect;
+ struct ipc_gen_phone_res_expect *expect;
+ struct ipc_fmt_data *data;
struct list_head *list;
+ struct list_head *list_next;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
+
+ list = data->gen_phone_res_expect;
+ while (list != NULL) {
+ if (list->data != NULL) {
+ expect = (struct ipc_gen_phone_res_expect *) list->data;
+ memset(expect, 0, sizeof(struct ipc_gen_phone_res_expect));
+ free(expect);
+ }
+
+ if (list == data->gen_phone_res_expect)
+ data->gen_phone_res_expect = list->next;
+
+ list_next = list->next;
+
+ list_head_free(list);
+
+list_continue:
+ list = list_next;
+ }
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
+}
+
+struct ipc_gen_phone_res_expect *ipc_gen_phone_res_expect_find_aseq(struct ril_client *client,
+ unsigned char aseq)
+{
+ struct ipc_gen_phone_res_expect *expect;
+ struct ipc_fmt_data *data;
+ struct list_head *list;
+
+ if (client == NULL || client->data == NULL)
+ return NULL;
+
+ data = (struct ipc_fmt_data *) client->data;
- list = ril_data.generic_responses;
+ RIL_CLIENT_LOCK(client);
+
+ list = data->gen_phone_res_expect;
while (list != NULL) {
- expect = (struct ipc_gen_phone_res_expect_info *) list->data;
- if (expect == NULL)
+ if (list->data == NULL)
goto list_continue;
- if (expect->aseq == aseq)
+ expect = (struct ipc_gen_phone_res_expect *) list->data;
+
+ if (expect->aseq == aseq) {
+ RIL_CLIENT_UNLOCK(client);
return expect;
+ }
list_continue:
list = list->next;
}
+ RIL_CLIENT_UNLOCK(client);
+
return NULL;
}
-int ipc_gen_phone_res_expect_to_func(unsigned char aseq, unsigned short command,
- void (*func)(struct ipc_message_info *info))
+int ipc_gen_phone_res_expect_callback(unsigned char aseq, unsigned short command,
+ int (*callback)(struct ipc_message *message))
{
- return ipc_gen_phone_res_expect_register(aseq, command, func, 0, 0);
+ struct ril_client *client;
+ int rc;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL)
+ return -1;
+
+ rc = ipc_gen_phone_res_expect_register(client, aseq, command, callback, 0, 0);
+ if (rc < 0)
+ return -1;
+
+ return 0;
}
-int ipc_gen_phone_res_expect_to_complete(unsigned char aseq, unsigned short command)
+int ipc_gen_phone_res_expect_complete(unsigned char aseq, unsigned short command)
{
- return ipc_gen_phone_res_expect_register(aseq, command, NULL, 1, 0);
+ struct ril_client *client;
+ int rc;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL)
+ return -1;
+
+ rc = ipc_gen_phone_res_expect_register(client, aseq, command, NULL, 1, 0);
+ if (rc < 0)
+ return -1;
+
+ return 0;
}
-int ipc_gen_phone_res_expect_to_abort(unsigned char aseq, unsigned short command)
+int ipc_gen_phone_res_expect_abort(unsigned char aseq, unsigned short command)
{
- return ipc_gen_phone_res_expect_register(aseq, command, NULL, 0, 1);
-}
+ struct ril_client *client;
+ int rc;
-/*
- * GEN dequeue function
- */
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL)
+ return -1;
+
+ rc = ipc_gen_phone_res_expect_register(client, aseq, command, NULL, 0, 1);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
-void ipc_gen_phone_res(struct ipc_message_info *info)
+int ipc_gen_phone_res(struct ipc_message *message)
{
- struct ipc_gen_phone_res_expect_info *expect;
- struct ipc_gen_phone_res *phone_res;
- RIL_Errno e;
+ struct ipc_gen_phone_res_expect *expect;
+ struct ipc_gen_phone_res_data *data;
+ struct ril_client *client;
+ RIL_Errno error;
int rc;
- if (info->data == NULL || info->length < sizeof(struct ipc_gen_phone_res))
- return;
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data))
+ return -1;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL)
+ return -1;
- phone_res = (struct ipc_gen_phone_res *) info->data;
- expect = ipc_gen_phone_res_expect_info_find_aseq(info->aseq);
+ data = (struct ipc_gen_phone_res_data *) message->data;
+ expect = ipc_gen_phone_res_expect_find_aseq(client, message->aseq);
if (expect == NULL) {
- RIL_LOGD("aseq: 0x%x not found in the IPC_GEN_PHONE_RES queue", info->aseq);
- return;
+ RIL_LOGD("Ignoring generic response for command %s", ipc_command_string(IPC_COMMAND(data->group, data->index)));
+ return 0;
}
- RIL_LOGD("aseq: 0x%x found in the IPC_GEN_PHONE_RES queue!", info->aseq);
-
- if (expect->command != IPC_COMMAND(phone_res)) {
- RIL_LOGE("IPC_GEN_PHONE_RES aseq (0x%x) doesn't match the queued one with command (0x%x)",
- expect->aseq, expect->command);
-
- if (expect->func != NULL) {
- RIL_LOGE("Not safe to run the custom function, reporting generic failure");
- ril_request_complete(ril_request_get_token(expect->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- goto unregister;
- }
+ if (IPC_COMMAND(data->group, data->index) != expect->command) {
+ RIL_LOGE("Generic response commands mismatch: %s/%s", ipc_command_string(IPC_COMMAND(data->group, data->index)), ipc_command_string(expect->command));
+ goto error;
}
- if (expect->func != NULL) {
- expect->func(info);
- goto unregister;
+ RIL_LOGD("Generic response was expected");
+
+ if (expect->callback != NULL) {
+ rc = expect->callback(message);
+ goto complete;
}
- rc = ipc_gen_phone_res_check(phone_res);
+ rc = ipc_gen_phone_res_check(data);
if (rc < 0)
- e = RIL_E_GENERIC_FAILURE;
+ error = RIL_E_GENERIC_FAILURE;
else
- e = RIL_E_SUCCESS;
+ error = RIL_E_SUCCESS;
+
+ if (expect->complete || (expect->abort && error == RIL_E_GENERIC_FAILURE))
+ ril_request_complete(ipc_fmt_request_token(message->aseq), error, NULL, 0);
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
- if (expect->complete || (expect->abort && e == RIL_E_GENERIC_FAILURE))
- ril_request_complete(ril_request_get_token(expect->aseq), e, NULL, 0);
+complete:
+ if (expect != NULL)
+ ipc_gen_phone_res_expect_unregister(client, expect);
-unregister:
- ipc_gen_phone_res_expect_unregister(expect);
+ return rc;
}
diff --git a/gprs.c b/gprs.c
deleted file mode 100644
index 90dda72..0000000
--- a/gprs.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*
- * This file is part of Samsung-RIL.
- *
- * Copyright (C) 2011-2013 Paul Kocialkowski <contact@paulk.fr>
- * Copyright (C) 2011 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#define LOG_TAG "RIL-GPRS"
-#include <utils/Log.h>
-#include <cutils/properties.h>
-
-#if RIL_VERSION >= 6
-#include <netutils/ifc.h>
-#endif
-
-#include "samsung-ril.h"
-#include "util.h"
-
-#if RIL_VERSION >= 6
-RIL_DataCallFailCause ipc2ril_gprs_fail_cause(unsigned short fail_cause)
-#else
-RIL_LastDataCallActivateFailCause ipc2ril_gprs_fail_cause(unsigned short fail_cause)
-#endif
-{
- switch (fail_cause) {
-
- case IPC_GPRS_FAIL_INSUFFICIENT_RESOURCES:
- return PDP_FAIL_INSUFFICIENT_RESOURCES;
- case IPC_GPRS_FAIL_MISSING_UKNOWN_APN:
- return PDP_FAIL_MISSING_UKNOWN_APN;
- case IPC_GPRS_FAIL_UNKNOWN_PDP_ADDRESS_TYPE:
- return PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE;
- case IPC_GPRS_FAIL_USER_AUTHENTICATION:
- return PDP_FAIL_USER_AUTHENTICATION;
- case IPC_GPRS_FAIL_ACTIVATION_REJECT_GGSN:
- return PDP_FAIL_ACTIVATION_REJECT_GGSN;
- case IPC_GPRS_FAIL_ACTIVATION_REJECT_UNSPECIFIED:
- return PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED;
- case IPC_GPRS_FAIL_SERVICE_OPTION_NOT_SUPPORTED:
- return PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED;
- case IPC_GPRS_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED:
- return PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED;
- case IPC_GPRS_FAIL_SERVICE_OPTION_OUT_OF_ORDER:
- return PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER;
- case IPC_GPRS_FAIL_NSAPI_IN_USE:
- return PDP_FAIL_NSAPI_IN_USE;
- default:
- return PDP_FAIL_ERROR_UNSPECIFIED;
- }
-}
-
-int ipc2ril_gprs_connection_active(unsigned char state)
-{
- switch (state) {
- case IPC_GPRS_STATE_DISABLED:
- return 1;
- case IPC_GPRS_STATE_ENABLED:
- return 2;
- case IPC_GPRS_STATE_NOT_ENABLED:
- default:
- return 0;
- }
-}
-
-int ril_gprs_connection_register(int cid)
-{
- struct ril_gprs_connection *gprs_connection;
- struct list_head *list_end;
- struct list_head *list;
-
- gprs_connection = calloc(1, sizeof(struct ril_gprs_connection));
- if (gprs_connection == NULL)
- return -1;
-
- gprs_connection->cid = cid;
-
- list_end = ril_data.gprs_connections;
- while (list_end != NULL && list_end->next != NULL)
- list_end = list_end->next;
-
- list = list_head_alloc((void *) gprs_connection, list_end, NULL);
-
- if (ril_data.gprs_connections == NULL)
- ril_data.gprs_connections = list;
-
- return 0;
-}
-
-void ril_gprs_connection_unregister(struct ril_gprs_connection *gprs_connection)
-{
- struct list_head *list;
-
- if (gprs_connection == NULL)
- return;
-
- list = ril_data.gprs_connections;
- while (list != NULL) {
- if (list->data == (void *) gprs_connection) {
- memset(gprs_connection, 0, sizeof(struct ril_gprs_connection));
- free(gprs_connection);
-
- if (list == ril_data.gprs_connections)
- ril_data.gprs_connections = list->next;
-
- list_head_free(list);
-
- break;
- }
-list_continue:
- list = list->next;
- }
-}
-
-struct ril_gprs_connection *ril_gprs_connection_find_cid(int cid)
-{
- struct ril_gprs_connection *gprs_connection;
- struct list_head *list;
-
- list = ril_data.gprs_connections;
- while (list != NULL) {
- gprs_connection = (struct ril_gprs_connection *) list->data;
- if (gprs_connection == NULL)
- goto list_continue;
-
- if (gprs_connection->cid == cid)
- return gprs_connection;
-
-list_continue:
- list = list->next;
- }
-
- return NULL;
-}
-
-struct ril_gprs_connection *ril_gprs_connection_find_token(RIL_Token t)
-{
- struct ril_gprs_connection *gprs_connection;
- struct list_head *list;
-
- list = ril_data.gprs_connections;
- while (list != NULL) {
- gprs_connection = (struct ril_gprs_connection *) list->data;
- if (gprs_connection == NULL)
- goto list_continue;
-
- if (gprs_connection->token == t)
- return gprs_connection;
-
-list_continue:
- list = list->next;
- }
-
- return NULL;
-}
-
-struct ril_gprs_connection *ril_gprs_connection_start(void)
-{
- struct ipc_client_gprs_capabilities gprs_capabilities;
- struct ril_gprs_connection *gprs_connection;
- struct ipc_client *ipc_client;
- struct list_head *list;
- int cid, cid_max;
- int rc;
- int i;
-
- if (ril_data.ipc_fmt_client == NULL || ril_data.ipc_fmt_client->data == NULL)
- return NULL;
-
- ipc_client = (struct ipc_client *) ril_data.ipc_fmt_client->data;
-
- ipc_client_gprs_get_capabilities(ipc_client, &gprs_capabilities);
- cid_max = gprs_capabilities.cid_max;
-
- for (i = 0 ; i < cid_max ; i++) {
- cid = i + 1;
- list = ril_data.gprs_connections;
- while (list != NULL) {
- if (list->data == NULL)
- goto list_continue;
-
- gprs_connection = (struct ril_gprs_connection *) list->data;
- if (gprs_connection->cid == cid) {
- cid = 0;
- break;
- }
-
-list_continue:
- list = list->next;
- }
-
- if (cid > 0)
- break;
- }
-
- if (cid <= 0) {
- RIL_LOGE("Unable to find an unused cid, aborting");
- return NULL;
- }
-
- RIL_LOGD("Using GPRS connection cid: %d", cid);
- rc = ril_gprs_connection_register(cid);
- if (rc < 0)
- return NULL;
-
- gprs_connection = ril_gprs_connection_find_cid(cid);
- return gprs_connection;
-}
-
-void ril_gprs_connection_stop(struct ril_gprs_connection *gprs_connection)
-{
- if (gprs_connection == NULL)
- return;
-
- if (gprs_connection->interface != NULL)
- free(gprs_connection->interface);
-
- ril_gprs_connection_unregister(gprs_connection);
-}
-
-void ipc_gprs_pdp_context_enable_complete(struct ipc_message_info *info)
-{
- struct ipc_gen_phone_res *phone_res;
- struct ril_gprs_connection *gprs_connection;
- int rc;
-
- phone_res = (struct ipc_gen_phone_res *) info->data;
- gprs_connection = ril_gprs_connection_find_token(ril_request_get_token(info->aseq));
-
- if (!gprs_connection) {
- RIL_LOGE("Unable to find GPRS connection, aborting");
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- rc = ipc_gen_phone_res_check(phone_res);
- if (rc < 0) {
- RIL_LOGE("There was an error, aborting PDP context complete");
-
- gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
- gprs_connection->token = RIL_TOKEN_NULL;
- ril_data.state.gprs_last_failed_cid = gprs_connection->cid;
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- RIL_LOGD("Waiting for IP configuration!");
-}
-
-void ipc_gprs_define_pdp_context_complete(struct ipc_message_info *info)
-{
- struct ipc_gen_phone_res *phone_res;
- struct ril_gprs_connection *gprs_connection;
- struct ril_request_info *request;
- int aseq;
- int rc;
-
- phone_res = (struct ipc_gen_phone_res *) info->data;
- gprs_connection = ril_gprs_connection_find_token(ril_request_get_token(info->aseq));
-
- if (!gprs_connection) {
- RIL_LOGE("Unable to find GPRS connection, aborting");
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- rc = ipc_gen_phone_res_check(phone_res);
- if (rc < 0) {
- RIL_LOGE("There was an error, aborting define PDP context complete");
-
- gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
- gprs_connection->token = RIL_TOKEN_NULL;
- ril_data.state.gprs_last_failed_cid = gprs_connection->cid;
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- request = ril_request_info_find_id(info->aseq);
- aseq = ril_request_id_get();
-
- if (request != NULL)
- request->id = aseq;
-
- ipc_gen_phone_res_expect_to_func(aseq, IPC_GPRS_PDP_CONTEXT,
- ipc_gprs_pdp_context_enable_complete);
-
- ipc_fmt_send(IPC_GPRS_PDP_CONTEXT, IPC_TYPE_SET,
- (void *) &(gprs_connection->context),
- sizeof(struct ipc_gprs_pdp_context_set), aseq);
-}
-
-void ipc_gprs_port_list_complete(struct ipc_message_info *info)
-{
- struct ipc_gen_phone_res *phone_res;
- struct ril_gprs_connection *gprs_connection;
- struct ril_request_info *request;
- int aseq;
- int rc;
-
- phone_res = (struct ipc_gen_phone_res *) info->data;
- gprs_connection = ril_gprs_connection_find_token(ril_request_get_token(info->aseq));
-
- if (!gprs_connection) {
- RIL_LOGE("Unable to find GPRS connection, aborting");
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- rc = ipc_gen_phone_res_check(phone_res);
- if (rc < 0) {
- RIL_LOGE("There was an error, aborting port list complete");
-
- gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
- gprs_connection->token = RIL_TOKEN_NULL;
- ril_data.state.gprs_last_failed_cid = gprs_connection->cid;
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- request = ril_request_info_find_id(info->aseq);
- aseq = ril_request_id_get();
-
- if (request != NULL)
- request->id = aseq;
- ipc_gen_phone_res_expect_to_func(aseq, IPC_GPRS_DEFINE_PDP_CONTEXT,
- ipc_gprs_define_pdp_context_complete);
-
- ipc_fmt_send(IPC_GPRS_DEFINE_PDP_CONTEXT, IPC_TYPE_SET,
- (void *) &(gprs_connection->define_context),
- sizeof(struct ipc_gprs_define_pdp_context),
- aseq);
-}
-
-void ril_request_setup_data_call(RIL_Token t, void *data, int length)
-{
- struct ril_gprs_connection *gprs_connection = NULL;
- struct ipc_client_gprs_capabilities gprs_capabilities;
- struct ipc_gprs_port_list port_list;
- struct ipc_client *ipc_client;
-
- char *username = NULL;
- char *password = NULL;
- char *apn = NULL;
-
- if (data == NULL || length < (int) (4 * sizeof(char *)))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- if (ril_data.ipc_fmt_client == NULL || ril_data.ipc_fmt_client->data == NULL)
- goto error;
-
- ipc_client = (struct ipc_client *) ril_data.ipc_fmt_client->data;
-
- apn = ((char **) data)[2];
- username = ((char **) data)[3];
- password = ((char **) data)[4];
-
- RIL_LOGD("Requesting data connection to APN '%s'\n", apn);
-
- gprs_connection = ril_gprs_connection_start();
-
- if (!gprs_connection) {
- RIL_LOGE("Unable to create GPRS connection, aborting");
-
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- gprs_connection->token = t;
-
- // Create the structs with the apn
- ipc_gprs_define_pdp_context_setup(&(gprs_connection->define_context),
- gprs_connection->cid, 1, apn);
-
- // Create the structs with the username/password tuple
- ipc_gprs_pdp_context_setup(&(gprs_connection->context),
- gprs_connection->cid, 1, username, password);
-
- ipc_client_gprs_get_capabilities(ipc_client, &gprs_capabilities);
-
- // If the device has the capability, deal with port list
- if (gprs_capabilities.port_list) {
- ipc_gprs_port_list_setup(&port_list);
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_GPRS_PORT_LIST,
- ipc_gprs_port_list_complete);
-
- ipc_fmt_send(IPC_GPRS_PORT_LIST, IPC_TYPE_SET,
- (void *) &port_list, sizeof(struct ipc_gprs_port_list), ril_request_get_id(t));
- } else {
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_GPRS_DEFINE_PDP_CONTEXT,
- ipc_gprs_define_pdp_context_complete);
-
- ipc_fmt_send(IPC_GPRS_DEFINE_PDP_CONTEXT, IPC_TYPE_SET,
- (void *) &(gprs_connection->define_context),
- sizeof(struct ipc_gprs_define_pdp_context), ril_request_get_id(t));
- }
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_gprs_ip_configuration(struct ipc_message_info *info)
-{
- struct ril_gprs_connection *gprs_connection;
- struct ipc_gprs_ip_configuration *ip_configuration;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_gprs_ip_configuration))
- goto error;
-
- ip_configuration = (struct ipc_gprs_ip_configuration *) info->data;
-
- gprs_connection = ril_gprs_connection_find_cid(ip_configuration->cid);
-
- if (!gprs_connection) {
- RIL_LOGE("Unable to find GPRS connection, aborting");
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- RIL_LOGD("Obtained IP Configuration");
-
- // Copy the obtained IP configuration to the GPRS connection structure
- memcpy(&(gprs_connection->ip_configuration),
- ip_configuration, sizeof(struct ipc_gprs_ip_configuration));
-
- RIL_LOGD("Waiting for GPRS call status");
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_gprs_pdp_context_disable_complete(struct ipc_message_info *info)
-{
- struct ipc_gen_phone_res *phone_res;
- struct ril_gprs_connection *gprs_connection;
- int rc;
-
- phone_res = (struct ipc_gen_phone_res *) info->data;
- gprs_connection = ril_gprs_connection_find_token(ril_request_get_token(info->aseq));
-
- if (!gprs_connection) {
- RIL_LOGE("Unable to find GPRS connection, aborting");
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- rc = ipc_gen_phone_res_check(phone_res);
- if (rc < 0) {
- RIL_LOGE("There was an error, aborting PDP context complete");
-
- // RILJ is not going to ask for fail reason
- ril_gprs_connection_stop(gprs_connection);
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- RIL_LOGD("Waiting for GPRS call status");
-}
-
-void ril_request_deactivate_data_call(RIL_Token t, void *data, int length)
-{
- struct ril_gprs_connection *gprs_connection;
- struct ipc_gprs_pdp_context_set context;
-
- char *cid;
- int rc;
-
- if (data == NULL || length < (int) sizeof(char *))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- cid = ((char **) data)[0];
-
- gprs_connection = ril_gprs_connection_find_cid(atoi(cid));
-
- if (!gprs_connection) {
- RIL_LOGE("Unable to find GPRS connection, aborting");
-
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- gprs_connection->token = t;
-
- ipc_gprs_pdp_context_setup(&context, gprs_connection->cid, 0, NULL, NULL);
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_GPRS_PDP_CONTEXT,
- ipc_gprs_pdp_context_disable_complete);
-
- ipc_fmt_send(IPC_GPRS_PDP_CONTEXT, IPC_TYPE_SET,
- (void *) &context, sizeof(struct ipc_gprs_pdp_context_set), ril_request_get_id(t));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-#if RIL_VERSION >= 6
-int ipc_gprs_connection_enable(struct ril_gprs_connection *gprs_connection,
- RIL_Data_Call_Response_v6 *setup_data_call_response)
-#else
-int ipc_gprs_connection_enable(struct ril_gprs_connection *gprs_connection,
- char **setup_data_call_response)
-#endif
-{
- struct ipc_client *ipc_client;
- struct ipc_gprs_ip_configuration *ip_configuration;
-
- char *interface = NULL;
- char *ip;
- char *gateway;
- char *subnet_mask;
- in_addr_t subnet_mask_addr;
- char *dns1;
- char *dns2;
-
- char prop_name[PROPERTY_KEY_MAX];
-
- int rc;
-
- if (gprs_connection == NULL || setup_data_call_response == NULL)
- return -EINVAL;
-
- if (ril_data.ipc_fmt_client == NULL || ril_data.ipc_fmt_client->data == NULL)
- return -EINVAL;
-
- ipc_client = (struct ipc_client *) ril_data.ipc_fmt_client->data;
-
- ip_configuration = &(gprs_connection->ip_configuration);
-
- asprintf(&ip, "%i.%i.%i.%i",
- (ip_configuration->ip)[0],
- (ip_configuration->ip)[1],
- (ip_configuration->ip)[2],
- (ip_configuration->ip)[3]);
-
- // FIXME: gateway isn't reliable!
- asprintf(&gateway, "%i.%i.%i.%i",
- (ip_configuration->ip)[0],
- (ip_configuration->ip)[1],
- (ip_configuration->ip)[2],
- (ip_configuration->ip)[3]);
-
- // FIXME: subnet isn't reliable!
- asprintf(&subnet_mask, "255.255.255.255");
-
- asprintf(&dns1, "%i.%i.%i.%i",
- (ip_configuration->dns1)[0],
- (ip_configuration->dns1)[1],
- (ip_configuration->dns1)[2],
- (ip_configuration->dns1)[3]);
- asprintf(&dns2, "%i.%i.%i.%i",
- (ip_configuration->dns2)[0],
- (ip_configuration->dns2)[1],
- (ip_configuration->dns2)[2],
- (ip_configuration->dns2)[3]);
-
- rc = ipc_client_gprs_activate(ipc_client, gprs_connection->cid);
- if (rc < 0) {
- // This is not a critical issue
- RIL_LOGE("Failed to activate interface!");
- }
-
- interface = ipc_client_gprs_get_iface(ipc_client, gprs_connection->cid);
- if (interface == NULL) {
- // This is not a critical issue, fallback to rmnet
- RIL_LOGE("Failed to get interface name!");
- asprintf(&interface, "rmnet%d", gprs_connection->cid - 1);
- }
-
- if (gprs_connection->interface == NULL && interface != NULL) {
- gprs_connection->interface = strdup(interface);
- }
-
- RIL_LOGD("Using net interface: %s\n", interface);
-
- RIL_LOGD("GPRS configuration: iface: %s, ip:%s, "
- "gateway:%s, subnet_mask:%s, dns1:%s, dns2:%s",
- interface, ip, gateway, subnet_mask, dns1, dns2);
-
- subnet_mask_addr = inet_addr(subnet_mask);
-
-#if RIL_VERSION >= 6
- rc = ifc_configure(interface, inet_addr(ip),
- ipv4NetmaskToPrefixLength(subnet_mask_addr),
- inet_addr(gateway),
- inet_addr(dns1), inet_addr(dns2));
-#else
- rc = ifc_configure(interface, inet_addr(ip),
- subnet_mask_addr,
- inet_addr(gateway),
- inet_addr(dns1), inet_addr(dns2));
-#endif
-
- if (rc < 0) {
- RIL_LOGE("ifc_configure failed");
-
- free(interface);
- return -1;
- }
-
- snprintf(prop_name, PROPERTY_KEY_MAX, "net.%s.dns1", interface);
- property_set(prop_name, dns1);
- snprintf(prop_name, PROPERTY_KEY_MAX, "net.%s.dns2", interface);
- property_set(prop_name, dns2);
- snprintf(prop_name, PROPERTY_KEY_MAX, "net.%s.gw", interface);
- property_set(prop_name, gateway);
-
-#if RIL_VERSION >= 6
- setup_data_call_response->status = 0;
- setup_data_call_response->cid = gprs_connection->cid;
- setup_data_call_response->active = 1;
- setup_data_call_response->type = strdup("IP");
-
- setup_data_call_response->ifname = interface;
- setup_data_call_response->addresses = ip;
- setup_data_call_response->gateways = gateway;
- asprintf(&setup_data_call_response->dnses, "%s %s", dns1, dns2);
-#else
- asprintf(&(setup_data_call_response[0]), "%d", gprs_connection->cid);
- setup_data_call_response[1] = interface;
- setup_data_call_response[2] = ip;
-
- free(gateway);
-#endif
-
- free(subnet_mask);
- free(dns1);
- free(dns2);
-
- return 0;
-}
-
-int ipc_gprs_connection_disable(struct ril_gprs_connection *gprs_connection)
-{
- struct ipc_client *ipc_client;
-
- char *interface;
- int rc;
-
- if (gprs_connection == NULL)
- return -EINVAL;
-
- if (ril_data.ipc_fmt_client == NULL || ril_data.ipc_fmt_client->data == NULL)
- return -EINVAL;
-
- ipc_client = (struct ipc_client *) ril_data.ipc_fmt_client->data;
-
- if (gprs_connection->interface == NULL) {
- interface = ipc_client_gprs_get_iface(ipc_client, gprs_connection->cid);
- if (interface == NULL) {
- // This is not a critical issue, fallback to rmnet
- RIL_LOGE("Failed to get interface name!");
- asprintf(&interface, "rmnet%d", gprs_connection->cid);
- }
- } else {
- interface = gprs_connection->interface;
- }
-
- RIL_LOGD("Using net interface: %s\n", interface);
-
- rc = ifc_down(interface);
-
- if (gprs_connection->interface == NULL)
- free(interface);
-
- if (rc < 0) {
- RIL_LOGE("ifc_down failed");
- }
-
- rc = ipc_client_gprs_deactivate(ipc_client, gprs_connection->cid);
- if (rc < 0) {
- // This is not a critical issue
- RIL_LOGE("Could not deactivate interface!");
- }
-
- return 0;
-}
-
-#if RIL_VERSION >= 6
-void ril_data_call_response_free(RIL_Data_Call_Response_v6 *response)
-#else
-void ril_data_call_response_free(RIL_Data_Call_Response *response)
-#endif
-{
- if (response == NULL)
- return;
-
- if (response->type != NULL)
- free(response->type);
-
-#if RIL_VERSION >= 6
- if (response->addresses)
- free(response->addresses);
- if (response->ifname)
- free(response->ifname);
- if (response->dnses)
- free(response->dnses);
- if (response->gateways)
- free(response->gateways);
-#else
- if (response->apn)
- free(response->apn);
- if (response->address)
- free(response->address);
-#endif
-}
-
-void ipc_gprs_call_status(struct ipc_message_info *info)
-{
- struct ril_gprs_connection *gprs_connection;
- struct ipc_gprs_call_status *call_status;
-
-#if RIL_VERSION >= 6
- RIL_Data_Call_Response_v6 setup_data_call_response;
-#else
- char *setup_data_call_response[3] = { NULL, NULL, NULL };
-#endif
-
- int rc;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_gprs_call_status))
- goto error;
-
- call_status = (struct ipc_gprs_call_status *) info->data;
-
- memset(&setup_data_call_response, 0, sizeof(setup_data_call_response));
-
- gprs_connection = ril_gprs_connection_find_cid(call_status->cid);
-
- if (!gprs_connection) {
- RIL_LOGE("Unable to find GPRS connection, aborting");
-
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- if (call_status->fail_cause == 0) {
- if (!gprs_connection->enabled &&
- call_status->state == IPC_GPRS_STATE_ENABLED &&
- gprs_connection->token != RIL_TOKEN_NULL) {
- RIL_LOGD("GPRS connection is now enabled");
-
- rc = ipc_gprs_connection_enable(gprs_connection,
- &setup_data_call_response);
- if (rc < 0) {
- RIL_LOGE("Failed to enable and configure GPRS interface");
-
- gprs_connection->enabled = 0;
- gprs_connection->fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
- ril_data.state.gprs_last_failed_cid = gprs_connection->cid;
-
- ril_request_complete(gprs_connection->token,
- RIL_E_GENERIC_FAILURE, NULL, 0);
- } else {
- RIL_LOGD("GPRS interface enabled");
-
- gprs_connection->enabled = 1;
-
- ril_request_complete(gprs_connection->token,
- RIL_E_SUCCESS, &setup_data_call_response,
- sizeof(setup_data_call_response));
- gprs_connection->token = RIL_TOKEN_NULL;
- }
-#if RIL_VERSION >= 6
- ril_data_call_response_free(&setup_data_call_response);
-#else
- if (setup_data_call_response[0] != NULL)
- free(setup_data_call_response[0]);
- if (setup_data_call_response[1] != NULL)
- free(setup_data_call_response[1]);
- if (setup_data_call_response[2] != NULL)
- free(setup_data_call_response[2]);
-#endif
- } else if (gprs_connection->enabled &&
- call_status->state == IPC_GPRS_STATE_DISABLED &&
- gprs_connection->token != RIL_TOKEN_NULL) {
- RIL_LOGD("GPRS connection is now disabled");
-
- rc = ipc_gprs_connection_disable(gprs_connection);
- if (rc < 0) {
- RIL_LOGE("Failed to disable GPRS interface");
-
- ril_request_complete(gprs_connection->token,
- RIL_E_GENERIC_FAILURE, NULL, 0);
-
- // RILJ is not going to ask for fail reason
- ril_gprs_connection_stop(gprs_connection);
- } else {
- RIL_LOGD("GPRS interface disabled");
-
- gprs_connection->enabled = 0;
-
- ril_request_complete(gprs_connection->token,
- RIL_E_SUCCESS, NULL, 0);
-
- ril_gprs_connection_stop(gprs_connection);
- }
- } else {
- RIL_LOGE("GPRS connection reported as changed though state is not OK:"
- "\n\tgprs_connection->enabled=%d\n\tgprs_connection->token=0x%x",
- gprs_connection->enabled, (unsigned)gprs_connection->token);
-
- ril_unsol_data_call_list_changed();
- }
- } else {
- if (!gprs_connection->enabled &&
- (call_status->state == IPC_GPRS_STATE_NOT_ENABLED ||
- call_status->state == IPC_GPRS_STATE_DISABLED) &&
- gprs_connection->token != RIL_TOKEN_NULL) {
- RIL_LOGE("Failed to enable GPRS connection");
-
- gprs_connection->enabled = 0;
- gprs_connection->fail_cause =
- ipc2ril_gprs_fail_cause(call_status->fail_cause);
- ril_data.state.gprs_last_failed_cid = gprs_connection->cid;
-
- ril_request_complete(gprs_connection->token,
- RIL_E_GENERIC_FAILURE, NULL, 0);
- gprs_connection->token = RIL_TOKEN_NULL;
-
- ril_unsol_data_call_list_changed();
- } else if (gprs_connection->enabled &&
- call_status->state == IPC_GPRS_STATE_DISABLED) {
- RIL_LOGE("GPRS connection suddently got disabled");
-
- rc = ipc_gprs_connection_disable(gprs_connection);
- if (rc < 0) {
- RIL_LOGE("Failed to disable GPRS interface");
-
- // RILJ is not going to ask for fail reason
- ril_gprs_connection_stop(gprs_connection);
- } else {
- RIL_LOGE("GPRS interface disabled");
-
- gprs_connection->enabled = 0;
- ril_gprs_connection_stop(gprs_connection);
- }
-
- ril_unsol_data_call_list_changed();
- } else {
- RIL_LOGE("GPRS connection reported to have failed though state is OK:"
- "\n\tgprs_connection->enabled=%d\n\tgprs_connection->token=0x%x",
- gprs_connection->enabled, (unsigned)gprs_connection->token);
-
- ril_unsol_data_call_list_changed();
- }
- }
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_last_data_call_fail_cause(RIL_Token t)
-{
- struct ril_gprs_connection *gprs_connection;
- int last_failed_cid;
- int fail_cause;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- last_failed_cid = ril_data.state.gprs_last_failed_cid;
-
- if (!last_failed_cid) {
- RIL_LOGE("No GPRS connection was reported to have failed");
-
- goto fail_cause_unspecified;
- }
-
- gprs_connection = ril_gprs_connection_find_cid(last_failed_cid);
-
- if (!gprs_connection) {
- RIL_LOGE("Unable to find GPRS connection");
-
- goto fail_cause_unspecified;
- }
-
- fail_cause = gprs_connection->fail_cause;
-
- RIL_LOGD("Destroying GPRS connection with cid: %d", gprs_connection->cid);
- ril_gprs_connection_stop(gprs_connection);
-
- goto fail_cause_return;
-
-fail_cause_unspecified:
- fail_cause = PDP_FAIL_ERROR_UNSPECIFIED;
-
-fail_cause_return:
- ril_data.state.gprs_last_failed_cid = 0;
-
- ril_request_complete(t, RIL_E_SUCCESS, &fail_cause, sizeof(fail_cause));
-}
-
-/*
- * Some modem firmwares have a bug that will make the first cid (1) overriden
- * by the current cid, thus reporting it twice, with a wrong 2nd status.
- *
- * This shouldn't change anything to healthy structures.
- */
-#if RIL_VERSION >= 6
-void ipc_gprs_pdp_context_fix(RIL_Data_Call_Response_v6 *data_call_list, int c)
-#else
-void ipc_gprs_pdp_context_fix(RIL_Data_Call_Response *data_call_list, int c)
-#endif
-{
- int i, j, k;
-
- for (i = 0 ; i < c ; i++) {
- for (j = i-1 ; j >= 0 ; j--) {
- if (data_call_list[i].cid == data_call_list[j].cid) {
- for (k = 0 ; k < c ; k++) {
- if (data_call_list[k].cid == 1) {
- data_call_list[i].cid = 0;
- break;
- }
- }
-
- data_call_list[i].cid = 1;
- }
- }
- }
-}
-
-void ipc_gprs_pdp_context(struct ipc_message_info *info)
-{
- struct ril_gprs_connection *gprs_connection;
- struct ipc_gprs_ip_configuration *ip_configuration;
- struct ipc_gprs_pdp_context_get *context;
-
-#if RIL_VERSION >= 6
- RIL_Data_Call_Response_v6 data_call_list[IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT];
-#else
- RIL_Data_Call_Response data_call_list[IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT];
-#endif
-
- memset(data_call_list, 0, sizeof(data_call_list));
-
- int i;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_gprs_pdp_context_get))
- goto error;
-
- context = (struct ipc_gprs_pdp_context_get *) info->data;
-
- for (i = 0 ; i < IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT ; i++) {
- data_call_list[i].cid = context->desc[i].cid;
- data_call_list[i].active =
- ipc2ril_gprs_connection_active(context->desc[i].state);
-
- if (context->desc[i].state == IPC_GPRS_STATE_ENABLED) {
- gprs_connection = ril_gprs_connection_find_cid(context->desc[i].cid);
-
- if (gprs_connection == NULL) {
- RIL_LOGE("CID %d reported as enabled but not listed here",
- context->desc[i].cid);
- continue;
- }
-
- ip_configuration = &(gprs_connection->ip_configuration);
-
- char *addr = NULL;
- asprintf(&addr, "%i.%i.%i.%i",
- (ip_configuration->ip)[0],
- (ip_configuration->ip)[1],
- (ip_configuration->ip)[2],
- (ip_configuration->ip)[3]);
-
-#if RIL_VERSION >= 6
- RIL_Data_Call_Response_v6 *resp = &data_call_list[i];
-#else
- RIL_Data_Call_Response *resp = &data_call_list[i];
-#endif
-
- resp->type = strdup("IP");
-
-#if RIL_VERSION < 6
- resp->address = addr;
- asprintf(&(resp->apn), "%s",
- gprs_connection->define_context.apn);
-#else
- resp->addresses = addr;
- resp->gateways = strdup(addr);
- resp->ifname = strdup(gprs_connection->interface);
- asprintf(&resp->dnses, "%i.%i.%i.%i %i.%i.%i.%i",
- ip_configuration->dns1[0],
- ip_configuration->dns1[1],
- ip_configuration->dns1[2],
- ip_configuration->dns1[3],
-
- ip_configuration->dns2[0],
- ip_configuration->dns2[1],
- ip_configuration->dns2[2],
- ip_configuration->dns2[3]);
-#endif
- }
- }
-
- ipc_gprs_pdp_context_fix(data_call_list, IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT);
-
- if (info->aseq == 0xff)
- ril_request_unsolicited(RIL_UNSOL_DATA_CALL_LIST_CHANGED,
- &data_call_list, sizeof(data_call_list));
- else
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS,
- &data_call_list, sizeof(data_call_list));
-
- for (i = 0; i < IPC_GPRS_PDP_CONTEXT_GET_DESC_COUNT; i++) {
- ril_data_call_response_free(data_call_list + i);
- }
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_unsol_data_call_list_changed(void)
-{
- ipc_fmt_send_get(IPC_GPRS_PDP_CONTEXT, 0xff);
-}
-
-void ril_request_data_call_list(RIL_Token t)
-{
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- ipc_fmt_send_get(IPC_GPRS_PDP_CONTEXT, ril_request_get_id(t));
-}
diff --git a/include/plmn_list.h b/include/plmn_list.h
index a415d35..8595e43 100644
--- a/include/plmn_list.h
+++ b/include/plmn_list.h
@@ -1,13 +1,17 @@
-/**
- * This list was generated from http://en.wikipedia.org/wiki/Mobile_Network_Code
- *
- * Date: 26/07/2013 16:36:48
- * Copyright: Wikipedia Contributors, Creative Commons Attribution-ShareAlike License
+/*
+ * This list was generated from:
+ * http://en.wikipedia.org/wiki/Mobile_country_code
+ *
+ * Date: 07/08/2014 12:54:48
+ * Copyright: Wikipedia Contributors, Creative Commons
+ * Attribution-ShareAlike License
*/
#ifndef _PLMN_LIST_H_
#define _PLMN_LIST_H_
+#include <stdlib.h>
+
struct plmn_list_entry {
unsigned int mcc;
unsigned int mnc;
@@ -18,12 +22,20 @@ struct plmn_list_entry {
struct plmn_list_entry plmn_list[] = {
{ 1, 1, "TEST", "TEST" },
+ // Abkhazia
+
+ { 289, 67, "Aquafon", "Aquafon" },
+ { 289, 88, "A-Mobile", "A-Mobile" },
+
// Afghanistan - AF
{ 412, 1, "AWCC", "AWCC" },
{ 412, 20, "Roshan", "Roshan" },
{ 412, 40, "MTN", "MTN" },
{ 412, 50, "Etisalat", "Etisalat" },
+ { 412, 55, "WASEL", "WASEL" },
+ { 412, 80, "Salaam", "Salaam" },
+ { 412, 88, "Salaam", "Salaam" },
// Albania - AL
@@ -36,7 +48,7 @@ struct plmn_list_entry plmn_list[] = {
{ 603, 1, "Mobilis", "Mobilis" },
{ 603, 2, "Djezzy", "Djezzy" },
- { 603, 3, "Nedjma", "Nedjma" },
+ { 603, 3, "Ooredoo", "Ooredoo" },
// American Samoa (United States of America) - AS
@@ -54,13 +66,14 @@ struct plmn_list_entry plmn_list[] = {
// Anguilla (United Kingdom) - AI
{ 365, 10, "Weblinks Limited", "Weblinks Limited" },
- { 365, 840, "Cable & Wireless", "Cable & Wireless" },
+ { 365, 840, "LIME", "LIME" },
// Antigua and Barbuda - AG
{ 344, 30, "APUA", "APUA" },
- { 344, 920, "LIME", "LIME" },
{ 344, 50, "Digicel", "Digicel" },
+ { 344, 920, "LIME", "LIME" },
+ { 344, 930, "AT&T Wireless", "AT&T Wireless" },
// Argentina - AR
@@ -74,10 +87,12 @@ struct plmn_list_entry plmn_list[] = {
{ 722, 340, "Personal", "Personal" },
{ 722, 350, "PORT-HABLE", "PORT-HABLE" },
- // Armenia - AM
+ // Armenia - AM
{ 283, 1, "Beeline", "Beeline" },
- { 283, 5, "K Telecom CJSC", "K Telecom CJSC" },
+ { 283, 4, "Karabakh Telecom", "Karabakh Telecom" },
+ { 283, 5, "VivaCell-MTS", "VivaCell-MTS" },
+ { 283, 10, "Orange", "Orange" },
// Aruba (Kingdom of the Netherlands) - AW
@@ -92,23 +107,31 @@ struct plmn_list_entry plmn_list[] = {
{ 505, 4, "Department of Defence", "Department of Defence" },
{ 505, 5, "Ozitel", "Ozitel" },
{ 505, 6, "3", "3" },
+ { 505, 7, "Vodafone", "Vodafone" },
{ 505, 8, "One.Tel", "One.Tel" },
{ 505, 9, "Airnet", "Airnet" },
{ 505, 10, "Norfolk Is.", "Norfolk Is." },
+ { 505, 11, "Telstra", "Telstra" },
{ 505, 12, "3", "3" },
{ 505, 13, "Railcorp", "Railcorp" },
{ 505, 14, "AAPT", "AAPT" },
{ 505, 15, "3GIS", "3GIS" },
- { 505, 16, "Victorian Rail Track", "Victorian Rail Track" },
+ { 505, 16, "VicTrack", "VicTrack" },
+ { 505, 17, "Vidid Wireless Pty. Ltd.", "Vidid Wireless Pty. Ltd." },
{ 505, 18, "Pactel", "Pactel" },
- { 505, 19, "Lycamobile Pty Ltd", "Lycamobile Pty Ltd" },
- { 505, 21, "SOUL", "SOUL" },
+ { 505, 19, "Lycamobile", "Lycamobile" },
+ { 505, 20, "Ausgrid Corporation", "Ausgrid Corporation" },
+ { 505, 21, "Queensland Rail Limited", "Queensland Rail Limited" },
+ { 505, 22, "iiNet Ltd", "iiNet Ltd" },
{ 505, 23, "Challenge Networks Pty. Ltd.", "Challenge Networks Pty. Ltd." },
- { 505, 24, "Advance Communications Technologies Pty. Ltd.", "Advance Communications Technologies Pty. Ltd." },
+ { 505, 24, "Advanced Communications Technologies Pty. Ltd.", "Advanced Communications Technologies Pty. Ltd." },
+ { 505, 25, "Pilbara Iron Company Services Pty Ltd", "Pilbara Iron Company Services Pty Ltd" },
{ 505, 26, "Dialogue Communications Pty. Ltd.", "Dialogue Communications Pty. Ltd." },
{ 505, 27, "Nexium Telecommunications", "Nexium Telecommunications" },
+ { 505, 28, "RCOM International Pty Ltd", "RCOM International Pty Ltd" },
{ 505, 38, "Crazy John's", "Crazy John's" },
{ 505, 62, "NBN", "NBN" },
+ { 505, 68, "NBN", "NBN" },
{ 505, 71, "Telstra", "Telstra" },
{ 505, 72, "Telstra", "Telstra" },
{ 505, 88, "Localstar Holding Pty. Ltd.", "Localstar Holding Pty. Ltd." },
@@ -120,14 +143,16 @@ struct plmn_list_entry plmn_list[] = {
{ 232, 1, "A1 TA", "A1 TA" },
{ 232, 2, "A1 Telekom Austria", "A1 Telekom Austria" },
{ 232, 3, "T-Mobile AT", "T-Mobile AT" },
+ { 232, 4, "T-Mobile AT", "T-Mobile AT" },
{ 232, 5, "Orange AT", "Orange AT" },
+ { 232, 6, "Orange AT", "Orange AT" },
{ 232, 7, "tele.ring", "tele.ring" },
{ 232, 9, "Tele2Mobil", "Tele2Mobil" },
{ 232, 10, "3AT", "3AT" },
{ 232, 11, "bob", "bob" },
{ 232, 12, "yesss!", "yesss!" },
{ 232, 14, "Hutchison Drei Austria", "Hutchison Drei Austria" },
- { 232, 15, "A1 Telekom Austria", "A1 Telekom Austria" },
+ { 232, 15, "Vectone", "Vectone" },
{ 232, 16, "Hutchison Drei Austria", "Hutchison Drei Austria" },
// Azerbaijan - AZ
@@ -145,16 +170,18 @@ struct plmn_list_entry plmn_list[] = {
{ 426, 1, "Batelco", "Batelco" },
{ 426, 2, "zain BH", "zain BH" },
- { 426, 4, "VIVA", "VIVA" },
+ { 426, 3, "Civil Aviation Authority", "Civil Aviation Authority" },
+ { 426, 4, "VIVA Bahrain", "VIVA Bahrain" },
{ 426, 5, "Batelco", "Batelco" },
// Bangladesh - BD
{ 470, 1, "Grameenphone", "Grameenphone" },
{ 470, 2, "Robi", "Robi" },
- { 470, 3, "Banglalink Sheba", "Banglalink Sheba" },
+ { 470, 3, "Banglalink", "Banglalink" },
{ 470, 4, "TeleTalk", "TeleTalk" },
{ 470, 5, "Citycell", "Citycell" },
+ { 470, 6, "Beeong3G Warid Telekom", "Beeong3G Warid Telekom" },
{ 470, 7, "Airtel", "Airtel" },
// Barbados - BB
@@ -169,18 +196,26 @@ struct plmn_list_entry plmn_list[] = {
{ 257, 2, "MTS", "MTS" },
{ 257, 3, "DIALLOG", "DIALLOG" },
{ 257, 4, "life:)", "life:)" },
+ { 257, 5, "Beltelecom", "Beltelecom" },
+ { 257, 6, "Belorussian Cloud Technologies", "Belorussian Cloud Technologies" },
{ 257, 501, "BelCel JV", "BelCel JV" },
// Belgium - BE
{ 206, 1, "Proximus", "Proximus" },
+ { 206, 2, "N.M.B.S.", "N.M.B.S." },
{ 206, 5, "Telenet", "Telenet" },
+ { 206, 6, "Lycamobile", "Lycamobile" },
+ { 206, 7, "Vectone Mobile", "Vectone Mobile" },
+ { 206, 9, "Voxbone", "Voxbone" },
{ 206, 10, "Mobistar", "Mobistar" },
+ { 206, 15, "Elephant Talk Communications Schweiz GmbH", "Elephant Talk Communications Schweiz GmbH" },
{ 206, 20, "BASE", "BASE" },
// Belize - BZ
{ 702, 67, "DigiCell", "DigiCell" },
+ { 702, 68, "INTELCO", "INTELCO" },
{ 702, 99, "Smart", "Smart" },
// Benin - BJ
@@ -189,15 +224,15 @@ struct plmn_list_entry plmn_list[] = {
{ 616, 2, "Moov", "Moov" },
{ 616, 3, "MTN", "MTN" },
{ 616, 4, "BBCOM", "BBCOM" },
- { 616, 5, "Glo", "Glo" },
{ 616, 4, "BLK", "BLK" },
+ { 616, 5, "Glo", "Glo" },
// Bermuda - BM
+ { 310, 59, "Cellular One", "Cellular One" },
+ { 338, 50, "Digicel Bermuda", "Digicel Bermuda" },
{ 350, 1, "Digicel Bermuda", "Digicel Bermuda" },
{ 350, 2, "Mobility", "Mobility" },
- { 338, 50, "Digicel Bermuda", "Digicel Bermuda" },
- { 310, 59, "Cellular One", "Cellular One" },
// Bhutan - BT
@@ -213,7 +248,7 @@ struct plmn_list_entry plmn_list[] = {
// Bosnia and Herzegovina - BA
{ 218, 3, "HT-ERONET", "HT-ERONET" },
- { 218, 5, "m:tel ", "m:tel " },
+ { 218, 5, "m:tel", "m:tel" },
{ 218, 90, "BH Mobile", "BH Mobile" },
// Botswana - BW
@@ -228,8 +263,8 @@ struct plmn_list_entry plmn_list[] = {
{ 724, 3, "TIM", "TIM" },
{ 724, 4, "TIM", "TIM" },
{ 724, 5, "Claro BR", "Claro BR" },
- { 724, 6, "Vivo", "Vivo" },
{ 724, 55, "Sercomtel", "Sercomtel" },
+ { 724, 6, "Vivo", "Vivo" },
{ 724, 10, "Vivo", "Vivo" },
{ 724, 11, "Vivo", "Vivo" },
{ 724, 15, "CTBC Celular", "CTBC Celular" },
@@ -244,6 +279,7 @@ struct plmn_list_entry plmn_list[] = {
// British Virgin Islands (United Kingdom) - VG
{ 348, 170, "LIME", "LIME" },
+ { 348, 370, "BVI Cable TV Ltd", "BVI Cable TV Ltd" },
{ 348, 570, "CCT Boatphone", "CCT Boatphone" },
{ 348, 770, "Digicel", "Digicel" },
@@ -257,14 +293,17 @@ struct plmn_list_entry plmn_list[] = {
{ 284, 1, "M-Tel", "M-Tel" },
{ 284, 3, "Vivacom", "Vivacom" },
- { 284, 4, "Undisclosed", "Undisclosed" },
{ 284, 5, "GLOBUL", "GLOBUL" },
+ { 284, 7, "НКЖИ", "НКЖИ" },
+ { 284, 9, "COMPATEL LIMITED", "COMPATEL LIMITED" },
+ { 284, 11, "Bulsatcom", "Bulsatcom" },
+ { 284, 13, "Max Telecom", "Max Telecom" },
// Burkina Faso - BF
{ 613, 1, "Telmob", "Telmob" },
{ 613, 2, "Airtel", "Airtel" },
- { 613, 3, "Telecel Faso ", "Telecel Faso " },
+ { 613, 3, "Telecel Faso", "Telecel Faso" },
// Burundi - BI
@@ -278,15 +317,15 @@ struct plmn_list_entry plmn_list[] = {
// Cambodia - KH
{ 456, 1, "Cellcard", "Cellcard" },
- { 456, 2, "Latelz Company Limited", "Latelz Company Limited" },
- { 456, 3, "S Telecom", "S Telecom" },
+ { 456, 2, "Smart", "Smart" },
+ { 456, 3, "qb", "qb" },
{ 456, 4, "qb", "qb" },
- { 456, 5, "Star-Cell", "Star-Cell" },
+ { 456, 5, "Latelz Company Limited", "Latelz Company Limited" },
{ 456, 6, "Latelz Company Limited", "Latelz Company Limited" },
- { 456, 18, "Cellcard", "Cellcard" },
- { 456, 11, "Excell", "Excell" },
+ { 456, 8, "Cellcard", "Cellcard" },
{ 456, 9, "Beeline", "Beeline" },
- { 456, 8, "Metfone", "Metfone" },
+ { 456, 11, "Excell", "Excell" },
+ { 456, 18, "Cellcard", "Cellcard" },
// Cameroon - CM
@@ -297,20 +336,28 @@ struct plmn_list_entry plmn_list[] = {
{ 302, 220, "Telus", "Telus" },
{ 302, 221, "Telus", "Telus" },
+ { 302, 222, "Telus", "Telus" },
+ { 302, 250, "ALO", "ALO" },
{ 302, 270, "EastLink", "EastLink" },
{ 302, 290, "Airtel Wireless", "Airtel Wireless" },
- { 302, 320, "Mobilicity ", "Mobilicity " },
+ { 302, 320, "Mobilicity", "Mobilicity" },
+ { 302, 340, "Execulink", "Execulink" },
{ 302, 350, "FIRST", "FIRST" },
{ 302, 360, "MiKe", "MiKe" },
{ 302, 361, "Telus", "Telus" },
{ 302, 370, "Fido", "Fido" },
{ 302, 380, "DMTS", "DMTS" },
+ { 302, 480, "SSi Connexions", "SSi Connexions" },
{ 302, 490, "WIND Mobile", "WIND Mobile" },
{ 302, 500, "Videotron", "Videotron" },
{ 302, 510, "Videotron", "Videotron" },
- { 302, 610, "Bell", "Bell" },
+ { 302, 530, "Keewatinook Okimacinac", "Keewatinook Okimacinac" },
+ { 302, 560, "Lynx Mobility", "Lynx Mobility" },
+ { 302, 570, "LightSquared", "LightSquared" },
+ { 302, 590, "Quadro Communication", "Quadro Communication" },
{ 302, 610, "Bell", "Bell" },
{ 302, 620, "ICE Wireless", "ICE Wireless" },
+ { 302, 630, "Aliant Mobility", "Aliant Mobility" },
{ 302, 640, "Bell", "Bell" },
{ 302, 652, "BC Tel Mobility (Telus)", "BC Tel Mobility (Telus)" },
{ 302, 653, "Telus", "Telus" },
@@ -318,6 +365,7 @@ struct plmn_list_entry plmn_list[] = {
{ 302, 656, "TBay", "TBay" },
{ 302, 657, "Telus", "Telus" },
{ 302, 660, "MTS", "MTS" },
+ { 302, 670, "CityTel Mobility", "CityTel Mobility" },
{ 302, 680, "SaskTel", "SaskTel" },
{ 302, 690, "Bell", "Bell" },
{ 302, 701, "MB Tel Mobility", "MB Tel Mobility" },
@@ -325,8 +373,15 @@ struct plmn_list_entry plmn_list[] = {
{ 302, 703, "New Tel Mobility (Aliant)", "New Tel Mobility (Aliant)" },
{ 302, 710, "Globalstar", "Globalstar" },
{ 302, 720, "Rogers Wireless", "Rogers Wireless" },
+ { 302, 730, "TerreStar Solutions", "TerreStar Solutions" },
+ { 302, 740, "Shaw Telecom G.P.", "Shaw Telecom G.P." },
+ { 302, 750, "SaskTel", "SaskTel" },
+ { 302, 760, "Public Mobile Inc.", "Public Mobile Inc." },
+ { 302, 770, "Rural Com", "Rural Com" },
{ 302, 780, "SaskTel", "SaskTel" },
+ { 302, 860, "Telus", "Telus" },
{ 302, 880, "Bell / Telus / SaskTel", "Bell / Telus / SaskTel" },
+ { 302, 940, "Wightman Telecom", "Wightman Telecom" },
// Cape Verde - CV
@@ -349,7 +404,7 @@ struct plmn_list_entry plmn_list[] = {
{ 622, 1, "Airtel", "Airtel" },
{ 622, 2, "Tchad Mobile", "Tchad Mobile" },
- { 622, 2, "Tawali ", "Tawali " },
+ { 622, 2, "Tawali", "Tawali" },
{ 622, 3, "Tigo", "Tigo" },
{ 622, 4, "Salam", "Salam" },
@@ -359,10 +414,17 @@ struct plmn_list_entry plmn_list[] = {
{ 730, 2, "movistar", "movistar" },
{ 730, 3, "Claro", "Claro" },
{ 730, 4, "Nextel", "Nextel" },
+ { 730, 5, "Multikom S.A.", "Multikom S.A." },
+ { 730, 6, "Blue Two Chile S.A.", "Blue Two Chile S.A." },
{ 730, 7, "Virgin Mobile", "Virgin Mobile" },
{ 730, 8, "VTR Móvil", "VTR Móvil" },
{ 730, 9, "Nextel", "Nextel" },
{ 730, 10, "entel", "entel" },
+ { 730, 11, "Celupago S.A.", "Celupago S.A." },
+ { 730, 12, "Telestar Móvil S.A.", "Telestar Móvil S.A." },
+ { 730, 13, "Tribe Mobile Chile SPA", "Tribe Mobile Chile SPA" },
+ { 730, 14, "Netline Telefónica Móvil Ltda", "Netline Telefónica Móvil Ltda" },
+ { 730, 15, "Cibeles Telecom S.A.", "Cibeles Telecom S.A." },
{ 730, 99, "Will", "Will" },
// China - CN
@@ -370,10 +432,11 @@ struct plmn_list_entry plmn_list[] = {
{ 460, 1, "China Unicom", "China Unicom" },
{ 460, 2, "China Mobile", "China Mobile" },
{ 460, 3, "China Telecom", "China Telecom" },
+ { 460, 4, "Global Star Satellite", "Global Star Satellite" },
{ 460, 5, "China Telecom", "China Telecom" },
- { 460, 6, "China Unicom ", "China Unicom " },
+ { 460, 6, "China Unicom", "China Unicom" },
{ 460, 7, "China Mobile", "China Mobile" },
- { 460, 20, "China Tietong ", "China Tietong " },
+ { 460, 20, "China Tietong", "China Tietong" },
// Christmas Island (Australia) - CX
@@ -385,21 +448,25 @@ struct plmn_list_entry plmn_list[] = {
{ 732, 1, "Colombia Telecomunicaciones S.A.", "Colombia Telecomunicaciones S.A." },
{ 732, 2, "Edatel", "Edatel" },
+ { 732, 20, "Emtelsa", "Emtelsa" },
+ { 732, 99, "EMCALI", "EMCALI" },
{ 732, 101, "Claro", "Claro" },
{ 732, 102, "movistar", "movistar" },
{ 732, 103, "Tigo", "Tigo" },
{ 732, 111, "Tigo", "Tigo" },
{ 732, 123, "movistar", "movistar" },
+ { 732, 130, "AVANTEL", "AVANTEL" },
+ { 732, 123, "Virgin Mobile Colombia", "Virgin Mobile Colombia" },
// Comoros - KM
- { 654, 1, "HURI - SNPT", "HURI - SNPT" },
+ { 654, 1, "Comoros Telecom", "Comoros Telecom" },
// Republic of the Congo - CG
{ 629, 1, "Airtel", "Airtel" },
- { 629, 10, "Libertis Telecom", "Libertis Telecom" },
{ 629, 7, "Warid Telecom", "Warid Telecom" },
+ { 629, 10, "Libertis Telecom", "Libertis Telecom" },
// Cook Islands (New Zealand) - CK
@@ -411,6 +478,7 @@ struct plmn_list_entry plmn_list[] = {
{ 712, 2, "Kolbi ICE", "Kolbi ICE" },
{ 712, 3, "Claro", "Claro" },
{ 712, 4, "movistar", "movistar" },
+ { 712, 20, "'''full'''móvil", "'''full'''móvil" },
// Croatia - HR
@@ -427,6 +495,7 @@ struct plmn_list_entry plmn_list[] = {
{ 280, 1, "Cytamobile-Vodafone", "Cytamobile-Vodafone" },
{ 280, 10, "MTN", "MTN" },
{ 280, 20, "PrimeTel", "PrimeTel" },
+ { 280, 22, "lemontel", "lemontel" },
// Czech Republic - CZ
@@ -436,37 +505,45 @@ struct plmn_list_entry plmn_list[] = {
{ 230, 4, "U:fon", "U:fon" },
{ 230, 5, "TRAVEL TELEKOMMUNIKATION, s.r.o.", "TRAVEL TELEKOMMUNIKATION, s.r.o." },
{ 230, 6, "OSNO TELECOMUNICATION, s.r.o.", "OSNO TELECOMUNICATION, s.r.o." },
+ { 230, 7, "ASTELNET, s.r.o.", "ASTELNET, s.r.o." },
+ { 230, 8, "Compatel s.r.o.", "Compatel s.r.o." },
{ 230, 98, "Správa železniční dopravní cesty, s.o.", "Správa železniční dopravní cesty, s.o." },
{ 230, 99, "Vodafone", "Vodafone" },
// Democratic Republic of the Congo - CD
{ 630, 1, "Vodacom", "Vodacom" },
- { 630, 2, "Zain", "Zain" },
+ { 630, 2, "airtel", "airtel" },
{ 630, 4, "Cellco", "Cellco" },
{ 630, 5, "Supercell", "Supercell" },
{ 630, 10, "Libertis Telecom", "Libertis Telecom" },
- { 630, 86, "CCT", "CCT" },
- { 630, 89, "Tigo DRC", "Tigo DRC" },
- { 630, 992, "Africell", "Africell" },
+ { 630, 86, "Orange", "Orange" },
+ { 630, 88, "YTT", "YTT" },
+ { 630, 89, "Tigo", "Tigo" },
+ { 630, 90, "Africell", "Africell" },
// Denmark (Kingdom of Denmark) - DK
{ 238, 1, "TDC", "TDC" },
{ 238, 2, "Telenor", "Telenor" },
{ 238, 3, "End2End", "End2End" },
- { 238, 5, "ApS KBUS", "ApS KBUS" },
+ { 238, 4, "NextGen Mobile Ltd", "NextGen Mobile Ltd" },
+ { 238, 5, "TetraNet", "TetraNet" },
{ 238, 6, "3", "3" },
- { 238, 7, "Barablu Mobile Ltd.", "Barablu Mobile Ltd." },
- { 238, 8, "Nordisk Mobiltelefon", "Nordisk Mobiltelefon" },
- { 238, 9, "Dansk Beredskabskommunikation A/S", "Dansk Beredskabskommunikation A/S" },
+ { 238, 7, "Vectone Mobile", "Vectone Mobile" },
+ { 238, 8, "Voxbone", "Voxbone" },
+ { 238, 9, "SINE", "SINE" },
{ 238, 10, "TDC", "TDC" },
- { 238, 11, "Dansk Beredskabskommunikation A/S", "Dansk Beredskabskommunikation A/S" },
- { 238, 12, "Lycamobile Denmark Ltd", "Lycamobile Denmark Ltd" },
+ { 238, 11, "SINE", "SINE" },
+ { 238, 12, "Lycamobile", "Lycamobile" },
+ { 238, 13, "Compatel Limited", "Compatel Limited" },
{ 238, 20, "Telia", "Telia" },
{ 238, 23, "GSM-R DK", "GSM-R DK" },
- { 238, 30, "Telia", "Telia" },
+ { 238, 28, "CoolTEL ApS", "CoolTEL ApS" },
+ { 238, 30, "Interactive digital media GmbH", "Interactive digital media GmbH" },
{ 238, 40, "Ericsson Danmark A/S", "Ericsson Danmark A/S" },
+ { 238, 43, "MobiWeb Limited", "MobiWeb Limited" },
+ { 238, 66, "TT-Netværket P/S", "TT-Netværket P/S" },
{ 238, 77, "Telenor", "Telenor" },
// Djibouti - DJ
@@ -487,7 +564,7 @@ struct plmn_list_entry plmn_list[] = {
// East Timor - TL
- { 514, 1, "Telin", "Telin" },
+ { 514, 1, "Telin Telkomcel", "Telin Telkomcel" },
{ 514, 2, "Timor Telecom", "Timor Telecom" },
{ 514, 3, "Viettel Timor-Leste", "Viettel Timor-Leste" },
@@ -526,6 +603,10 @@ struct plmn_list_entry plmn_list[] = {
{ 248, 4, "OY Top Connect", "OY Top Connect" },
{ 248, 5, "AS Bravocom Mobiil", "AS Bravocom Mobiil" },
{ 248, 6, "Progroup Holding", "Progroup Holding" },
+ { 248, 7, "Televõrgu AS", "Televõrgu AS" },
+ { 248, 8, "VIVEX", "VIVEX" },
+ { 248, 9, "Bravo Telecom", "Bravo Telecom" },
+ { 248, 71, "Siseministeerium (Ministry of Interior)", "Siseministeerium (Ministry of Interior)" },
// Ethiopia - ET
@@ -535,11 +616,13 @@ struct plmn_list_entry plmn_list[] = {
{ 288, 1, "Faroese Telecom", "Faroese Telecom" },
{ 288, 2, "Vodafone", "Vodafone" },
+ { 288, 3, "Edge Mobile Sp/F", "Edge Mobile Sp/F" },
// Fiji - FJ
{ 542, 1, "Vodafone", "Vodafone" },
{ 542, 2, "Digicel", "Digicel" },
+ { 542, 3, "Telecom Fiji Ltd", "Telecom Fiji Ltd" },
// Finland - FI
@@ -547,43 +630,69 @@ struct plmn_list_entry plmn_list[] = {
{ 244, 4, "AINA", "AINA" },
{ 244, 5, "Elisa", "Elisa" },
{ 244, 7, "Nokia", "Nokia" },
- { 244, 8, "Unknown", "Unknown" },
- { 244, 9, "Finnet Group / NOKIA OYJ", "Finnet Group / NOKIA OYJ" },
+ { 244, 8, "Nokia", "Nokia" },
+ { 244, 9, "Finnet Group / Nokia Solutions and Networks", "Finnet Group / Nokia Solutions and Networks" },
{ 244, 10, "TDC", "TDC" },
- { 244, 11, "VIRVE", "VIRVE" },
+ { 244, 11, "Vectone Mobile", "Vectone Mobile" },
{ 244, 12, "DNA", "DNA" },
- { 244, 14, "AMT", "AMT" },
+ { 244, 13, "DNA", "DNA" },
+ { 244, 14, "Ålcom", "Ålcom" },
{ 244, 15, "SAMK", "SAMK" },
+ { 244, 16, "Oy Finland Tele2 AB", "Oy Finland Tele2 AB" },
{ 244, 21, "Saunalahti", "Saunalahti" },
- { 244, 29, "Scnl Truphone", "Scnl Truphone" },
+ { 244, 25, "Datame", "Datame" },
+ { 244, 26, "Compatel", "Compatel" },
+ { 244, 29, "SCNL Truphone", "SCNL Truphone" },
+ { 244, 30, "Vectone Mobile", "Vectone Mobile" },
+ { 244, 31, "Ukko Mobile", "Ukko Mobile" },
+ { 244, 32, "Voxbone", "Voxbone" },
{ 244, 91, "Sonera", "Sonera" },
// France - FR
{ 208, 1, "Orange", "Orange" },
{ 208, 2, "Orange", "Orange" },
- { 208, 4, "Sisteer ", "Sisteer " },
+ { 208, 3, "MobiquiThings", "MobiquiThings" },
+ { 208, 4, "Sisteer", "Sisteer" },
{ 208, 5, "Globalstar Europe", "Globalstar Europe" },
{ 208, 6, "Globalstar Europe", "Globalstar Europe" },
{ 208, 7, "Globalstar Europe", "Globalstar Europe" },
+ { 208, 8, "Completel Mobile", "Completel Mobile" },
+ { 208, 9, "SFR", "SFR" },
{ 208, 10, "SFR", "SFR" },
{ 208, 11, "SFR", "SFR" },
{ 208, 13, "SFR", "SFR" },
{ 208, 14, "RFF", "RFF" },
{ 208, 15, "Free Mobile", "Free Mobile" },
{ 208, 16, "Free Mobile", "Free Mobile" },
+ { 208, 17, "LEGOS", "LEGOS" },
+ { 208, 18, "Voxbone", "Voxbone" },
{ 208, 20, "Bouygues", "Bouygues" },
{ 208, 21, "Bouygues", "Bouygues" },
{ 208, 22, "Transatel Mobile", "Transatel Mobile" },
{ 208, 23, "Virgin Mobile (MVNO)", "Virgin Mobile (MVNO)" },
+ { 208, 24, "MobiquiThings", "MobiquiThings" },
{ 208, 25, "LycaMobile", "LycaMobile" },
{ 208, 26, "NRJ Mobile (MVNO)", "NRJ Mobile (MVNO)" },
+ { 208, 27, "Afone", "Afone" },
+ { 208, 28, "Astrium SAS", "Astrium SAS" },
+ { 208, 29, "Société International Mobile Communication", "Société International Mobile Communication" },
+ { 208, 30, "Symacom", "Symacom" },
+ { 208, 31, "Vectone", "Vectone" },
+ { 208, 88, "Bouygues", "Bouygues" },
+ { 208, 89, "Omer Telecom Ltd", "Omer Telecom Ltd" },
+ { 208, 90, "Images & Réseaux", "Images & Réseaux" },
+ { 208, 91, "Orange S.A.", "Orange S.A." },
+ { 208, 92, "Com4Innov", "Com4Innov" },
+ { 208, 93, "TDF", "TDF" },
// French Guiana (France) - GF
// French Polynesia (France) - PF
+ { 547, 10, "Mara Telecom", "Mara Telecom" },
+ { 547, 15, "Vodafone", "Vodafone" },
{ 547, 20, "Vini", "Vini" },
// French Southern Territories (France) - TF
@@ -595,13 +704,14 @@ struct plmn_list_entry plmn_list[] = {
{ 628, 2, "Moov", "Moov" },
{ 628, 3, "Airtel", "Airtel" },
{ 628, 4, "Azur", "Azur" },
+ { 628, 5, "RAG", "RAG" },
// Gambia - GM
{ 607, 1, "Gamcel", "Gamcel" },
{ 607, 2, "Africel", "Africel" },
{ 607, 3, "Comium", "Comium" },
- { 607, 4, "QCell ", "QCell " },
+ { 607, 4, "QCell", "QCell" },
// Georgia - GE
@@ -610,10 +720,12 @@ struct plmn_list_entry plmn_list[] = {
{ 282, 3, "MagtiCom", "MagtiCom" },
{ 282, 4, "Beeline", "Beeline" },
{ 282, 5, "Silknet", "Silknet" },
+ { 282, 6, "JSC Compatel", "JSC Compatel" },
+ { 282, 7, "GlobalCell Ltd", "GlobalCell Ltd" },
// Germany - DE
- { 262, 1, "T-Mobile", "T-Mobile" },
+ { 262, 1, "Telekom", "Telekom" },
{ 262, 2, "Vodafone", "Vodafone" },
{ 262, 3, "E-Plus", "E-Plus" },
{ 262, 4, "Vodafone", "Vodafone" },
@@ -622,19 +734,25 @@ struct plmn_list_entry plmn_list[] = {
{ 262, 7, "O2", "O2" },
{ 262, 8, "O2", "O2" },
{ 262, 9, "Vodafone", "Vodafone" },
- { 262, 10, "Arcor AG & Co", "Arcor AG & Co" },
+ { 262, 10, "DB Netz AG", "DB Netz AG" },
{ 262, 11, "O2", "O2" },
{ 262, 12, "Dolphin Telecom / sipgate", "Dolphin Telecom / sipgate" },
{ 262, 13, "Mobilcom Multimedia", "Mobilcom Multimedia" },
{ 262, 14, "Group 3G UMTS", "Group 3G UMTS" },
{ 262, 15, "Airdata", "Airdata" },
{ 262, 16, "Telogic ex. Vistream", "Telogic ex. Vistream" },
+ { 262, 17, "E-Plus", "E-Plus" },
+ { 262, 18, "NetCologne", "NetCologne" },
+ { 262, 19, "Inquam Deutschland", "Inquam Deutschland" },
{ 262, 20, "OnePhone", "OnePhone" },
- { 262, 42, "27C3", "27C3" },
+ { 262, 41, "First Telecom GmbH", "First Telecom GmbH" },
+ { 262, 42, "CCC Event", "CCC Event" },
{ 262, 43, "LYCA", "LYCA" },
{ 262, 60, "DB Telematik", "DB Telematik" },
{ 262, 76, "Siemens AG", "Siemens AG" },
{ 262, 77, "E-Plus", "E-Plus" },
+ { 262, 78, "T-Mobile", "T-Mobile" },
+ { 262, 79, "ng4T GmbH", "ng4T GmbH" },
{ 262, 92, "Nash Technologies", "Nash Technologies" },
{ 262, 901, "Debitel", "Debitel" },
@@ -643,9 +761,10 @@ struct plmn_list_entry plmn_list[] = {
{ 620, 1, "MTN", "MTN" },
{ 620, 2, "Vodafone", "Vodafone" },
{ 620, 3, "tiGO", "tiGO" },
- { 620, 4, "Expresso ", "Expresso " },
+ { 620, 4, "Expresso", "Expresso" },
{ 620, 6, "Airtel", "Airtel" },
- { 620, 7, "Globacom (Zain)", "Globacom (Zain)" },
+ { 620, 7, "Globacom", "Globacom" },
+ { 620, 11, "Netafrique Dot Com Ltd", "Netafrique Dot Com Ltd" },
// Gibraltar (United Kingdom) - GI
@@ -656,7 +775,12 @@ struct plmn_list_entry plmn_list[] = {
// Greece - GR
{ 202, 1, "Cosmote", "Cosmote" },
+ { 202, 2, "Cosmote", "Cosmote" },
+ { 202, 3, "OTE", "OTE" },
+ { 202, 4, "EDISY", "EDISY" },
{ 202, 5, "Vodafone", "Vodafone" },
+ { 202, 6, "Cosmoline", "Cosmoline" },
+ { 202, 7, "AMD Telecom", "AMD Telecom" },
{ 202, 9, "Wind", "Wind" },
{ 202, 10, "Wind", "Wind" },
@@ -682,21 +806,21 @@ struct plmn_list_entry plmn_list[] = {
{ 310, 32, "IT&E Wireless", "IT&E Wireless" },
{ 310, 33, "Guam Telephone Authority", "Guam Telephone Authority" },
{ 310, 140, "mPulse", "mPulse" },
- { 310, 370, "docomo", "docomo" },
{ 311, 250, "i CAN_GSM", "i CAN_GSM" },
- { 310, 470, "docomo", "docomo" },
+ { 310, 370, "Docomo", "Docomo" },
+ { 310, 470, "Docomo", "Docomo" },
// Guatemala - GT
{ 704, 1, "Claro", "Claro" },
- { 704, 201, "Tigo", "Tigo" },
+ { 704, 2, "Tigo", "Tigo" },
{ 704, 3, "movistar", "movistar" },
// Guernsey (United Kingdom) - GG
- { 234, 55, "Sure Mobile", "Sure Mobile" },
- { 234, 50, "Wave Telecom", "Wave Telecom" },
{ 234, 3, "Airtel Vodafone", "Airtel Vodafone" },
+ { 234, 50, "Wave Telecom", "Wave Telecom" },
+ { 234, 55, "Sure Mobile", "Sure Mobile" },
// Guinea - GN
@@ -708,7 +832,8 @@ struct plmn_list_entry plmn_list[] = {
// Guinea-Bissau - GW
- { 632, 2, "Areeba", "Areeba" },
+ { 632, 1, "Guinetel", "Guinetel" },
+ { 632, 2, "MTN Areeba", "MTN Areeba" },
{ 632, 3, "Orange", "Orange" },
{ 632, 7, "Guinetel", "Guinetel" },
@@ -721,20 +846,20 @@ struct plmn_list_entry plmn_list[] = {
{ 372, 1, "Voila", "Voila" },
{ 372, 2, "Digicel", "Digicel" },
- { 372, 3, "Telecommunication S.A.", "Telecommunication S.A." },
+ { 372, 3, "Natcom", "Natcom" },
// Honduras - HN
{ 708, 1, "Claro", "Claro" },
{ 708, 2, "Tigo", "Tigo" },
{ 708, 30, "Hondutel", "Hondutel" },
- { 708, 40, "DIGICEL ", "DIGICEL " },
+ { 708, 40, "Digicel", "Digicel" },
// Hong Kong - HK
{ 454, 1, "CITIC Telecom 1616", "CITIC Telecom 1616" },
- { 454, 2, "CSL Limited ", "CSL Limited " },
- { 454, 3, "3 (3G) ", "3 (3G) " },
+ { 454, 2, "CSL Limited", "CSL Limited" },
+ { 454, 3, "3", "3" },
{ 454, 4, "3 (2G)", "3 (2G)" },
{ 454, 5, "3 (CDMA)", "3 (CDMA)" },
{ 454, 6, "SmarTone", "SmarTone" },
@@ -749,17 +874,19 @@ struct plmn_list_entry plmn_list[] = {
{ 454, 15, "SmarTone Mobile Communications Limited", "SmarTone Mobile Communications Limited" },
{ 454, 16, "PCCW Mobile (2G)", "PCCW Mobile (2G)" },
{ 454, 17, "SmarTone Mobile Communications Limited", "SmarTone Mobile Communications Limited" },
- { 454, 18, "CSL Limited ", "CSL Limited " },
- { 454, 19, "PCCW Mobile (3G)", "PCCW Mobile (3G)" },
+ { 454, 18, "CSL Limited", "CSL Limited" },
+ { 454, 19, "PCCW Mobile (3G/4G)", "PCCW Mobile (3G/4G)" },
{ 454, 22, "P Plus", "P Plus" },
{ 454, 29, "PCCW Mobile (CDMA)", "PCCW Mobile (CDMA)" },
// Hungary - HU
{ 216, 1, "Telenor", "Telenor" },
+ { 216, 20, "Telenor", "Telenor" },
{ 216, 30, "T-Mobile", "T-Mobile" },
{ 216, 70, "Vodafone", "Vodafone" },
{ 216, 71, "UPC Hungary", "UPC Hungary" },
+ { 216, 99, "MAV GSM-R", "MAV GSM-R" },
// Iceland - IS
@@ -862,31 +989,12 @@ struct plmn_list_entry plmn_list[] = {
{ 404, 97, "AirTel", "AirTel" },
{ 404, 98, "AirTel", "AirTel" },
{ 405, 1, "Reliance", "Reliance" },
- { 405, 3, "Reliance", "Reliance" },
- { 405, 4, "Reliance", "Reliance" },
- { 405, 5, "Reliance", "Reliance" },
- { 405, 6, "Reliance", "Reliance" },
- { 405, 7, "Reliance", "Reliance" },
- { 405, 8, "Reliance", "Reliance" },
- { 405, 9, "Reliance", "Reliance" },
- { 405, 10, "Reliance", "Reliance" },
- { 405, 11, "Reliance", "Reliance" },
- { 405, 12, "Reliance", "Reliance" },
- { 405, 13, "Reliance", "Reliance" },
- { 405, 14, "Reliance", "Reliance" },
- { 405, 15, "Reliance", "Reliance" },
- { 405, 17, "Reliance", "Reliance" },
- { 405, 18, "Reliance", "Reliance" },
- { 405, 19, "Reliance", "Reliance" },
- { 405, 20, "Reliance", "Reliance" },
- { 405, 21, "Reliance", "Reliance" },
- { 405, 22, "Reliance", "Reliance" },
- { 405, 23, "Reliance", "Reliance" },
{ 405, 25, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 26, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 27, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 28, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 29, "TATA DOCOMO", "TATA DOCOMO" },
+ { 405, 3, "Reliance", "Reliance" },
{ 405, 30, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 31, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 32, "TATA DOCOMO", "TATA DOCOMO" },
@@ -897,6 +1005,7 @@ struct plmn_list_entry plmn_list[] = {
{ 405, 37, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 38, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 39, "TATA DOCOMO", "TATA DOCOMO" },
+ { 405, 4, "Reliance", "Reliance" },
{ 405, 41, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 42, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 43, "TATA DOCOMO", "TATA DOCOMO" },
@@ -904,6 +1013,24 @@ struct plmn_list_entry plmn_list[] = {
{ 405, 45, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 46, "TATA DOCOMO", "TATA DOCOMO" },
{ 405, 47, "TATA DOCOMO", "TATA DOCOMO" },
+ { 405, 5, "Reliance", "Reliance" },
+ { 405, 6, "Reliance", "Reliance" },
+ { 405, 7, "Reliance", "Reliance" },
+ { 405, 8, "Reliance", "Reliance" },
+ { 405, 9, "Reliance", "Reliance" },
+ { 405, 10, "Reliance", "Reliance" },
+ { 405, 11, "Reliance", "Reliance" },
+ { 405, 12, "Reliance", "Reliance" },
+ { 405, 13, "Reliance", "Reliance" },
+ { 405, 14, "Reliance", "Reliance" },
+ { 405, 15, "Reliance", "Reliance" },
+ { 405, 17, "Reliance", "Reliance" },
+ { 405, 18, "Reliance", "Reliance" },
+ { 405, 19, "Reliance", "Reliance" },
+ { 405, 20, "Reliance", "Reliance" },
+ { 405, 21, "Reliance", "Reliance" },
+ { 405, 22, "Reliance", "Reliance" },
+ { 405, 23, "Reliance", "Reliance" },
{ 405, 51, "AirTel", "AirTel" },
{ 405, 52, "AirTel", "AirTel" },
{ 405, 53, "AirTel", "AirTel" },
@@ -911,6 +1038,7 @@ struct plmn_list_entry plmn_list[] = {
{ 405, 55, "Airtel", "Airtel" },
{ 405, 56, "AirTel", "AirTel" },
{ 405, 66, "Vodafone IN", "Vodafone IN" },
+ { 405, 67, "Vodafone IN", "Vodafone IN" },
{ 405, 70, "IDEA", "IDEA" },
{ 405, 750, "Vodafone IN", "Vodafone IN" },
{ 405, 751, "Vodafone IN", "Vodafone IN" },
@@ -942,6 +1070,7 @@ struct plmn_list_entry plmn_list[] = {
{ 405, 827, "Videocon Datacom", "Videocon Datacom" },
{ 405, 834, "Videocon Datacom", "Videocon Datacom" },
{ 405, 844, "Uninor", "Uninor" },
+ { 405, 840, "Jio", "Jio" },
{ 405, 845, "IDEA", "IDEA" },
{ 405, 846, "IDEA", "IDEA" },
{ 405, 847, "IDEA", "IDEA" },
@@ -951,27 +1080,27 @@ struct plmn_list_entry plmn_list[] = {
{ 405, 851, "IDEA", "IDEA" },
{ 405, 852, "IDEA", "IDEA" },
{ 405, 853, "IDEA", "IDEA" },
- { 405, 854, "Loop Mobile", "Loop Mobile" },
- { 405, 855, "Loop Mobile", "Loop Mobile" },
- { 405, 856, "Loop Mobile", "Loop Mobile" },
- { 405, 857, "Loop Mobile", "Loop Mobile" },
- { 405, 858, "Loop Mobile", "Loop Mobile" },
- { 405, 859, "Loop Mobile", "Loop Mobile" },
- { 405, 860, "Loop Mobile", "Loop Mobile" },
- { 405, 861, "Loop Mobile", "Loop Mobile" },
- { 405, 862, "Loop Mobile", "Loop Mobile" },
- { 405, 863, "Loop Mobile", "Loop Mobile" },
- { 405, 864, "Loop Mobile", "Loop Mobile" },
- { 405, 865, "Loop Mobile", "Loop Mobile" },
- { 405, 866, "Loop Mobile", "Loop Mobile" },
- { 405, 867, "Loop Mobile", "Loop Mobile" },
- { 405, 868, "Loop Mobile", "Loop Mobile" },
- { 405, 869, "Loop Mobile", "Loop Mobile" },
- { 405, 870, "Loop Mobile", "Loop Mobile" },
- { 405, 871, "Loop Mobile", "Loop Mobile" },
- { 405, 872, "Loop Mobile", "Loop Mobile" },
- { 405, 873, "Loop Mobile", "Loop Mobile" },
- { 405, 874, "Loop Mobile", "Loop Mobile" },
+ { 405, 854, "Jio", "Jio" },
+ { 405, 855, "Jio", "Jio" },
+ { 405, 856, "Jio", "Jio" },
+ { 405, 857, "Jio", "Jio" },
+ { 405, 858, "Jio", "Jio" },
+ { 405, 859, "Jio", "Jio" },
+ { 405, 860, "Jio", "Jio" },
+ { 405, 861, "Jio", "Jio" },
+ { 405, 862, "Jio", "Jio" },
+ { 405, 863, "Jio", "Jio" },
+ { 405, 864, "Jio", "Jio" },
+ { 405, 865, "Jio", "Jio" },
+ { 405, 866, "Jio", "Jio" },
+ { 405, 867, "Jio", "Jio" },
+ { 405, 868, "Jio", "Jio" },
+ { 405, 869, "Jio", "Jio" },
+ { 405, 870, "Jio", "Jio" },
+ { 405, 871, "Jio", "Jio" },
+ { 405, 872, "Jio", "Jio" },
+ { 405, 873, "Jio", "Jio" },
+ { 405, 874, "Jio", "Jio" },
{ 405, 875, "Uninor", "Uninor" },
{ 405, 880, "Uninor", "Uninor" },
{ 405, 881, "S Tel", "S Tel" },
@@ -992,7 +1121,7 @@ struct plmn_list_entry plmn_list[] = {
{ 510, 3, "StarOne", "StarOne" },
{ 510, 7, "TelkomFlexi", "TelkomFlexi" },
{ 510, 8, "AXIS", "AXIS" },
- { 510, 9, "SMART", "SMART" },
+ { 510, 9, "SMARTFREN", "SMARTFREN" },
{ 510, 10, "Telkomsel", "Telkomsel" },
{ 510, 11, "XL", "XL" },
{ 510, 20, "TELKOMMobile", "TELKOMMobile" },
@@ -1002,6 +1131,7 @@ struct plmn_list_entry plmn_list[] = {
{ 510, 89, "3", "3" },
{ 510, 99, "Esia", "Esia" },
{ 510, 995, "Komselindo", "Komselindo" },
+ { 510, 996, "Komselindo", "Komselindo" },
// Iran - IR
@@ -1039,8 +1169,8 @@ struct plmn_list_entry plmn_list[] = {
// Isle of Man (United Kingdom) - IM
- { 234, 58, "Pronto GSM", "Pronto GSM" },
{ 234, 9, "Sure Mobile", "Sure Mobile" },
+ { 234, 58, "Pronto GSM", "Pronto GSM" },
// Israel - IL
@@ -1049,10 +1179,17 @@ struct plmn_list_entry plmn_list[] = {
{ 425, 3, "Pelephone", "Pelephone" },
{ 425, 7, "Hot Mobile", "Hot Mobile" },
{ 425, 8, "Golan Telecom", "Golan Telecom" },
+ { 425, 11, "365 Telecom", "365 Telecom" },
+ { 425, 12, "Free Telecom", "Free Telecom" },
+ { 425, 13, "Ituran Cellular Communications", "Ituran Cellular Communications" },
{ 425, 14, "Youphone", "Youphone" },
{ 425, 15, "Home Cellular", "Home Cellular" },
{ 425, 16, "Rami Levy", "Rami Levy" },
+ { 425, 17, "Gale Phone", "Gale Phone" },
{ 425, 18, "Cellact Communications", "Cellact Communications" },
+ { 425, 19, "Azi Communications Ltd.", "Azi Communications Ltd." },
+ { 425, 20, "Bezeq Ltd", "Bezeq Ltd" },
+ { 425, 21, "B.I.P. Communications Ltd.", "B.I.P. Communications Ltd." },
// Italy - IT
@@ -1063,6 +1200,7 @@ struct plmn_list_entry plmn_list[] = {
{ 222, 7, "Noverca", "Noverca" },
{ 222, 10, "Vodafone", "Vodafone" },
{ 222, 30, "RFI", "RFI" },
+ { 222, 34, "BT Italia", "BT Italia" },
{ 222, 35, "Lyca Italy", "Lyca Italy" },
{ 222, 77, "IPSE 2000", "IPSE 2000" },
{ 222, 88, "Wind", "Wind" },
@@ -1082,6 +1220,7 @@ struct plmn_list_entry plmn_list[] = {
{ 338, 20, "LIME", "LIME" },
{ 338, 50, "Digicel", "Digicel" },
+ { 338, 110, "LIME", "LIME" },
{ 338, 180, "LIME", "LIME" },
// Japan - JP
@@ -1184,14 +1323,14 @@ struct plmn_list_entry plmn_list[] = {
// Jersey (United Kingdom) - JE
+ { 234, 3, "Airtel Vodafone", "Airtel Vodafone" },
{ 234, 50, "JT", "JT" },
{ 234, 55, "Sure Mobile", "Sure Mobile" },
- { 234, 3, "Airtel Vodafone", "Airtel Vodafone" },
// Jordan - JO
{ 416, 1, "zain JO", "zain JO" },
- { 416, 74, "XPress Telecom", "XPress Telecom" },
+ { 416, 2, "XPress Telecom", "XPress Telecom" },
{ 416, 3, "Umniah", "Umniah" },
{ 416, 77, "Orange", "Orange" },
@@ -1201,19 +1340,18 @@ struct plmn_list_entry plmn_list[] = {
{ 401, 2, "Kcell", "Kcell" },
{ 401, 7, "Dalacom", "Dalacom" },
{ 401, 8, "Kazakhtelecom", "Kazakhtelecom" },
- { 401, 10, "Dontelecom", "Dontelecom" },
{ 401, 77, "Tele2.kz", "Tele2.kz" },
// Kenya - KE
{ 639, 2, "Safaricom", "Safaricom" },
{ 639, 3, "Airtel", "Airtel" },
- { 639, 7, "Orange Kenya", "Orange Kenya" },
{ 639, 5, "yu", "yu" },
+ { 639, 7, "Orange Kenya", "Orange Kenya" },
// Kiribati - KI
- { 545, 1, "Kiribati - Frigate Net", "Kiribati - Frigate Net" },
+ { 545, 1, "Kiribati - TSKL", "Kiribati - TSKL" },
{ 545, 9, "Kiribati - Frigate Net", "Kiribati - Frigate Net" },
// North Korea - KP
@@ -1231,12 +1369,12 @@ struct plmn_list_entry plmn_list[] = {
{ 450, 8, "olleh", "olleh" },
{ 450, 11, "SKTelecom", "SKTelecom" },
- // Kosovo - RKS
+ // Kosovo - XK
{ 212, 1, "Vala", "Vala" },
+ { 212, 1, "Z Mobile", "Z Mobile" },
{ 293, 41, "IPKO", "IPKO" },
{ 293, 41, "D3 Mobile", "D3 Mobile" },
- { 212, 1, "Z Mobile", "Z Mobile" },
// Kuwait - KW
@@ -1263,6 +1401,7 @@ struct plmn_list_entry plmn_list[] = {
{ 247, 1, "LMT", "LMT" },
{ 247, 2, "Tele2", "Tele2" },
{ 247, 3, "TRIATEL", "TRIATEL" },
+ { 247, 4, "Beta Telecom", "Beta Telecom" },
{ 247, 5, "Bite", "Bite" },
{ 247, 6, "Rigatta", "Rigatta" },
{ 247, 7, "MTS", "MTS" },
@@ -1300,21 +1439,24 @@ struct plmn_list_entry plmn_list[] = {
{ 295, 1, "Swisscom", "Swisscom" },
{ 295, 2, "Orange", "Orange" },
{ 295, 5, "FL1", "FL1" },
- { 295, 77, "Alpmobil", "Alpmobil" },
{ 295, 6, "Cubic Telecom", "Cubic Telecom" },
+ { 295, 77, "Alpmobil", "Alpmobil" },
// Lithuania - LT
{ 246, 1, "Omnitel", "Omnitel" },
- { 246, 2, "BITE", "BITE" },
+ { 246, 2, "BITĖ", "BITĖ" },
{ 246, 3, "Tele 2", "Tele 2" },
{ 246, 5, "LitRail", "LitRail" },
{ 246, 6, "Mediafon", "Mediafon" },
// Luxembourg - LU
- { 270, 1, "LuxGSM", "LuxGSM" },
+ { 270, 1, "POST", "POST" },
+ { 270, 2, "MTX Connect S.a.r.l.", "MTX Connect S.a.r.l." },
+ { 270, 10, "Blue Communications", "Blue Communications" },
{ 270, 77, "Tango", "Tango" },
+ { 270, 78, "Interactive digital media GmbH", "Interactive digital media GmbH" },
{ 270, 99, "Orange", "Orange" },
// Macau (People's Republic of China) - MO
@@ -1324,6 +1466,7 @@ struct plmn_list_entry plmn_list[] = {
{ 455, 3, "3", "3" },
{ 455, 4, "CTM", "CTM" },
{ 455, 5, "3", "3" },
+ { 455, 6, "SmarTone", "SmarTone" },
// Macedonia - MK
@@ -1335,7 +1478,7 @@ struct plmn_list_entry plmn_list[] = {
{ 646, 1, "Airtel", "Airtel" },
{ 646, 2, "Orange", "Orange" },
- { 646, 3, "Sacel ", "Sacel " },
+ { 646, 3, "Sacel", "Sacel" },
{ 646, 4, "Telma", "Telma" },
// Malawi - MW
@@ -1351,20 +1494,22 @@ struct plmn_list_entry plmn_list[] = {
{ 502, 12, "Maxis", "Maxis" },
{ 502, 13, "Celcom", "Celcom" },
{ 502, 14, "Telekom Malaysia Berhad for PSTN SMS", "Telekom Malaysia Berhad for PSTN SMS" },
+ { 502, 150, "Tune Talk", "Tune Talk" },
+ { 502, 151, "Baraka Telecom Sdn Bhd (MVNE)", "Baraka Telecom Sdn Bhd (MVNE)" },
+ { 502, 152, "Yes", "Yes" },
+ { 502, 156, "Altel", "Altel" },
{ 502, 16, "DiGi", "DiGi" },
{ 502, 17, "Hotlink", "Hotlink" },
{ 502, 18, "U Mobile", "U Mobile" },
{ 502, 18, "TM Homeline", "TM Homeline" },
{ 502, 19, "Celcom", "Celcom" },
{ 502, 20, "Electcoms Wireless Sdn Bhd", "Electcoms Wireless Sdn Bhd" },
- { 502, 150, "Tune Talk", "Tune Talk" },
- { 502, 151, "Baraka Telecom Sdn Bhd (MVNE)", "Baraka Telecom Sdn Bhd (MVNE)" },
- { 502, 152, "Yes", "Yes" },
+ { 502, 12, "Kartu As", "Kartu As" },
// Maldives - MV
{ 472, 1, "Dhiraagu", "Dhiraagu" },
- { 472, 2, "Wataniya", "Wataniya" },
+ { 472, 2, "Ooredoo", "Ooredoo" },
// Mali - ML
@@ -1379,7 +1524,7 @@ struct plmn_list_entry plmn_list[] = {
// Marshall Islands - MH
- { 551, 1, "Marshall Islands National Telecommunications Authority (MINTA) ", "Marshall Islands National Telecommunications Authority (MINTA) " },
+ { 551, 1, "Marshall Islands National Telecommunications Authority (MINTA)", "Marshall Islands National Telecommunications Authority (MINTA)" },
// Martinique (France) - MQ
@@ -1407,6 +1552,7 @@ struct plmn_list_entry plmn_list[] = {
{ 334, 10, "Nextel", "Nextel" },
{ 334, 20, "Telcel", "Telcel" },
{ 334, 30, "movistar", "movistar" },
+ { 334, 30, "Virgin Mobile", "Virgin Mobile" },
{ 334, 40, "Iusacell / Unefon", "Iusacell / Unefon" },
{ 334, 50, "Iusacell", "Iusacell" },
{ 334, 90, "Nextel", "Nextel" },
@@ -1462,12 +1608,14 @@ struct plmn_list_entry plmn_list[] = {
// Myanmar - MM
{ 414, 1, "MPT", "MPT" },
+ { 414, 5, "Ooredoo", "Ooredoo" },
+ { 414, 6, "NA", "NA" },
// Namibia - NA
{ 649, 1, "MTC", "MTC" },
{ 649, 2, "switch", "switch" },
- { 649, 3, "Leo", "Leo" },
+ { 649, 3, "TN Mobile", "TN Mobile" },
// Nauru - NR
@@ -1482,20 +1630,21 @@ struct plmn_list_entry plmn_list[] = {
// Netherlands (Kingdom of the Netherlands) - NL
- { 204, 1, "VastMobiel B.V.", "VastMobiel B.V." },
+ { 204, 1, "RadioAccess Network Services BV", "RadioAccess Network Services BV" },
{ 204, 2, "Tele2", "Tele2" },
{ 204, 3, "Voiceworks", "Voiceworks" },
- { 204, 4, "Vodafone Libertel B.V.", "Vodafone Libertel B.V." },
+ { 204, 4, "Vodafone", "Vodafone" },
{ 204, 5, "Elephant Talk Communications Premium Rate Services", "Elephant Talk Communications Premium Rate Services" },
- { 204, 6, "Vectone Mobile Delight Mobile ", "Vectone Mobile Delight Mobile " },
+ { 204, 6, "Vectone Mobile Delight Mobile", "Vectone Mobile Delight Mobile" },
{ 204, 7, "Teleena (MVNE)", "Teleena (MVNE)" },
{ 204, 8, "KPN", "KPN" },
{ 204, 9, "Lycamobile", "Lycamobile" },
{ 204, 10, "KPN", "KPN" },
+ { 204, 11, "VoipIT B.V.", "VoipIT B.V." },
{ 204, 12, "Telfort", "Telfort" },
{ 204, 13, "Unica Installatietechniek B.V.", "Unica Installatietechniek B.V." },
{ 204, 14, "6GMOBILE B.V.", "6GMOBILE B.V." },
- { 204, 15, "Ziggo B.V.", "Ziggo B.V." },
+ { 204, 15, "Ziggo", "Ziggo" },
{ 204, 16, "T-Mobile (BEN)", "T-Mobile (BEN)" },
{ 204, 17, "Intercity Zakelijk", "Intercity Zakelijk" },
{ 204, 18, "UPC Nederland B.V.", "UPC Nederland B.V." },
@@ -1509,17 +1658,23 @@ struct plmn_list_entry plmn_list[] = {
{ 204, 26, "SpeakUp B.V.", "SpeakUp B.V." },
{ 204, 27, "Breezz Nederland B.V.", "Breezz Nederland B.V." },
{ 204, 28, "Lancelot B.V.", "Lancelot B.V." },
+ { 204, 60, "Nextgen Mobile Ltd", "Nextgen Mobile Ltd" },
+ { 204, 61, "BodyTrace Netherlands B.V.", "BodyTrace Netherlands B.V." },
+ { 204, 62, "Voxbone", "Voxbone" },
+ { 204, 64, "Zetacom B.V.", "Zetacom B.V." },
+ { 204, 65, "AGMS Netherlands B.V.", "AGMS Netherlands B.V." },
+ { 204, 66, "Utility Connect B.V.", "Utility Connect B.V." },
{ 204, 67, "RadioAccess B.V.", "RadioAccess B.V." },
- { 204, 68, "Unify Group Holding B.V.", "Unify Group Holding B.V." },
+ { 204, 68, "Roamware (Netherlands) B.V.", "Roamware (Netherlands) B.V." },
{ 204, 69, "KPN Mobile The Netherlands B.V.", "KPN Mobile The Netherlands B.V." },
- // Netherlands Antilles (Kingdom of the Netherlands) - AN
+ // Former Netherlands Antilles (Kingdom of the Netherlands) - AN
{ 362, 51, "Telcell", "Telcell" },
{ 362, 69, "Digicel", "Digicel" },
{ 362, 91, "UTS", "UTS" },
- { 362, 95, "MIO", "MIO" },
{ 362, 94, "Bayòs", "Bayòs" },
+ { 362, 95, "MIO", "MIO" },
// New Caledonia (France) - NC
@@ -1532,8 +1687,8 @@ struct plmn_list_entry plmn_list[] = {
{ 530, 3, "Woosh", "Woosh" },
{ 530, 4, "TelstraClear", "TelstraClear" },
{ 530, 5, "XT Mobile Network", "XT Mobile Network" },
- { 530, 24, "2degrees", "2degrees" },
{ 530, 6, "Skinny", "Skinny" },
+ { 530, 24, "2degrees", "2degrees" },
// Nicaragua - NI
@@ -1577,10 +1732,14 @@ struct plmn_list_entry plmn_list[] = {
{ 242, 5, "Network Norway", "Network Norway" },
{ 242, 6, "Ice", "Ice" },
{ 242, 7, "Ventelo", "Ventelo" },
- { 242, 8, "TDC ", "TDC " },
+ { 242, 8, "TDC", "TDC" },
{ 242, 9, "Com4", "Com4" },
{ 242, 11, "SystemNet", "SystemNet" },
+ { 242, 12, "Telenor", "Telenor" },
{ 242, 20, "Jernbaneverket AS", "Jernbaneverket AS" },
+ { 242, 21, "Jernbaneverket AS", "Jernbaneverket AS" },
+ { 242, 23, "Lyca", "Lyca" },
+ { 242, 24, "Mobile Norway AS", "Mobile Norway AS" },
// Oman - OM
@@ -1592,15 +1751,16 @@ struct plmn_list_entry plmn_list[] = {
{ 410, 1, "Mobilink", "Mobilink" },
{ 410, 3, "Ufone", "Ufone" },
{ 410, 4, "Zong", "Zong" },
+ { 410, 5, "SCO Mobile", "SCO Mobile" },
{ 410, 6, "Telenor", "Telenor" },
- { 410, 7, "Warid", "Warid" },
+ { 410, 7, "Warid Pakistan", "Warid Pakistan" },
// Palau - PW
{ 552, 1, "PNCC", "PNCC" },
{ 552, 80, "Palau Mobile", "Palau Mobile" },
- // State of Palestine - PS
+ // Palestine, State of - PS
{ 425, 5, "Jawwal", "Jawwal" },
{ 425, 6, "Wataniya", "Wataniya" },
@@ -1609,12 +1769,12 @@ struct plmn_list_entry plmn_list[] = {
{ 714, 1, "Cable & Wireless", "Cable & Wireless" },
{ 714, 2, "movistar", "movistar" },
- { 714, 4, "Digicel", "Digicel" },
{ 714, 3, "Claro", "Claro" },
+ { 714, 4, "Digicel", "Digicel" },
// Papua New Guinea - PG
- { 537, 1, "BeMobile", "BeMobile" },
+ { 537, 1, "bmobile", "bmobile" },
{ 537, 3, "Digicel", "Digicel" },
// Paraguay - PY
@@ -1629,7 +1789,7 @@ struct plmn_list_entry plmn_list[] = {
{ 716, 6, "Movistar", "Movistar" },
{ 716, 7, "NEXTEL", "NEXTEL" },
- { 716, 10, "Claro(TIM)", "Claro(TIM)" },
+ { 716, 10, "Claro (TIM)", "Claro (TIM)" },
{ 716, 15, "Viettel Mobile", "Viettel Mobile" },
{ 716, 17, "NEXTEL", "NEXTEL" },
@@ -1641,6 +1801,7 @@ struct plmn_list_entry plmn_list[] = {
{ 515, 5, "Sun", "Sun" },
{ 515, 11, "PLDT via ACeS Philippines", "PLDT via ACeS Philippines" },
{ 515, 18, "Cure", "Cure" },
+ { 515, 24, "ABS-CBN", "ABS-CBN" },
{ 515, 88, "Nextel", "Nextel" },
// Pitcairn Islands (United Kingdom) - PN
@@ -1665,6 +1826,7 @@ struct plmn_list_entry plmn_list[] = {
{ 260, 15, "CenterNet", "CenterNet" },
{ 260, 16, "Mobyland", "Mobyland" },
{ 260, 17, "Aero2", "Aero2" },
+ { 260, 32, "Voxbone", "Voxbone" },
{ 260, 34, "T-Mobile Polska S.A.", "T-Mobile Polska S.A." },
{ 260, 98, "P4 Sp. z o.o.", "P4 Sp. z o.o." },
@@ -1672,24 +1834,26 @@ struct plmn_list_entry plmn_list[] = {
{ 268, 1, "Vodafone", "Vodafone" },
{ 268, 3, "Optimus", "Optimus" },
- { 268, 7, "Vectonemobile - Delightmobile", "Vectonemobile - Delightmobile" },
{ 268, 4, "LycaMobile", "LycaMobile" },
{ 268, 6, "TMN", "TMN" },
+ { 268, 7, "Vectonemobile - Delightmobile", "Vectonemobile - Delightmobile" },
{ 268, 21, "Zapp", "Zapp" },
// Puerto Rico - PR
- { 330, 110, "Claro", "Claro" },
- { 330, 120, "Open Mobile", "Open Mobile" },
+ { 330, 110, "Claro Puerto Rico", "Claro Puerto Rico" },
+ { 330, 120, "tmobile", "tmobile" },
// Qatar - QA
{ 427, 1, "ooredoo", "ooredoo" },
{ 427, 2, "Vodafone", "Vodafone" },
{ 427, 5, "Ministry of Interior", "Ministry of Interior" },
+ { 427, 6, "Ministry of Interior", "Ministry of Interior" },
// Réunion (France) - RE
+ { 647, 1, "BJT Partners", "BJT Partners" },
{ 647, 2, "Outremer", "Outremer" },
{ 647, 10, "SFR Reunion", "SFR Reunion" },
@@ -1702,6 +1866,7 @@ struct plmn_list_entry plmn_list[] = {
{ 226, 5, "Digi.Mobil", "Digi.Mobil" },
{ 226, 6, "Cosmote/Zapp", "Cosmote/Zapp" },
{ 226, 10, "Orange", "Orange" },
+ { 226, 15, "Idilis", "Idilis" },
// Russian Federation - RU
@@ -1718,9 +1883,11 @@ struct plmn_list_entry plmn_list[] = {
{ 250, 12, "Baykalwestcom", "Baykalwestcom" },
{ 250, 12, "Akos", "Akos" },
{ 250, 13, "KUGSM", "KUGSM" },
+ { 250, 14, "MegaFon", "MegaFon" },
{ 250, 15, "SMARTS", "SMARTS" },
{ 250, 16, "NTC", "NTC" },
{ 250, 17, "Utel", "Utel" },
+ { 250, 18, "Osnova Telecom", "Osnova Telecom" },
{ 250, 19, "INDIGO", "INDIGO" },
{ 250, 20, "Tele2", "Tele2" },
{ 250, 23, "Mobicom - Novosibirsk", "Mobicom - Novosibirsk" },
@@ -1741,6 +1908,7 @@ struct plmn_list_entry plmn_list[] = {
{ 635, 12, "Rwandatel", "Rwandatel" },
{ 635, 13, "Tigo", "Tigo" },
{ 635, 14, "Airtel", "Airtel" },
+ { 635, 17, "Olleh Rwanda Networks", "Olleh Rwanda Networks" },
// Saint Kitts and Nevis - KN
@@ -1750,7 +1918,7 @@ struct plmn_list_entry plmn_list[] = {
// Saint Lucia - LC
- { 358, 358, "| 358 || 050 ||Unknown", "| 358 || 050 ||Unknown" },
+ { 358, 50, "Digicel", "Digicel" },
{ 358, 110, "Cable & Wireless", "Cable & Wireless" },
// Saint Pierre and Miquelon (France) - PM
@@ -1789,6 +1957,7 @@ struct plmn_list_entry plmn_list[] = {
{ 608, 1, "Orange", "Orange" },
{ 608, 2, "Tigo", "Tigo" },
{ 608, 3, "Expresso", "Expresso" },
+ { 608, 4, "CSU-SA", "CSU-SA" },
// Serbia - RS
@@ -1806,10 +1975,10 @@ struct plmn_list_entry plmn_list[] = {
// Sierra Leone - SL
{ 619, 1, "Airtel", "Airtel" },
- { 619, 2, "Tigo", "Tigo" },
{ 619, 3, "Africell", "Africell" },
{ 619, 4, "Comium", "Comium" },
{ 619, 5, "Africell", "Africell" },
+ { 619, 6, "SierraTel", "SierraTel" },
{ 619, 25, "Mobitel", "Mobitel" },
// Singapore - SG
@@ -1825,16 +1994,18 @@ struct plmn_list_entry plmn_list[] = {
// Slovakia - SK
{ 231, 1, "Orange", "Orange" },
- { 231, 2, "T-Mobile", "T-Mobile" },
+ { 231, 2, "Telekom", "Telekom" },
{ 231, 3, "Unient Communications", "Unient Communications" },
{ 231, 4, "T-Mobile", "T-Mobile" },
- { 231, 6, "O2 ", "O2 " },
+ { 231, 6, "O2", "O2" },
{ 231, 99, "ŽSR", "ŽSR" },
// Slovenia - SI
+ { 293, 31, "Mobitel", "Mobitel" },
{ 293, 40, "Si.mobil", "Si.mobil" },
{ 293, 41, "Mobitel", "Mobitel" },
+ { 293, 51, "Mobitel", "Mobitel" },
{ 293, 64, "T-2", "T-2" },
{ 293, 70, "Tušmobil", "Tušmobil" },
@@ -1845,11 +2016,11 @@ struct plmn_list_entry plmn_list[] = {
// Somalia - SO
- { 637, 4, "SomaCyber", "SomaCyber" },
{ 637, 1, "Telesom", "Telesom" },
+ { 637, 4, "SomaCyber", "SomaCyber" },
{ 637, 4, "Somafone", "Somafone" },
{ 637, 10, "Nationlink", "Nationlink" },
- { 637, 25, "Hormuud", "Hormuud" },
+ { 637, 50, "Hormuud", "Hormuud" },
{ 637, 30, "Golis", "Golis" },
{ 637, 57, "Unittel", "Unittel" },
{ 637, 60, "Nationlink Telecom", "Nationlink Telecom" },
@@ -1865,12 +2036,15 @@ struct plmn_list_entry plmn_list[] = {
{ 655, 10, "MTN", "MTN" },
{ 655, 11, "South African Police Service Gauteng", "South African Police Service Gauteng" },
{ 655, 13, "Neotel", "Neotel" },
+ { 655, 14, "Neotel", "Neotel" },
{ 655, 19, "iBurst", "iBurst" },
{ 655, 21, "Cape Town Metropolitan Council", "Cape Town Metropolitan Council" },
{ 655, 30, "Bokamoso Consortium", "Bokamoso Consortium" },
{ 655, 31, "Karabo Telecoms (Pty) Ltd.", "Karabo Telecoms (Pty) Ltd." },
{ 655, 32, "Ilizwi Telecommunications", "Ilizwi Telecommunications" },
{ 655, 33, "Thinta Thinta Telecommunications", "Thinta Thinta Telecommunications" },
+ { 655, 50, "Ericsson South Africa (Pty) Ltd", "Ericsson South Africa (Pty) Ltd" },
+ { 655, 51, "Integrat (Pty) Ltd", "Integrat (Pty) Ltd" },
// South Sudan - SS
@@ -1900,7 +2074,12 @@ struct plmn_list_entry plmn_list[] = {
{ 214, 22, "DigiMobil", "DigiMobil" },
{ 214, 23, "Barablu", "Barablu" },
{ 214, 24, "Eroski", "Eroski" },
- { 214, 25, "LycaMobile", "LycaMobile" },
+ { 214, 25, "Lycamobile", "Lycamobile" },
+ { 214, 28, "Consorcio de Telecomunicaciones Avanzadas, S.A.", "Consorcio de Telecomunicaciones Avanzadas, S.A." },
+ { 214, 29, "NEO-SKY 2002, S.A.", "NEO-SKY 2002, S.A." },
+ { 214, 30, "Compatel Limited", "Compatel Limited" },
+ { 214, 31, "Red Digital De Telecomunicaciones de las Islas Baleares, S.L.", "Red Digital De Telecomunicaciones de las Islas Baleares, S.L." },
+ { 214, 32, "Tuenti", "Tuenti" },
// Sri Lanka - LK
@@ -1914,6 +2093,7 @@ struct plmn_list_entry plmn_list[] = {
{ 634, 1, "Zain SD", "Zain SD" },
{ 634, 2, "MTN", "MTN" },
+ { 634, 5, "Canar Telecom", "Canar Telecom" },
{ 634, 7, "Sudani One", "Sudani One" },
{ 634, 9, "Privet Network", "Privet Network" },
@@ -1931,7 +2111,7 @@ struct plmn_list_entry plmn_list[] = {
{ 240, 1, "Telia", "Telia" },
{ 240, 2, "3", "3" },
- { 240, 3, "Ice.net", "Ice.net" },
+ { 240, 3, "Net 1", "Net 1" },
{ 240, 4, "SWEDEN", "SWEDEN" },
{ 240, 5, "Sweden 3G", "Sweden 3G" },
{ 240, 6, "Telenor", "Telenor" },
@@ -1939,20 +2119,40 @@ struct plmn_list_entry plmn_list[] = {
{ 240, 8, "Telenor", "Telenor" },
{ 240, 9, "djuice", "djuice" },
{ 240, 10, "Spring Mobil", "Spring Mobil" },
- { 240, 11, "Lindholmen Science Park", "Lindholmen Science Park" },
- { 240, 12, "Lycamobile Sweden ", "Lycamobile Sweden " },
- { 240, 13, "Ventelo Sverige", "Ventelo Sverige" },
- { 240, 14, "TDC Mobil", "TDC Mobil" },
- { 240, 15, "Wireless Maingate Nordic", "Wireless Maingate Nordic" },
- { 240, 16, "42IT", "42IT" },
- { 240, 17, "Götalandsnätet", "Götalandsnätet" },
- { 240, 20, "Wireless Maingate Message Services", "Wireless Maingate Message Services" },
+ { 240, 11, "Lindholmen Science Park AB", "Lindholmen Science Park AB" },
+ { 240, 12, "Lycamobile", "Lycamobile" },
+ { 240, 13, "Alltele Företag Sverige AB", "Alltele Företag Sverige AB" },
+ { 240, 14, "TDC Sverige AB", "TDC Sverige AB" },
+ { 240, 15, "Wireless Maingate Nordic AB", "Wireless Maingate Nordic AB" },
+ { 240, 16, "42 Telecom AB", "42 Telecom AB" },
+ { 240, 17, "Götalandsnätet AB", "Götalandsnätet AB" },
+ { 240, 18, "Generic Mobile Systems Sweden AB", "Generic Mobile Systems Sweden AB" },
+ { 240, 19, "Vectone Mobile / Delight Mobile", "Vectone Mobile / Delight Mobile" },
+ { 240, 20, "Wireless Maingate Messaging Services AB", "Wireless Maingate Messaging Services AB" },
{ 240, 21, "MobiSir", "MobiSir" },
+ { 240, 22, "EuTel AB", "EuTel AB" },
+ { 240, 23, "Infobip Limited", "Infobip Limited" },
{ 240, 24, "Sweden 2G", "Sweden 2G" },
- { 240, 25, "DigiTelMobile", "DigiTelMobile" },
- { 240, 26, "Beepsend", "Beepsend" },
+ { 240, 25, "Digitel Mobile Srl", "Digitel Mobile Srl" },
+ { 240, 26, "Beepsend AB", "Beepsend AB" },
+ { 240, 27, "Fogg Mobile AB", "Fogg Mobile AB" },
+ { 240, 28, "CoolTEL Aps", "CoolTEL Aps" },
+ { 240, 29, "Mercury International Carrier Services", "Mercury International Carrier Services" },
+ { 240, 30, "NextGen Mobile Ltd.", "NextGen Mobile Ltd." },
+ { 240, 31, "Mobimax AB", "Mobimax AB" },
+ { 240, 32, "Compatel Limited", "Compatel Limited" },
{ 240, 33, "Mobile Arts AB", "Mobile Arts AB" },
- { 240, 41, "Shyam Telecom UK Ltd", "Shyam Telecom UK Ltd" },
+ { 240, 34, "Pro Net Telecommunications Services Ltd.", "Pro Net Telecommunications Services Ltd." },
+ { 240, 35, "42 Telecom LTD", "42 Telecom LTD" },
+ { 240, 36, "interactive digital media GmbH", "interactive digital media GmbH" },
+ { 240, 37, "CLX Networks AB", "CLX Networks AB" },
+ { 240, 38, "Voxbone", "Voxbone" },
+ { 240, 39, "iCentrex Sweden AB", "iCentrex Sweden AB" },
+ { 240, 40, "ReWiCom Scandinavia AB", "ReWiCom Scandinavia AB" },
+ { 240, 41, "Shyam Telecom UK Ltd.", "Shyam Telecom UK Ltd." },
+ { 240, 42, "Telenor Connexion AB", "Telenor Connexion AB" },
+ { 240, 43, "MobiWeb Ltd.", "MobiWeb Ltd." },
+ { 240, 44, "Limitless Mobile AB", "Limitless Mobile AB" },
// Switzerland - CH
@@ -1970,6 +2170,7 @@ struct plmn_list_entry plmn_list[] = {
{ 228, 52, "Barablu", "Barablu" },
{ 228, 53, "UPC", "UPC" },
{ 228, 54, "Lyca Mobile", "Lyca Mobile" },
+ { 228, 99, "Swisscom", "Swisscom" },
// Syria - SY
@@ -1980,9 +2181,9 @@ struct plmn_list_entry plmn_list[] = {
{ 466, 1, "FarEasTone", "FarEasTone" },
{ 466, 5, "APTG", "APTG" },
- { 466, 6, "Tuntex", "Tuntex" },
+ { 466, 6, "FarEasTone", "FarEasTone" },
{ 466, 11, "Chunghwa LDM", "Chunghwa LDM" },
- { 466, 88, "KG Telecom", "KG Telecom" },
+ { 466, 88, "FarEasTone", "FarEasTone" },
{ 466, 89, "VIBO", "VIBO" },
{ 466, 92, "Chungwa", "Chungwa" },
{ 466, 93, "MobiTai", "MobiTai" },
@@ -1993,9 +2194,9 @@ struct plmn_list_entry plmn_list[] = {
{ 436, 1, "Tcell", "Tcell" },
{ 436, 2, "Tcell", "Tcell" },
- { 436, 3, "Megafon", "Megafon" },
+ { 436, 3, "Megafon Tajikistan", "Megafon Tajikistan" },
{ 436, 4, "Babilon-M", "Babilon-M" },
- { 436, 5, "Tacom", "Tacom" },
+ { 436, 5, "Beeline", "Beeline" },
{ 436, 12, "Tcell", "Tcell" },
// Tanzania - TZ
@@ -2012,17 +2213,18 @@ struct plmn_list_entry plmn_list[] = {
// Thailand - TH
- { 520, 1, "AIS ", "AIS " },
+ { 520, 1, "AIS", "AIS" },
{ 520, 2, "CAT CDMA", "CAT CDMA" },
{ 520, 3, "AIS 3G", "AIS 3G" },
- { 520, 4, "True Move H 4G LTE", "True Move H 4G LTE" },
- { 520, 5, "dtac 3G", "dtac 3G" },
+ { 520, 4, "truemove H 4G LTE", "truemove H 4G LTE" },
+ { 520, 5, "dtac TriNet", "dtac TriNet" },
{ 520, 10, "?", "?" },
{ 520, 15, "TOT 3G", "TOT 3G" },
{ 520, 18, "dtac", "dtac" },
{ 520, 23, "AIS GSM 1800", "AIS GSM 1800" },
- { 520, 99, "True Move", "True Move" },
{ 520, 25, "WE PCT", "WE PCT" },
+ { 520, 47, "Telephone Organization of Thailand (TOT)", "Telephone Organization of Thailand (TOT)" },
+ { 520, 99, "truemove", "truemove" },
// Togo - TG
@@ -2055,7 +2257,7 @@ struct plmn_list_entry plmn_list[] = {
// Turkmenistan - TM
- { 438, 1, "MTS (BARASH Communication) ", "MTS (BARASH Communication) " },
+ { 438, 1, "MTS (BARASH Communication)", "MTS (BARASH Communication)" },
{ 438, 2, "TM-Cell", "TM-Cell" },
// Turks and Caicos Islands - TC
@@ -2072,9 +2274,12 @@ struct plmn_list_entry plmn_list[] = {
{ 641, 1, "Airtel", "Airtel" },
{ 641, 10, "MTN", "MTN" },
- { 641, 11, "UTL", "UTL" },
+ { 641, 11, "UTL ( Telecom Limited)", "UTL ( Telecom Limited)" },
{ 641, 14, "Orange", "Orange" },
{ 641, 22, "Warid Telecom", "Warid Telecom" },
+ { 641, 33, "Smile", "Smile" },
+ { 641, 44, "K2", "K2" },
+ { 641, 66, "i-Tel", "i-Tel" },
// Ukraine - UA
@@ -2111,31 +2316,41 @@ struct plmn_list_entry plmn_list[] = {
{ 234, 13, "Railtrack", "Railtrack" },
{ 234, 14, "Hay Systems Ltd", "Hay Systems Ltd" },
{ 234, 15, "Vodafone UK", "Vodafone UK" },
- { 234, 16, "Talk Talk (Opal Tel Ltd)", "Talk Talk (Opal Tel Ltd)" },
+ { 234, 16, "Talk Talk", "Talk Talk" },
{ 234, 17, "FleXtel Limited", "FleXtel Limited" },
{ 234, 18, "Cloud9", "Cloud9" },
{ 234, 19, "Private Mobile Networks PMN", "Private Mobile Networks PMN" },
{ 234, 20, "3", "3" },
{ 234, 22, "RoutoMessaging", "RoutoMessaging" },
+ { 234, 23, "Icron Network Limited", "Icron Network Limited" },
{ 234, 24, "Greenfone", "Greenfone" },
{ 234, 25, "Truphone", "Truphone" },
- { 234, 27, "United Kingdom of Great Britain and Northern Ireland", "United Kingdom of Great Britain and Northern Ireland" },
- { 234, 30, "T-Mobile (UK)", "T-Mobile (UK)" },
+ { 234, 26, "Lycamobile", "Lycamobile" },
+ { 234, 27, "Teleena UK Limited", "Teleena UK Limited" },
+ { 234, 28, "Marathon Telecom Ltd", "Marathon Telecom Ltd" },
+ { 234, 29, "aql", "aql" },
+ { 234, 30, "T-Mobile UK", "T-Mobile UK" },
{ 234, 31, "Virgin Mobile UK", "Virgin Mobile UK" },
{ 234, 32, "Virgin Mobile UK", "Virgin Mobile UK" },
{ 234, 33, "Orange (UK)", "Orange (UK)" },
{ 234, 34, "Orange (UK)", "Orange (UK)" },
{ 234, 35, "JSC Ingenium (UK) Limited", "JSC Ingenium (UK) Limited" },
- { 234, 36, "Cable and Wireless Isle of Man Limited", "Cable and Wireless Isle of Man Limited" },
+ { 234, 36, "Sure (Isle of Man) Limited", "Sure (Isle of Man) Limited" },
{ 234, 37, "Synectiv Ltd", "Synectiv Ltd" },
+ { 234, 38, "Virgin Mobile UK", "Virgin Mobile UK" },
+ { 234, 39, "SSE Energy Supply Limited", "SSE Energy Supply Limited" },
{ 234, 50, "JT", "JT" },
- { 234, 51, "UK Broadband Limited", "UK Broadband Limited" },
+ { 234, 51, "UK Broadband", "UK Broadband" },
+ { 234, 52, "Shyam Telecom UK Ltd", "Shyam Telecom UK Ltd" },
+ { 234, 53, "Limitless Mobile Ltd", "Limitless Mobile Ltd" },
{ 234, 55, "Cable & Wireless Guernsey / Sure Mobile (Jersey)", "Cable & Wireless Guernsey / Sure Mobile (Jersey)" },
{ 234, 58, "Manx Telecom", "Manx Telecom" },
{ 234, 76, "BT", "BT" },
{ 234, 78, "Airwave", "Airwave" },
+ { 234, 86, "EE", "EE" },
{ 235, 1, "EE", "EE" },
{ 235, 2, "EE", "EE" },
+ { 235, 3, "UK Broadband", "UK Broadband" },
{ 235, 77, "BT", "BT" },
{ 235, 91, "Vodafone United Kingdom", "Vodafone United Kingdom" },
{ 235, 92, "Cable & Wireless UK", "Cable & Wireless UK" },
@@ -2144,13 +2359,9 @@ struct plmn_list_entry plmn_list[] = {
// United States of America - US
- { 310, 53, "Virgin Mobile US", "Virgin Mobile US" },
- { 310, 54, "Alltel US", "Alltel US" },
- { 310, 66, "U.S. Cellular", "U.S. Cellular" },
{ 310, 4, "Verizon", "Verizon" },
{ 310, 5, "Verizon", "Verizon" },
{ 310, 10, "MCI", "MCI" },
- { 310, 12, "Verizon", "Verizon" },
{ 310, 13, "MobileTel", "MobileTel" },
{ 310, 14, "Testing", "Testing" },
{ 310, 16, "Cricket Communications", "Cricket Communications" },
@@ -2161,11 +2372,14 @@ struct plmn_list_entry plmn_list[] = {
{ 310, 34, "Airpeak", "Airpeak" },
{ 310, 40, "Concho", "Concho" },
{ 310, 46, "SIMMETRY", "SIMMETRY" },
+ { 310, 53, "Virgin Mobile US", "Virgin Mobile US" },
+ { 310, 54, "Alltel US", "Alltel US" },
{ 310, 60, "Consolidated Telcom", "Consolidated Telcom" },
+ { 310, 66, "U.S. Cellular", "U.S. Cellular" },
{ 310, 70, "Highland Cellular", "Highland Cellular" },
{ 310, 80, "Corr", "Corr" },
{ 310, 90, "Cricket Communications", "Cricket Communications" },
- { 310, 100, "Plateau Wireless ", "Plateau Wireless " },
+ { 310, 100, "Plateau Wireless", "Plateau Wireless" },
{ 310, 110, "PTI Pacifica", "PTI Pacifica" },
{ 310, 120, "Sprint", "Sprint" },
{ 310, 150, "AT&T", "AT&T" },
@@ -2243,6 +2457,7 @@ struct plmn_list_entry plmn_list[] = {
{ 310, 980, "AT&T", "AT&T" },
{ 310, 990, "AT&T", "AT&T" },
{ 311, 10, "Chariton Valley", "Chariton Valley" },
+ { 311, 12, "Verizon", "Verizon" },
{ 311, 20, "Missouri RSA 5 Partnership", "Missouri RSA 5 Partnership" },
{ 311, 30, "Indigo Wireless", "Indigo Wireless" },
{ 311, 40, "Commnet Wireless", "Commnet Wireless" },
@@ -2267,9 +2482,13 @@ struct plmn_list_entry plmn_list[] = {
{ 311, 330, "Bug Tussel Wireless", "Bug Tussel Wireless" },
{ 311, 480, "Verizon", "Verizon" },
{ 311, 481, "Verizon", "Verizon" },
- { 311, 660, "metroPCS ", "metroPCS " },
+ { 311, 490, "Sprint Corporation", "Sprint Corporation" },
+ { 311, 580, "U.S. Cellular", "U.S. Cellular" },
+ { 311, 660, "metroPCS", "metroPCS" },
+ { 311, 870, "Boost", "Boost" },
{ 311, 960, "Lycamobile", "Lycamobile" },
{ 311, 970, "Big River Broadband", "Big River Broadband" },
+ { 312, 590, "NMU", "NMU" },
{ 313, 100, "700&nbsp;MHz Public Safety Broadband", "700&nbsp;MHz Public Safety Broadband" },
{ 313, 101, "700&nbsp;MHz Public Safety Broadband", "700&nbsp;MHz Public Safety Broadband" },
{ 316, 10, "Nextel", "Nextel" },
@@ -2289,18 +2508,20 @@ struct plmn_list_entry plmn_list[] = {
{ 434, 5, "Ucell", "Ucell" },
{ 434, 6, "Perfectum Mobile", "Perfectum Mobile" },
{ 434, 7, "MTS", "MTS" },
+ { 434, 3, "UzMobile", "UzMobile" },
// Vanuatu - VU
{ 541, 1, "SMILE", "SMILE" },
{ 541, 5, "Digicel", "Digicel" },
+ { 541, 7, "WanTok", "WanTok" },
// Vatican - VA
// Venezuela - VE
- { 734, 1, "Digitel ", "Digitel " },
+ { 734, 1, "Digitel", "Digitel" },
{ 734, 2, "Digitel GSM", "Digitel GSM" },
{ 734, 3, "Digitel", "Digitel" },
{ 734, 4, "movistar", "movistar" },
@@ -2308,14 +2529,14 @@ struct plmn_list_entry plmn_list[] = {
// Vietnam - VN
- { 452, 1, "MobiFone ", "MobiFone " },
+ { 452, 1, "MobiFone", "MobiFone" },
{ 452, 2, "Vinaphone", "Vinaphone" },
{ 452, 3, "S-Fone", "S-Fone" },
{ 452, 4, "Viettel Mobile", "Viettel Mobile" },
{ 452, 5, "Vietnamobile (HT Mobile )", "Vietnamobile (HT Mobile )" },
{ 452, 6, "EVNTelecom", "EVNTelecom" },
- { 452, 8, "3G EVNTelecom", "3G EVNTelecom" },
{ 452, 7, "G-Mobile", "G-Mobile" },
+ { 452, 8, "3G EVNTelecom", "3G EVNTelecom" },
// Yemen - YE
@@ -2371,7 +2592,11 @@ struct plmn_list_entry plmn_list[] = {
{ 901, 34, "tyntec GmbH", "tyntec GmbH" },
{ 901, 35, "Globecomm Network Services", "Globecomm Network Services" },
{ 901, 36, "Azerfon", "Azerfon" },
+ { 901, 39, "MTX Connect Ltd", "MTX Connect Ltd" },
{ 901, 88, "UN Office for the Coordination of Humanitarian Affairs (OCHA)", "UN Office for the Coordination of Humanitarian Affairs (OCHA)" },
};
+unsigned int plmn_list_count = sizeof(plmn_list) /
+ sizeof(struct plmn_list_entry);
+
#endif
diff --git a/include/plmn_list.sh b/include/plmn_list.sh
index 26e9616..0a17068 100755
--- a/include/plmn_list.sh
+++ b/include/plmn_list.sh
@@ -1,22 +1,26 @@
#!/bin/sh
#
-# Copyright 2012 Paul Kocialkowski, GPLv3+
+# Copyright 2012-2014 Paul Kocialkowski, GPLv3+
#
# This script is a dirty hack, keep in mind that is was written in a hurry
-# and doesn't reflect our code cleanness standards.
+# and doesn't reflect our code cleanness standards.
# Any (working) replacement written in a cleaner way, such as a perl script
# would be greatly appreciated.
-echo "/**"
-echo " * This list was generated from http://en.wikipedia.org/wiki/Mobile_Network_Code"
-echo " * "
+echo "/*"
+echo " * This list was generated from:"
+echo " * http://en.wikipedia.org/wiki/Mobile_country_code"
+echo " *"
echo " * Date: "$( date "+%x %X" )
-echo " * Copyright: Wikipedia Contributors, Creative Commons Attribution-ShareAlike License"
+echo " * Copyright: Wikipedia Contributors, Creative Commons"
+echo " * Attribution-ShareAlike License"
echo " */"
echo ""
echo "#ifndef _PLMN_LIST_H_"
echo "#define _PLMN_LIST_H_"
echo ""
+echo "#include <stdlib.h>"
+echo ""
echo "struct plmn_list_entry {"
echo " unsigned int mcc;"
echo " unsigned int mnc;"
@@ -26,7 +30,7 @@ echo "};"
echo ""
echo "struct plmn_list_entry plmn_list[] = {"
-wget "http://en.wikipedia.org/w/index.php?title=Special:Export&pages=Mobile_country_code&action=submit" --quiet -O - | tr -d '\n' | sed -e "s|.*<text[^>]*>\(.*\)</text>.*|\1|g" -e "s/|-/\n|-\n/g" | sed -e "s/\(}===.*\)/\n\1/g" -e "s/===={.*/===={\n/g" -e "s/\&amp;/\&/g" -e "s/\&lt;[^\&]*\&gt;//g" -e "s/&quot;//g" -e "s#\[http[^]]*\]##g" -e "s#\[\[\([^]|]*\)|\([^]]*\)\]\]#\2#g" -e "s#\[\[\([^]]*\)\]\]#\1#g" -e "s#\[\([^] ]*\) \([^]]*\)\]#\2#g" | tail -n +2 | sed "s|.*=== \(.*\) ===.*|// \1|g" | grep -v "|-" | while read line
+wget "http://en.wikipedia.org/w/index.php?title=Special:Export&pages=Mobile_country_code&action=submit" --quiet -O - | tr -d '\n' | sed -e "s|.*<text[^>]*>\(.*\)</text>.*|\1|g" -e "s/|-/\n|-\n/g" | sed -e "s/\(}===.*\)/\n\1/g" -e "s/===={.*/===={\n/g" -e "s/\&amp;/\&/g" -e "s/\&lt;[^\&]*\&gt;//g" -e "s/&quot;//g" -e "s#\[http[^]]*\]##g" -e "s#\[\[\([^]|]*\)|\([^]]*\)\]\]#\2#g" -e "s#\[\[\([^]]*\)\]\]#\1#g" -e "s#\[\([^] ]*\) \([^]]*\)\]#\2#g" -e "s#{{[^}]*}}##g" | tail -n +2 | sed "s|.*==== *\([^=]*\) *====.*|// \1|g" | grep -v "|-" | while read line
do
if [ "$line" = "" ]
then
@@ -37,7 +41,7 @@ do
if [ ! "$test" = "" ]
then
- echo "\n\t$line\n" | sed -e "s#[^|]*|\(.*\)#// \1#g" -e "s/^ //g" -e "s/ $//g"
+ echo "\n\t$line\n" | sed -e "s#[^|]*|\(.*\)#// \1#g" -e "s/^ //g" -e "s/ $//g" -e "s/ / /g"
continue
fi
@@ -48,10 +52,10 @@ do
continue
fi
- mcc=$( echo "$line" | sed -e "s#[^|]*|[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\).*#\1#g" -e "s/^ //g" -e "s/ $//g" -e "s/[^1-9]*\([0-9]*\).*/\1/g")
- mnc=$( echo "$line" | sed -e "s#[^|]*|[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\).*#\2#g" -e "s/^ //g" -e "s/ $//g" -e "s/[^1-9]*\([0-9]*\).*/\1/g")
- brand=$( echo "$line" | sed -e "s#[^|]*|[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\).*#\3#g" -e "s/^ //g" -e "s/ $//g" )
- operator=$( echo "$line" | sed -e "s#[^|]*|[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\).*#\4#g" -e "s/^ //g" -e "s/ $//g" )
+ mcc=$( echo "$line" | sed -e "s#[^|]*|[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\).*#\1#g" -e "s/^[ |\t]*//g" -e "s/ [ |\t]*$//g" -e "s/[^1-9]*\([0-9]*\).*/\1/g")
+ mnc=$( echo "$line" | sed -e "s#[^|]*|[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\).*#\2#g" -e "s/^[ |\t]*//g" -e "s/ [ |\t]*$//g" -e "s/[^1-9]*\([0-9]*\).*/\1/g")
+ brand=$( echo "$line" | sed -e "s#[^|]*|[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\).*#\3#g" -e "s/^[ |\t]*//g" -e "s/ [ |\t]*$//g" )
+ operator=$( echo "$line" | sed -e "s#[^|]*|[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\)[ ]*||[ ]*\([^|]*\).*#\4#g" -e "s/^[ |\t]*//g" -e "s/ [ |\t]*$//g" )
if [ "$mcc" = "" ] || [ "$mcc" = "?" ]
then
@@ -78,4 +82,7 @@ done
echo "};"
echo ""
+echo "unsigned int plmn_list_count = sizeof(plmn_list) /"
+echo "\tsizeof(struct plmn_list_entry);"
+echo ""
echo "#endif"
diff --git a/include/ril_oem.h b/include/ril_oem.h
new file mode 100644
index 0000000..c38db00
--- /dev/null
+++ b/include/ril_oem.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of Samsung-RIL.
+ *
+ * Copyright (C) 2013-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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Samsung-RIL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _RIL_OEM_H_
+#define _RIL_OEM_H_
+
+#include <stdlib.h>
+
+#define RIL_OEM_HOOK_TAG_SVC 1
+
+#define RIL_OEM_COMMAND_SVC_ENTER_MODE 1
+#define RIL_OEM_COMMAND_SVC_END_MODE 2
+#define RIL_OEM_COMMAND_SVC_KEY 3
+
+typedef struct {
+ unsigned char tag;
+ unsigned char command;
+ unsigned short length;
+} RIL_OEMHookHeader;
+
+typedef struct {
+ unsigned char mode;
+ unsigned char type;
+ unsigned char query;
+} RIL_OEMHookSvcEnterMode;
+
+typedef struct {
+ unsigned char mode;
+} RIL_OEMHookSvcEndMode;
+
+typedef struct {
+ unsigned char key;
+ unsigned char query;
+} RIL_OEMHookSvcKey;
+
+#endif
diff --git a/include/samsung-ril-socket.h b/include/samsung-ril-socket.h
index d231e62..9e919d1 100644
--- a/include/samsung-ril-socket.h
+++ b/include/samsung-ril-socket.h
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * Copyright (C) 2011-2013 Paul Kocialkowski <contact@oaulk.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
@@ -17,40 +17,36 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
-/* Samsung RIL Socket protocol defines */
-
#ifndef _SAMSUNG_RIL_SOCKET_H_
#define _SAMSUNG_RIL_SOCKET_H_
-#define SRS_COMMAND(f) ((f->group << 8) | f->index)
-#define SRS_GROUP(m) (m >> 8)
-#define SRS_INDEX(m) (m & 0xff)
+#include <stdlib.h>
-#define SRS_SOCKET_NAME "samsung-ril-socket"
-#define SRS_DATA_MAX_SIZE 0x1000
+/*
+ * Groups
+ */
-#define SRS_CONTROL 0x01
-#define SRS_CONTROL_PING 0x0101
+#define SRS_GROUP_CONTROL 0x01
+#define SRS_GROUP_SND 0x02
-#define SRS_SND 0x02
-#define SRS_SND_SET_CALL_VOLUME 0x0201
-#define SRS_SND_SET_CALL_AUDIO_PATH 0x0202
-#define SRS_SND_SET_CALL_CLOCK_SYNC 0x0203
+/*
+ * Commands
+ */
-#define SRS_CONTROL_CAFFE 0xCAFFE
+#define SRS_CONTROL_PING 0x0101
-struct srs_header {
- unsigned int length;
- unsigned char group;
- unsigned char index;
-} __attribute__((__packed__));
+#define SRS_SND_SET_CALL_VOLUME 0x0201
+#define SRS_SND_SET_CALL_AUDIO_PATH 0x0202
+#define SRS_SND_SET_CALL_CLOCK_SYNC 0x0203
-struct srs_message {
- unsigned short command;
- int length;
- void *data;
-};
+/*
+ * Values
+ */
+
+#define SRS_SOCKET_NAME "samsung-ril-socket"
+#define SRS_BUFFER_LENGTH 0x1000
+#define SRS_CONTROL_CAFFE 0xCAFFE
enum srs_snd_type {
SRS_SND_TYPE_VOICE,
@@ -73,21 +69,45 @@ enum srs_snd_clock {
SND_CLOCK_START
};
-struct srs_snd_call_volume {
+/*
+ * Macros
+ */
+
+#define SRS_COMMAND(group, index) ((group << 8) | index)
+#define SRS_GROUP(command) (command >> 8)
+#define SRS_INDEX(command) (command & 0xff)
+
+/*
+ * Structures
+ */
+
+struct srs_message {
+ unsigned short command;
+ void *data;
+ size_t size;
+};
+
+struct srs_header {
+ unsigned int length;
+ unsigned char group;
+ unsigned char index;
+} __attribute__((__packed__));
+
+struct srs_control_ping_data {
+ unsigned int caffe;
+} __attribute__((__packed__));
+
+struct srs_snd_call_volume_data {
enum srs_snd_type type;
int volume;
} __attribute__((__packed__));
-struct srs_snd_call_audio_path {
+struct srs_snd_call_audio_path_data {
enum srs_snd_path path;
} __attribute__((__packed__));
-struct srs_snd_call_clock_sync {
+struct srs_snd_call_clock_sync_data {
unsigned char sync;
} __attribute__((__packed__));
-struct srs_control_ping {
- int caffe;
-} __attribute__((__packed__));
-
#endif
diff --git a/include/sim.h b/include/sim.h
index dc16808..d3ec95c 100644
--- a/include/sim.h
+++ b/include/sim.h
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2013-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
@@ -20,22 +20,36 @@
#ifndef _SIM_H_
#define _SIM_H_
-// Values from TS 11.11
-#define SIM_COMMAND_READ_BINARY 0xB0
-#define SIM_COMMAND_UPDATE_BINARY 0xD6
-#define SIM_COMMAND_READ_RECORD 0xB2
-#define SIM_COMMAND_UPDATE_RECORD 0xDC
-#define SIM_COMMAND_SEEK 0xA2
-#define SIM_COMMAND_GET_RESPONSE 0xC0
+#include <stdlib.h>
-#define SIM_FILE_STRUCTURE_TRANSPARENT 0x00
-#define SIM_FILE_STRUCTURE_LINEAR_FIXED 0x01
-#define SIM_FILE_STRUCTURE_CYCLIC 0x03
+#define SIM_COMMAND_READ_BINARY 0xB0
+#define SIM_COMMAND_UPDATE_BINARY 0xD6
+#define SIM_COMMAND_READ_RECORD 0xB2
+#define SIM_COMMAND_UPDATE_RECORD 0xDC
+#define SIM_COMMAND_SEEK 0xA2
+#define SIM_COMMAND_GET_RESPONSE 0xC0
-#define SIM_FILE_TYPE_RFU 0x00
-#define SIM_FILE_TYPE_MF 0x01
-#define SIM_FILE_TYPE_DF 0x02
-#define SIM_FILE_TYPE_EF 0x04
+#define SIM_FILE_STRUCTURE_TRANSPARENT 0x00
+#define SIM_FILE_STRUCTURE_LINEAR_FIXED 0x01
+#define SIM_FILE_STRUCTURE_CYCLIC 0x03
+
+#define SIM_FILE_TYPE_RFU 0x00
+#define SIM_FILE_TYPE_MF 0x01
+#define SIM_FILE_TYPE_DF 0x02
+#define SIM_FILE_TYPE_EF 0x04
+
+struct sim_file_response {
+ unsigned char rfu12[2];
+ unsigned char file_size[2];
+ unsigned char file_id[2];
+ unsigned char file_type;
+ unsigned char rfu3;
+ unsigned char access_condition[3];
+ unsigned char file_status;
+ unsigned char file_length;
+ unsigned char file_structure;
+ unsigned char record_length;
+} __attribute__((__packed__));
struct sim_file_id {
unsigned short file_id;
@@ -85,19 +99,7 @@ struct sim_file_id sim_file_ids[] = {
{ 0x7F20, SIM_FILE_TYPE_DF },
};
-int sim_file_ids_count = sizeof(sim_file_ids) / sizeof(sim_file_ids[0]);
-
-struct sim_file_response {
- unsigned char rfu12[2];
- unsigned char file_size[2];
- unsigned char file_id[2];
- unsigned char file_type;
- unsigned char rfu3;
- unsigned char access_condition[3];
- unsigned char file_status;
- unsigned char file_length;
- unsigned char file_structure;
- unsigned char record_length;
-} __attribute__((__packed__));
+unsigned int sim_file_ids_count = sizeof(sim_file_ids) /
+ sizeof(struct sim_file_id);
#endif
diff --git a/ipc.c b/ipc.c
index a86a27f..d8601fa 100644
--- a/ipc.c
+++ b/ipc.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,364 +18,1092 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
+#include <sys/eventfd.h>
+
#define LOG_TAG "RIL-IPC"
#include <utils/Log.h>
+#include <hardware_legacy/power.h>
-#include "samsung-ril.h"
+#include <samsung-ril.h>
+#include <utils.h>
/*
- * IPC shared
+ * Utils
*/
void ipc_log_handler(void *log_data, const char *message)
{
- RIL_LOGD("ipc: %s", message);
+ RIL_LOGD("%s", message);
}
/*
* IPC FMT
*/
-void ipc_fmt_send(const unsigned short command, const char type, unsigned char *data, const int length, unsigned char mseq)
-{
- struct ipc_client *ipc_client;
-
- if (ril_data.ipc_fmt_client == NULL || ril_data.ipc_fmt_client->data == NULL)
- return;
-
- ipc_client = (struct ipc_client *) ril_data.ipc_fmt_client->data;
-
- RIL_CLIENT_LOCK(ril_data.ipc_fmt_client);
- ipc_client_send(ipc_client, command, type, data, length, mseq);
- RIL_CLIENT_UNLOCK(ril_data.ipc_fmt_client);
-}
-
-int ipc_fmt_read_loop(struct ril_client *client)
+int ipc_fmt_send(unsigned char mseq, unsigned short command, unsigned char type,
+ const void *data, size_t size)
{
- struct ipc_client *ipc_client;
- struct ipc_message_info info;
-
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
int rc;
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
if (client == NULL || client->data == NULL)
- return -EINVAL;
+ return -1;
- ipc_client = (struct ipc_client *) client->data;
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+ if (ipc_fmt_data->ipc_client == NULL || ipc_fmt_data->event_fd < 0)
+ return -1;
- while (1) {
- rc = ipc_client_poll(ipc_client, NULL);
- if (rc < 0) {
- RIL_LOGE("IPC FMT client poll failed, aborting");
- goto error;
- }
-
- memset(&info, 0, sizeof(info));
-
- RIL_CLIENT_LOCK(client);
- if (ipc_client_recv(ipc_client, &info) < 0) {
- RIL_CLIENT_UNLOCK(client);
- RIL_LOGE("IPC FMT recv failed, aborting");
- goto error;
- }
- RIL_CLIENT_UNLOCK(client);
+ if (!client->available) {
+ RIL_LOGE("%s client is not available", client->name);
+ return -1;
+ }
- ipc_fmt_dispatch(&info);
+ RIL_CLIENT_LOCK(client);
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_VERSION_STRING);
- ipc_client_response_free(ipc_client, &info);
+ rc = ipc_client_send(ipc_fmt_data->ipc_client, mseq, command, type, data, size);
+ if (rc < 0) {
+ RIL_LOGE("Sending to %s client failed", client->name);
+ goto error;
}
rc = 0;
goto complete;
error:
- ril_radio_state_update(RADIO_STATE_UNAVAILABLE);
- ril_sms_send(RIL_SMS_NUMBER, "Samsung-RIL: The modem just crashed, please reboot your device if you can't get service back.");
+ eventfd_send(ipc_fmt_data->event_fd, IPC_CLIENT_IO_ERROR);
rc = -1;
complete:
+ release_wake_lock(RIL_VERSION_STRING);
+ RIL_CLIENT_UNLOCK(client);
+
return rc;
}
-int ipc_fmt_create(struct ril_client *client)
+unsigned char ipc_fmt_seq(void)
{
- struct ipc_client *ipc_client;
+ struct ril_client *client;
+ struct ipc_fmt_data *data;
- int rc;
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ return 0xff;
+
+ data = (struct ipc_fmt_data *) client->data;
+ data->seq++;
+
+ if (data->seq % 0xff == 0x00)
+ data->seq = 0x01;
+
+ return data->seq;
+}
+
+unsigned char ipc_fmt_request_seq(RIL_Token token)
+{
+ struct ril_client *client;
+ struct ipc_fmt_request *request;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
if (client == NULL)
- return -EINVAL;
+ return 0xff;
- RIL_LOGD("Creating new FMT client");
+ request = ipc_fmt_request_find_token(client, token);
+ if (request == NULL)
+ return 0xff;
- ipc_client = ipc_client_create(IPC_CLIENT_TYPE_FMT);
- if (ipc_client == NULL) {
- RIL_LOGE("FMT client creation failed");
- goto error_client_create;
- }
+ if (request->seq == 0xff)
+ request->seq = ipc_fmt_seq();
- client->data = (void *) ipc_client;
+ return request->seq;
+}
- RIL_LOGD("Setting log handler");
+RIL_Token ipc_fmt_request_token(unsigned char seq)
+{
+ struct ril_client *client;
+ struct ipc_fmt_request *request;
- rc = ipc_client_set_log_callback(ipc_client, ipc_log_handler, NULL);
- if (rc < 0) {
- RIL_LOGE("Setting log handler failed");
- goto error_log_callback;
- }
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL)
+ return NULL;
- RIL_LOGD("Creating data");
+ request = ipc_fmt_request_find_seq(client, seq);
+ if (request == NULL)
+ return NULL;
- rc = ipc_client_data_create(ipc_client);
- if (rc < 0) {
- RIL_LOGE("Creating data failed");
- goto error_data_create;
- }
+ return request->token;
+}
- RIL_LOGD("Starting bootstrap");
+/*
+ * IPC FMT client
+ */
- rc = ipc_client_bootstrap(ipc_client);
- if (rc < 0) {
- RIL_LOGE("Modem bootstrap failed");
- goto error_bootstrap;
+int ipc_fmt_create(struct ril_client *client)
+{
+ struct ipc_fmt_data *data = NULL;
+ struct ipc_client *ipc_client = NULL;
+ int event_fd = -1;
+ int rc = 0;
+
+ if (client == NULL)
+ return -1;
+
+
+ RIL_CLIENT_LOCK(client);
+
+ client->available = 0;
+
+ data = (struct ipc_fmt_data *) calloc(1, sizeof(struct ipc_fmt_data));
+
+ event_fd = eventfd(0, EFD_NONBLOCK);
+ if (event_fd < 0) {
+ RIL_LOGE("Creating %s event failed", client->name);
+ goto error;
}
- RIL_LOGD("Client power on...");
+ data->event_fd = event_fd;
+
+ ipc_client = ipc_client_create(IPC_CLIENT_TYPE_FMT);
+ if (ipc_client == NULL) {
+ RIL_LOGE("Creating %s client failed", client->name);
+ goto error;
+ }
- rc = ipc_client_power_on(ipc_client);
+ rc = ipc_client_data_create(ipc_client);
if (rc < 0) {
- RIL_LOGE("%s: failed to power on ipc client", __func__);
- goto error_power_on;
+ RIL_LOGE("Creating %s client data failed", client->name);
+ goto error;
}
- RIL_LOGD("Client open...");
+ rc = ipc_client_log_callback_register(ipc_client, ipc_log_handler, NULL);
+ if (rc < 0) {
+ RIL_LOGE("Setting %s client log handler failed", client->name);
+ goto error;
+ }
- rc = ipc_client_open(ipc_client);
+ rc = ipc_client_boot(ipc_client);
if (rc < 0) {
- RIL_LOGE("%s: failed to open ipc client", __func__);
- goto error_open;
+ RIL_LOGE("Booting %s client failed", client->name);
+ goto error;
}
- RIL_LOGD("IPC FMT client done");
+ data->ipc_client = ipc_client;
+ client->data = (void *) data;
- return 0;
+ rc = 0;
+ goto complete;
error:
- ipc_client_power_off(ipc_client);
+ if (event_fd >= 0)
+ close(event_fd);
-error_power_on:
-error_get_fd:
- ipc_client_close(ipc_client);
+ if (ipc_client != NULL) {
+ ipc_client_data_destroy(ipc_client);
+ ipc_client_destroy(ipc_client);
+ }
-error_open:
-error_bootstrap:
- ipc_client_data_destroy(ipc_client);
+ if (data != NULL)
+ free(data);
-error_data_create:
-error_log_callback:
- ipc_client_destroy(ipc_client);
+ rc = -1;
-error_client_create:
- client->data = NULL;
+complete:
+ RIL_CLIENT_UNLOCK(client);
- return -1;
+ return rc;
}
int ipc_fmt_destroy(struct ril_client *client)
{
- struct ipc_client *ipc_client;
+ struct ipc_fmt_data *data;
- int rc;
+ if (client == NULL || client->data == NULL)
+ return -1;
- if (client == NULL || client->data == NULL) {
- RIL_LOGE("Client was already destroyed");
- return 0;
- }
+ data = (struct ipc_fmt_data *) client->data;
- ipc_client = (struct ipc_client *) client->data;
+ if (client->available)
+ ipc_fmt_close(client);
- RIL_LOGD("Destroying ipc fmt client");
+ RIL_CLIENT_LOCK(client);
- if (ipc_client != NULL) {
- ipc_client_power_off(ipc_client);
- ipc_client_close(ipc_client);
- ipc_client_data_destroy(ipc_client);
- ipc_client_destroy(ipc_client);
+ client->available = 0;
+
+ if (data->event_fd >= 0)
+ close(data->event_fd);
+
+ if (data->ipc_client != NULL) {
+ ipc_client_data_destroy(data->ipc_client);
+ ipc_client_destroy(data->ipc_client);
}
+ RIL_CLIENT_UNLOCK(client);
+
+ ipc_fmt_flush(client);
+
+ RIL_CLIENT_LOCK(client);
+
+ memset(data, 0, sizeof(struct ipc_fmt_data));
+ free(data);
+
client->data = NULL;
+ RIL_CLIENT_UNLOCK(client);
+
return 0;
}
-/*
- * IPC RFS
- */
+int ipc_fmt_open(struct ril_client *client)
+{
+ struct ipc_fmt_data *data;
+ int rc;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+ if (data->ipc_client == NULL || data->event_fd < 0)
+ return -1;
+
+ RIL_CLIENT_LOCK(client);
+
+ if (client->failures != 1) {
+ rc = ipc_client_power_on(data->ipc_client);
+ if (rc < 0) {
+ RIL_LOGE("Powering on %s client failed", client->name);
+ goto error;
+ }
+ }
+
+ rc = ipc_client_open(data->ipc_client);
+ if (rc < 0) {
+ RIL_LOGE("Opening %s client failed", client->name);
+ goto error;
+ }
+
+ eventfd_flush(data->event_fd);
+
+ client->available = 1;
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ RIL_CLIENT_UNLOCK(client);
-void ipc_rfs_send(const unsigned short command, unsigned char *data, const int length, unsigned char mseq)
+ return rc;
+}
+
+int ipc_fmt_close(struct ril_client *client)
{
- struct ipc_client *ipc_client;
+ struct ipc_fmt_data *data;
+ int rc;
- if (ril_data.ipc_rfs_client == NULL || ril_data.ipc_rfs_client->data == NULL)
- return;
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+ if (data->ipc_client == NULL || data->event_fd < 0)
+ return -1;
- ipc_client = (struct ipc_client *) ril_data.ipc_rfs_client->data;
+ RIL_CLIENT_LOCK(client);
- RIL_CLIENT_LOCK(ril_data.ipc_rfs_client);
- ipc_client_send(ipc_client, command, 0, data, length, mseq);
- RIL_CLIENT_UNLOCK(ril_data.ipc_rfs_client);
+ client->available = 0;
+
+ rc = eventfd_send(data->event_fd, IPC_CLIENT_CLOSE);
+ if (rc < 0) {
+ RIL_LOGE("Sending %s close event failed", client->name);
+ goto error;
+ }
+
+ rc = ipc_client_close(data->ipc_client);
+ if (rc < 0) {
+ RIL_LOGE("Closing %s client failed", client->name);
+ goto error;
+ }
+
+ if (client->failures != 1) {
+ rc = ipc_client_power_off(data->ipc_client);
+ if (rc < 0) {
+ RIL_LOGE("Powering off %s client failed", client->name);
+ goto error;
+ }
+ }
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ RIL_CLIENT_UNLOCK(client);
+
+ return rc;
}
-int ipc_rfs_read_loop(struct ril_client *client)
+int ipc_fmt_dispatch(struct ril_client *client, struct ipc_message *message)
{
- struct ipc_client *ipc_client;
- struct ipc_message_info info;
+ unsigned int i;
+ int rc;
+
+ if (client == NULL || message == NULL || ril_data == NULL)
+ return -1;
+ RIL_LOCK();
+
+ for (i = 0; i < ipc_fmt_dispatch_handlers_count; i++) {
+ if (ipc_fmt_dispatch_handlers[i].handler == NULL)
+ continue;
+
+ if (ipc_fmt_dispatch_handlers[i].command == message->command) {
+ rc = ipc_fmt_dispatch_handlers[i].handler(message);
+ if (rc < 0)
+ goto error;
+
+ rc = 0;
+ goto complete;
+ }
+ }
+
+ RIL_LOGD("Unhandled %s message: %s", client->name, ipc_command_string(message->command));
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ RIL_UNLOCK();
+
+ return rc;
+}
+
+int ipc_fmt_loop(struct ril_client *client)
+{
+ struct ipc_fmt_data *data;
+ struct ipc_message message;
+ struct ipc_poll_fds fds;
+ int fds_array[] = { 0 };
+ unsigned int count;
+ eventfd_t event;
int rc;
if (client == NULL || client->data == NULL)
- return -EINVAL;
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+ if (data->ipc_client == NULL || data->event_fd < 0)
+ return -1;
+
+ memset(&fds, 0, sizeof(fds));
+ fds.fds = (int *) &fds_array;
- ipc_client = (struct ipc_client *) client->data;
+ count = sizeof(fds_array) / sizeof(int);
while (1) {
- rc = ipc_client_poll(ipc_client, NULL);
+ if (!client->available) {
+ RIL_LOGE("%s client is not available", client->name);
+ return -1;
+ }
+
+ fds_array[0] = data->event_fd;
+ fds.count = count;
+
+ rc = ipc_client_poll(data->ipc_client, &fds, NULL);
if (rc < 0) {
- RIL_LOGE("IPC RFS client poll failed, aborting");
- goto error;
+ RIL_LOGE("Polling %s client failed", client->name);
+ return -1;
}
- memset(&info, 0, sizeof(info));
+ if (fds.fds[0] == data->event_fd && fds.count > 0) {
+ rc = eventfd_recv(data->event_fd, &event);
+ if (rc < 0)
+ return -1;
+
+ switch (event) {
+ case IPC_CLIENT_CLOSE:
+ return 0;
+ case IPC_CLIENT_IO_ERROR:
+ return -1;
+ }
+ }
+
+ if ((unsigned int) rc == fds.count)
+ continue;
+
+ memset(&message, 0, sizeof(message));
+ RIL_LOCK();
RIL_CLIENT_LOCK(client);
- if (ipc_client_recv(ipc_client, &info) < 0) {
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_VERSION_STRING);
+
+ rc = ipc_client_recv(data->ipc_client, &message);
+ if (rc < 0) {
+ RIL_LOGE("Receiving from %s client failed", client->name);
+
+ release_wake_lock(RIL_VERSION_STRING);
RIL_CLIENT_UNLOCK(client);
- RIL_LOGE("IPC RFS recv failed, aborting");
- goto error;
+ RIL_UNLOCK();
+
+ return -1;
}
+
+ release_wake_lock(RIL_VERSION_STRING);
RIL_CLIENT_UNLOCK(client);
+ RIL_UNLOCK();
+
+ rc = ipc_fmt_dispatch(client, &message);
+ if (rc < 0) {
+ RIL_LOGE("Dispatching %s message failed", client->name);
- ipc_rfs_dispatch(&info);
+ if (message.data != NULL && message.size > 0)
+ free(message.data);
- ipc_client_response_free(ipc_client, &info);
+ return -1;
+ }
+
+ if (client->failures)
+ client->failures = 0;
+
+ if (message.data != NULL && message.size > 0)
+ free(message.data);
+ }
+
+ return 0;
+}
+
+int ipc_fmt_request_register(struct ril_client *client, int request,
+ RIL_Token token)
+{
+ struct ipc_fmt_data *data;
+ struct ipc_fmt_request *ipc_fmt_request;
+ struct list_head *list_end;
+ struct list_head *list;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
+
+ ipc_fmt_request = (struct ipc_fmt_request *) calloc(1, sizeof(struct ipc_fmt_request));
+ ipc_fmt_request->request = request;
+ ipc_fmt_request->token = token;
+ ipc_fmt_request->seq = 0xff;
+
+ list_end = data->requests;
+ while (list_end != NULL && list_end->next != NULL)
+ list_end = list_end->next;
+
+ list = list_head_alloc(list_end, NULL, (void *) ipc_fmt_request);
+
+ if (data->requests == NULL)
+ data->requests = list;
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
+}
+
+int ipc_fmt_request_unregister(struct ril_client *client, int request,
+ RIL_Token token)
+{
+ struct ipc_fmt_data *data;
+ struct ipc_fmt_request *ipc_fmt_request;
+ struct list_head *list;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
+
+ list = data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ ipc_fmt_request = (struct ipc_fmt_request *) list->data;
+
+ if (ipc_fmt_request->request == request && ipc_fmt_request->token == token) {
+ memset(ipc_fmt_request, 0, sizeof(struct ipc_fmt_request));
+ free(ipc_fmt_request);
+
+ if (list == data->requests)
+ data->requests = list->next;
+
+ list_head_free(list);
+
+ break;
+ }
+
+list_continue:
+ list = list->next;
+ }
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
+}
+
+int ipc_fmt_request_flush(struct ril_client *client)
+{
+ struct ipc_fmt_data *data;
+ struct ipc_fmt_request *ipc_fmt_request;
+ struct list_head *list;
+ struct list_head *list_next;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
+
+ list = data->requests;
+ while (list != NULL) {
+ if (list->data != NULL) {
+ ipc_fmt_request = (struct ipc_fmt_request *) list->data;
+
+ memset(ipc_fmt_request, 0, sizeof(struct ipc_fmt_request));
+ free(ipc_fmt_request);
+ }
+
+ if (list == data->requests)
+ data->requests = list->next;
+
+ list_next = list->next;
+
+ list_head_free(list);
+
+list_continue:
+ list = list_next;
+ }
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
+}
+
+struct ipc_fmt_request *ipc_fmt_request_find_token(struct ril_client *client,
+ RIL_Token token)
+{
+ struct ipc_fmt_data *data;
+ struct ipc_fmt_request *request;
+ struct list_head *list;
+
+ if (client == NULL || client->data == NULL)
+ return NULL;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
+
+ list = data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ request = (struct ipc_fmt_request *) list->data;
+
+ if (request->token == token) {
+ RIL_CLIENT_UNLOCK(client);
+ return request;
+ }
+
+list_continue:
+ list = list->next;
+ }
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return NULL;
+}
+
+struct ipc_fmt_request *ipc_fmt_request_find_seq(struct ril_client *client,
+ unsigned char seq)
+{
+ struct ipc_fmt_data *data;
+ struct ipc_fmt_request *request;
+ struct list_head *list;
+
+ if (client == NULL || client->data == NULL)
+ return NULL;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
+
+ list = data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ request = (struct ipc_fmt_request *) list->data;
+
+ if (request->seq == seq) {
+ RIL_CLIENT_UNLOCK(client);
+ return request;
+ }
+
+list_continue:
+ list = list->next;
+ }
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return NULL;
+}
+
+int ipc_fmt_flush(struct ril_client *client)
+{
+ struct ipc_fmt_data *data;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ ipc_fmt_request_flush(client);
+
+ ipc_gen_phone_res_expect_flush(client);
+
+ RIL_CLIENT_LOCK(client);
+
+ memset(&data->sim_icc_type_data, 0, sizeof(data->sim_icc_type_data));
+ memset(&data->hsdpa_status_data, 0, sizeof(data->hsdpa_status_data));
+ data->svc_session = 0;
+
+ data->seq = 0x00;
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
+}
+/*
+ * IPC RFS
+ */
+
+int ipc_rfs_send(unsigned char mseq, unsigned short command, const void *data,
+ size_t size)
+{
+ struct ril_client *client;
+ struct ipc_rfs_data *ipc_rfs_data;
+ int rc;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_RFS);
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ ipc_rfs_data = (struct ipc_rfs_data *) client->data;
+ if (ipc_rfs_data->ipc_client == NULL || ipc_rfs_data->event_fd < 0)
+ return -1;
+
+ if (!client->available) {
+ RIL_LOGE("%s client is not available", client->name);
+ return -1;
+ }
+
+ RIL_CLIENT_LOCK(client);
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_VERSION_STRING);
+
+ rc = ipc_client_send(ipc_rfs_data->ipc_client, mseq, command, 0x00, data, size);
+ if (rc < 0) {
+ RIL_LOGE("Sending to %s client failed", client->name);
+ goto error;
}
rc = 0;
goto complete;
error:
- ril_radio_state_update(RADIO_STATE_UNAVAILABLE);
- ril_sms_send(RIL_SMS_NUMBER, "Samsung-RIL: The modem just crashed, please reboot your device if you can't get service back.");
+ eventfd_send(ipc_rfs_data->event_fd, IPC_CLIENT_IO_ERROR);
rc = -1;
complete:
+ release_wake_lock(RIL_VERSION_STRING);
+ RIL_CLIENT_UNLOCK(client);
+
return rc;
}
+/*
+ * IPC RFS client
+ */
+
int ipc_rfs_create(struct ril_client *client)
{
- struct ipc_client *ipc_client;
-
- int rc;
+ struct ipc_rfs_data *data = NULL;
+ struct ipc_client *ipc_client = NULL;
+ int event_fd = -1;
+ int rc = 0;
if (client == NULL)
- return -EINVAL;
-
- RIL_LOGD("Creating new RFS client");
+ return -1;
- ipc_client = ipc_client_create(IPC_CLIENT_TYPE_RFS);
- if (ipc_client == NULL) {
- RIL_LOGE("RFS client creation failed");
- goto error_client_create;
- }
+ data = (struct ipc_rfs_data *) calloc(1, sizeof(struct ipc_rfs_data));
- client->data = (void *) ipc_client;
+ RIL_CLIENT_LOCK(client);
- RIL_LOGD("Setting log handler");
+ client->available = 0;
- rc = ipc_client_set_log_callback(ipc_client, ipc_log_handler, NULL);
- if (rc < 0) {
- RIL_LOGE("Setting log handler failed");
- goto error_log_callback;
+ event_fd = eventfd(0, EFD_NONBLOCK);
+ if (event_fd < 0) {
+ RIL_LOGE("Creating %s event failed", client->name);
+ goto error;
}
- RIL_LOGD("Creating data");
+ data->event_fd = event_fd;
+
+ ipc_client = ipc_client_create(IPC_CLIENT_TYPE_RFS);
+ if (ipc_client == NULL) {
+ RIL_LOGE("Creating %s client failed", client->name);
+ goto error;
+ }
rc = ipc_client_data_create(ipc_client);
if (rc < 0) {
- RIL_LOGE("Creating data failed");
- goto error_data_create;
+ RIL_LOGE("Creating %s client data failed", client->name);
+ goto error;
}
- RIL_LOGD("Client open...");
-
- rc = ipc_client_open(ipc_client);
+ rc = ipc_client_log_callback_register(ipc_client, ipc_log_handler, NULL);
if (rc < 0) {
- RIL_LOGE("%s: failed to open ipc client", __func__);
- goto error_open;
+ RIL_LOGE("Setting %s client log handler failed", client->name);
+ goto error;
}
- RIL_LOGD("IPC RFS client done");
+ data->ipc_client = ipc_client;
+ client->data = (void *) data;
- return 0;
+ rc = 0;
+ goto complete;
error:
-error_get_fd:
- ipc_client_close(ipc_client);
+ if (event_fd >= 0)
+ close(event_fd);
-error_open:
- ipc_client_data_destroy(ipc_client);
+ if (ipc_client != NULL) {
+ ipc_client_data_destroy(ipc_client);
+ ipc_client_destroy(ipc_client);
+ }
-error_data_create:
-error_log_callback:
- ipc_client_destroy(ipc_client);
+ if (data != NULL)
+ free(data);
-error_client_create:
- client->data = NULL;
+ rc = -1;
- return -1;
-}
+complete:
+ RIL_CLIENT_UNLOCK(client);
+ return rc;
+}
int ipc_rfs_destroy(struct ril_client *client)
{
- struct ipc_client *ipc_client;
+ struct ipc_rfs_data *data;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_rfs_data *) client->data;
+
+ if (client->available)
+ ipc_rfs_close(client);
+
+ RIL_CLIENT_LOCK(client);
+
+ client->available = 0;
+
+ if (data->event_fd >= 0)
+ close(data->event_fd);
+
+ if (data->ipc_client != NULL) {
+ ipc_client_data_destroy(data->ipc_client);
+ ipc_client_destroy(data->ipc_client);
+ }
+
+ memset(data, 0, sizeof(struct ipc_rfs_data));
+ free(data);
+
+ client->data = NULL;
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
+}
+int ipc_rfs_open(struct ril_client *client)
+{
+ struct ipc_rfs_data *data;
int rc;
- if (client == NULL || client->data == NULL) {
- RIL_LOGE("Client was already destroyed");
- return 0;
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_rfs_data *) client->data;
+ if (data->ipc_client == NULL || data->event_fd < 0)
+ return -1;
+
+ RIL_CLIENT_LOCK(client);
+
+ rc = ipc_client_open(data->ipc_client);
+ if (rc < 0) {
+ RIL_LOGE("Opening %s client failed", client->name);
+ goto error;
}
- ipc_client = (struct ipc_client *) client->data;
+ eventfd_flush(data->event_fd);
- RIL_LOGD("Destroying ipc rfs client");
+ client->available = 1;
- if (ipc_client != NULL) {
- ipc_client_close(ipc_client);
- ipc_client_data_destroy(ipc_client);
- ipc_client_destroy(ipc_client);
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ RIL_CLIENT_UNLOCK(client);
+
+ return rc;
+}
+
+int ipc_rfs_close(struct ril_client *client)
+{
+ struct ipc_rfs_data *data;
+ int rc;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_rfs_data *) client->data;
+ if (data->ipc_client == NULL || data->event_fd < 0)
+ return -1;
+
+ RIL_CLIENT_LOCK(client);
+
+ client->available = 0;
+
+ rc = eventfd_send(data->event_fd, IPC_CLIENT_CLOSE);
+ if (rc < 0) {
+ RIL_LOGE("Sending %s close event failed", client->name);
+ goto error;
}
- client->data = NULL;
+ rc = ipc_client_close(data->ipc_client);
+ if (rc < 0) {
+ RIL_LOGE("Closing %s client failed", client->name);
+ goto error;
+ }
+
+ rc = ipc_client_power_off(data->ipc_client);
+ if (rc < 0) {
+ RIL_LOGE("Powering off %s client failed", client->name);
+ goto error;
+ }
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ RIL_CLIENT_UNLOCK(client);
+
+ return rc;
+}
+
+int ipc_rfs_dispatch(struct ril_client *client, struct ipc_message *message)
+{
+ unsigned int i;
+ int rc;
+
+ if (client == NULL || message == NULL || ril_data == NULL)
+ return -1;
+
+ RIL_LOCK();
+
+ for (i = 0; i < ipc_rfs_dispatch_handlers_count; i++) {
+ if (ipc_rfs_dispatch_handlers[i].handler == NULL)
+ continue;
+
+ if (ipc_rfs_dispatch_handlers[i].command == message->command) {
+ rc = ipc_rfs_dispatch_handlers[i].handler(message);
+ if (rc < 0)
+ goto error;
+
+ rc = 0;
+ goto complete;
+ }
+ }
+
+ RIL_LOGD("Unhandled %s message: %s", client->name, ipc_command_string(message->command));
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ RIL_UNLOCK();
+
+ return rc;
+}
+
+int ipc_rfs_loop(struct ril_client *client)
+{
+ struct ipc_rfs_data *data;
+ struct ipc_message message;
+ struct ipc_poll_fds fds;
+ int fds_array[] = { 0 };
+ unsigned int count;
+ eventfd_t event;
+ int rc;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_rfs_data *) client->data;
+ if (data->ipc_client == NULL || data->event_fd < 0)
+ return -1;
+
+ memset(&fds, 0, sizeof(fds));
+ fds.fds = (int *) &fds_array;
+
+ count = sizeof(fds_array) / sizeof(int);
+
+ while (1) {
+ if (!client->available) {
+ RIL_LOGE("%s client is not available", client->name);
+ return -1;
+ }
+
+ fds_array[0] = data->event_fd;
+ fds.count = count;
+
+ rc = ipc_client_poll(data->ipc_client, &fds, NULL);
+ if (rc < 0) {
+ RIL_LOGE("Polling %s client failed", client->name);
+ return -1;
+ }
+
+ if (fds.fds[0] == data->event_fd && fds.count > 0) {
+ rc = eventfd_recv(data->event_fd, &event);
+ if (rc < 0)
+ return -1;
+
+ switch (event) {
+ case IPC_CLIENT_CLOSE:
+ return 0;
+ case IPC_CLIENT_IO_ERROR:
+ return -1;
+ }
+ }
+
+ if ((unsigned int) rc == fds.count)
+ continue;
+
+ memset(&message, 0, sizeof(message));
+
+ RIL_LOCK();
+ RIL_CLIENT_LOCK(client);
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_VERSION_STRING);
+
+ rc = ipc_client_recv(data->ipc_client, &message);
+ if (rc < 0) {
+ RIL_LOGE("Receiving from %s client failed", client->name);
+
+ release_wake_lock(RIL_VERSION_STRING);
+ RIL_CLIENT_UNLOCK(client);
+ RIL_UNLOCK();
+
+ return -1;
+ }
+
+ release_wake_lock(RIL_VERSION_STRING);
+ RIL_CLIENT_UNLOCK(client);
+ RIL_UNLOCK();
+
+ rc = ipc_rfs_dispatch(client, &message);
+ if (rc < 0) {
+ RIL_LOGE("Dispatching %s message failed", client->name);
+
+ if (message.data != NULL && message.size > 0)
+ free(message.data);
+
+ return -1;
+ }
+
+ if (client->failures)
+ client->failures = 0;
+
+ if (message.data != NULL && message.size > 0)
+ free(message.data);
+ }
return 0;
}
/*
- * IPC clients structures
+ * RIL clients
*/
-struct ril_client_funcs ipc_fmt_client_funcs = {
+struct ril_client_handlers ipc_fmt_handlers = {
.create = ipc_fmt_create,
.destroy = ipc_fmt_destroy,
- .read_loop = ipc_fmt_read_loop,
+ .open = ipc_fmt_open,
+ .close = ipc_fmt_close,
+ .loop = ipc_fmt_loop,
};
-struct ril_client_funcs ipc_rfs_client_funcs = {
+struct ril_client_handlers ipc_rfs_handlers = {
.create = ipc_rfs_create,
.destroy = ipc_rfs_destroy,
- .read_loop = ipc_rfs_read_loop,
+ .open = ipc_rfs_open,
+ .close = ipc_rfs_close,
+ .loop = ipc_rfs_loop,
+};
+
+struct ril_client_callbacks ipc_fmt_callbacks = {
+ .request_register = ipc_fmt_request_register,
+ .request_unregister = ipc_fmt_request_unregister,
+ .flush = ipc_fmt_flush,
+};
+
+struct ril_client_callbacks ipc_rfs_callbacks = {
+ .request_register = NULL,
+ .request_unregister = NULL,
+ .flush = NULL,
+};
+
+struct ril_client ipc_fmt_client = {
+ .id = RIL_CLIENT_IPC_FMT,
+ .name = "IPC FMT",
+ .critical = 1,
+ .handlers = &ipc_fmt_handlers,
+ .callbacks = &ipc_fmt_callbacks,
+};
+
+struct ril_client ipc_rfs_client = {
+ .id = RIL_CLIENT_IPC_RFS,
+ .name = "IPC RFS",
+ .critical = 0,
+ .handlers = &ipc_rfs_handlers,
+ .callbacks = &ipc_rfs_callbacks,
};
diff --git a/ipc.h b/ipc.h
index 3ede416..3874b76 100644
--- a/ipc.h
+++ b/ipc.h
@@ -1,8 +1,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
@@ -21,21 +20,106 @@
#ifndef _SAMSUNG_RIL_IPC_H_
#define _SAMSUNG_RIL_IPC_H_
-#include "samsung-ril.h"
+#include <stdlib.h>
-#define ipc_fmt_send_get(command, mseq) \
- ipc_fmt_send(command, IPC_TYPE_GET, NULL, 0, mseq)
+#include <samsung-ril.h>
-#define ipc_fmt_send_set(command, mseq, data, length) \
- ipc_fmt_send(command, IPC_TYPE_SET, data, length, mseq)
+struct ril_client;
-#define ipc_fmt_send_exec(command, mseq) \
- ipc_fmt_send(command, IPC_TYPE_EXEC, NULL, 0, mseq)
+/*
+ * Values
+ */
+
+#define IPC_CLIENT_CLOSE 0x00
+#define IPC_CLIENT_IO_ERROR 0x01
+
+/*
+ * Structures
+ */
+
+struct ipc_fmt_request {
+ int request;
+ RIL_Token token;
+ unsigned char seq;
+};
+
+struct ipc_fmt_data {
+ struct ipc_client *ipc_client;
+ int event_fd;
+
+ struct list_head *gen_phone_res_expect;
+
+ struct ipc_sec_sim_icc_type_data sim_icc_type_data;
+ struct ipc_gprs_hsdpa_status_data hsdpa_status_data;
+ int svc_session;
+
+ struct list_head *requests;
+ unsigned char seq;
+};
+
+struct ipc_rfs_data {
+ struct ipc_client *ipc_client;
+ int event_fd;
+};
-extern struct ril_client_funcs ipc_fmt_client_funcs;
-extern struct ril_client_funcs ipc_rfs_client_funcs;
+struct ipc_dispatch_handler {
+ unsigned short command;
+ int (*handler)(struct ipc_message *message);
+};
+
+/*
+ * Helpers
+ */
+
+/* Utils */
+void ipc_log_handler(void *log_data, const char *message);
+
+/* IPC FMT */
+int ipc_fmt_send(unsigned char mseq, unsigned short command, unsigned char type,
+ const void *data, size_t size);
+unsigned char ipc_fmt_seq(void);
+unsigned char ipc_fmt_request_seq(RIL_Token token);
+RIL_Token ipc_fmt_request_token(unsigned char seq);
+
+/* IPC FMT client */
+int ipc_fmt_create(struct ril_client *client);
+int ipc_fmt_destroy(struct ril_client *client);
+int ipc_fmt_open(struct ril_client *client);
+int ipc_fmt_close(struct ril_client *client);
+int ipc_fmt_dispatch(struct ril_client *client, struct ipc_message *message);
+int ipc_fmt_loop(struct ril_client *client);
+int ipc_fmt_request_register(struct ril_client *client, int request,
+ RIL_Token token);
+int ipc_fmt_request_unregister(struct ril_client *client, int request,
+ RIL_Token token);
+int ipc_fmt_request_flush(struct ril_client *client);
+struct ipc_fmt_request *ipc_fmt_request_find_token(struct ril_client *client,
+ RIL_Token token);
+struct ipc_fmt_request *ipc_fmt_request_find_seq(struct ril_client *client,
+ unsigned char seq);
+int ipc_fmt_flush(struct ril_client *client);
+
+/* IPC RFS */
+int ipc_rfs_send(unsigned char mseq, unsigned short command, const void *data,
+ size_t size);
+
+/* IPC RFS client */
+int ipc_rfs_create(struct ril_client *client);
+int ipc_rfs_destroy(struct ril_client *client);
+int ipc_rfs_open(struct ril_client *client);
+int ipc_rfs_close(struct ril_client *client);
+int ipc_rfs_dispatch(struct ril_client *client, struct ipc_message *message);
+int ipc_rfs_loop(struct ril_client *client);
+
+/*
+ * RIL clients
+ */
-void ipc_fmt_send(const unsigned short command, const char type, unsigned char *data, const int length, unsigned char mseq);
-void ipc_rfs_send(const unsigned short command, unsigned char *data, const int length, unsigned char mseq);
+extern struct ril_client_handlers ipc_fmt_handlers;
+extern struct ril_client_handlers ipc_rfs_handlers;
+extern struct ril_client_callbacks ipc_fmt_callbacks;
+extern struct ril_client_callbacks ipc_rfs_callbacks;
+extern struct ril_client ipc_fmt_client;
+extern struct ril_client ipc_rfs_client;
#endif
diff --git a/misc.c b/misc.c
index 131a660..7668022 100644
--- a/misc.c
+++ b/misc.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,256 +18,270 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
-#define LOG_TAG "RIL-MISC"
+#include <stdlib.h>
+
+#define LOG_TAG "RIL"
#include <utils/Log.h>
-#include "samsung-ril.h"
-#include "util.h"
+#include <samsung-ril.h>
-void ril_request_get_imei_send(RIL_Token t)
+int ipc_misc_me_version(struct ipc_message *message)
{
- unsigned char data;
+ struct ipc_misc_me_version_response_data *data;
+ char *baseband_version;
+ int active;
- data = IPC_MISC_ME_SN_SERIAL_NUM;
- ipc_fmt_send(IPC_MISC_ME_SN, IPC_TYPE_GET, (unsigned char *) &data, sizeof(data), ril_request_get_id(t));
-}
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_misc_me_version_response_data))
+ return -1;
-void ril_request_get_imei(RIL_Token t)
-{
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
- if (ril_data.tokens.get_imei) {
- RIL_LOGD("Another IMEI request is waiting, aborting");
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
+ data = (struct ipc_misc_me_version_response_data *) message->data;
- ril_data.tokens.get_imei = t;
+ baseband_version = strndup(data->software_version, sizeof(data->software_version));
- if (ril_data.tokens.get_imeisv) {
- RIL_LOGD("IMEISV token found: %p", ril_data.tokens.get_imeisv);
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) baseband_version, sizeof(baseband_version));
- ril_request_get_imei_send(ril_data.tokens.get_imei);
- } else {
- RIL_LOGD("Waiting for IMEISV token");
- }
+ free(baseband_version);
+
+ return 0;
}
-void ril_request_get_imeisv(RIL_Token t)
+int ril_request_baseband_version(void *data, size_t size, RIL_Token token)
{
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
+ struct ipc_misc_me_version_request_data request_data;
+ struct ril_request *request;
+ int rc;
- if (ril_data.tokens.get_imeisv) {
- RIL_LOGD("Another IMEISV request is waiting, aborting");
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- ril_data.tokens.get_imeisv = t;
-
- if (ril_data.tokens.get_imei) {
- RIL_LOGD("IMEI token found: %p", ril_data.tokens.get_imei);
-
- ril_request_get_imei_send(ril_data.tokens.get_imei);
- } else {
- RIL_LOGD("Waiting for IMEI token");
- }
-}
-
-void ipc_misc_me_sn_imei(struct ipc_message_info *info)
-{
- struct ipc_misc_me_sn *imei_info;
- RIL_Token t;
- char imei[33];
- char imeisv[3];
+ request = ril_request_find_request_status(RIL_REQUEST_BASEBAND_VERSION, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
- if (info->type != IPC_TYPE_RESP)
+ rc = ipc_misc_me_version_setup(&request_data);
+ if (rc < 0)
goto error;
- if (info->data == NULL || info->length < sizeof(struct ipc_misc_me_sn))
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_MISC_ME_VERSION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
goto error;
- imei_info = (struct ipc_misc_me_sn *) info->data;
- t = ril_request_get_token(info->aseq);
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
- if (ril_data.tokens.get_imei != t)
- RIL_LOGE("IMEI tokens mismatch (%p and %p)",
- ril_data.tokens.get_imei, t);
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
- if (imei_info->length > 32)
- return;
+ rc = RIL_REQUEST_COMPLETED;
- memset(imei, 0, sizeof(imei));
- memset(imeisv, 0, sizeof(imeisv));
+complete:
+ return rc;
+}
- memcpy(imei, imei_info->data, imei_info->length);
+int ipc_misc_me_imsi(struct ipc_message *message)
+{
+ char *imsi;
- // Last two bytes of IMEI in imei_info are the SV bytes
- memcpy(imeisv, (imei_info->data + imei_info->length - 2), 2);
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_misc_me_imsi_header))
+ return -1;
- // In case of token mismatch, complete both requests
- if (t && ril_data.tokens.get_imei != t) {
- ril_request_complete(t, RIL_E_SUCCESS, imei, sizeof(char *));
- }
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
- // IMEI
- if (ril_data.tokens.get_imei) {
- ril_request_complete(ril_data.tokens.get_imei,
- RIL_E_SUCCESS, imei, sizeof(char *));
- ril_data.tokens.get_imei = 0;
+ imsi = ipc_misc_me_imsi_imsi_extract(message->data, message->size);
+ if (imsi == NULL) {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ return 0;
}
- // IMEI SV
- if (ril_data.tokens.get_imeisv) {
- ril_request_complete(ril_data.tokens.get_imeisv,
- RIL_E_SUCCESS, imeisv, sizeof(char *));
- ril_data.tokens.get_imeisv = 0;
- }
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) imsi, sizeof(imsi));
- return;
+ free(imsi);
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ return 0;
}
-void ipc_misc_me_sn(struct ipc_message_info *info)
+int ril_request_get_imsi(void *data, size_t size, RIL_Token token)
{
- struct ipc_misc_me_sn *me_sn_info;
-
- if (info->type != IPC_TYPE_RESP)
- return;
+ struct ril_request *request;
+ int rc;
- if (info->data == NULL || info->length < sizeof(struct ipc_misc_me_sn))
- goto error;
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- me_sn_info = (struct ipc_misc_me_sn *) info->data;
+ request = ril_request_find_request_status(RIL_REQUEST_GET_IMSI, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
- switch (me_sn_info->type) {
- case IPC_MISC_ME_SN_SERIAL_NUM:
- ipc_misc_me_sn_imei(info);
- break;
- case IPC_MISC_ME_SN_SERIAL_NUM_SERIAL:
- RIL_LOGD("Got IPC_MISC_ME_SN_SERIAL_NUM_SERIAL: %s\n",
- me_sn_info->data);
- break;
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_MISC_ME_IMSI, IPC_TYPE_GET, NULL, 0);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
}
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_HANDLED;
}
-void ril_request_baseband_version(RIL_Token t)
+int ipc_misc_me_sn(struct ipc_message *message)
{
- unsigned char data;
+ struct ipc_misc_me_sn_response_data *data;
+ struct ril_request *request;
+ char *imei;
+ char *imeisv;
+ unsigned int offset;
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_misc_me_sn_response_data))
+ return -1;
- if (ril_data.tokens.baseband_version) {
- RIL_LOGD("Another Baseband version request is waiting, aborting");
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
+ if (message->type != IPC_TYPE_RESP)
+ return 0;
- ril_data.tokens.baseband_version = t;
+ data = (struct ipc_misc_me_sn_response_data *) message->data;
- data = 0xff;
+ if (data->type != IPC_MISC_ME_SN_SERIAL_NUM)
+ return 0;
- ipc_fmt_send(IPC_MISC_ME_VERSION, IPC_TYPE_GET, (unsigned char *) &data, sizeof(data), ril_request_get_id(t));
-}
-
-void ipc_misc_me_version(struct ipc_message_info *info)
-{
- char sw_version[33];
- struct ipc_misc_me_version *version;
- RIL_Token t;
+ imei = ipc_misc_me_sn_extract(data);
+ if (imei == NULL) {
+ request = ril_request_find_request_status(RIL_REQUEST_GET_IMEI, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ ril_request_complete(request->token, RIL_E_GENERIC_FAILURE, NULL, 0);
- if (info->type != IPC_TYPE_RESP)
- return;
+ request = ril_request_find_request_status(RIL_REQUEST_GET_IMEISV, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ ril_request_complete(request->token, RIL_E_GENERIC_FAILURE, NULL, 0);
- if (info->data == NULL || info->length < sizeof(struct ipc_misc_me_version))
- goto error;
+ return 0;
+ }
- version = (struct ipc_misc_me_version *) info->data;
- t = ril_request_get_token(info->aseq);
+ offset = strlen(imei) - 2;
+ imeisv = strdup((char *) (imei + offset));
- if (ril_data.tokens.baseband_version != t)
- RIL_LOGE("Baseband tokens mismatch (%p and %p)",
- ril_data.tokens.baseband_version, t);
+ imei[offset] = '\0';
- memcpy(sw_version, version->sw_version, 32);
- sw_version[32] = '\0';
+ request = ril_request_find_request_status(RIL_REQUEST_GET_IMEI, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ ril_request_complete(request->token, RIL_E_SUCCESS, (void *) imei, sizeof(imei));
- ril_request_complete(t, RIL_E_SUCCESS, sw_version, sizeof(sw_version));
- ril_data.tokens.baseband_version = 0;
+ request = ril_request_find_request_status(RIL_REQUEST_GET_IMEISV, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ ril_request_complete(request->token, RIL_E_SUCCESS, (void *) imeisv, sizeof(imeisv));
- return;
+ free(imei);
+ free(imeisv);
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ return 0;
}
-void ril_request_get_imsi(RIL_Token t)
+int ril_request_get_imei(void *data, size_t size, RIL_Token token)
{
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
+ struct ipc_misc_me_sn_request_data request_data;
+ struct ril_request *request;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- ipc_fmt_send_get(IPC_MISC_ME_IMSI, ril_request_get_id(t));
+ request = ril_request_find_request_status(RIL_REQUEST_GET_IMEI, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ // The response to the IMEISV request will hold IMEI as well
+ request = ril_request_find_request_status(RIL_REQUEST_GET_IMEISV, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_HANDLED;
+
+ request_data.type = IPC_MISC_ME_SN_SERIAL_NUM;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_MISC_ME_SN, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ return RIL_REQUEST_HANDLED;
}
-void ipc_misc_me_imsi(struct ipc_message_info *info)
+int ril_request_get_imeisv(void *data, size_t size, RIL_Token token)
{
- unsigned char imsi_length;
- char *imsi;
+ struct ipc_misc_me_sn_request_data request_data;
+ struct ril_request *request;
+ int rc;
- if (info->type != IPC_TYPE_RESP)
- return;
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- if (info->data == NULL || info->length < sizeof(unsigned char))
- goto error;
+ request = ril_request_find_request_status(RIL_REQUEST_GET_IMEISV, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ // The response to the IMEI request will hold IMEISV as well
+ request = ril_request_find_request_status(RIL_REQUEST_GET_IMEI, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_HANDLED;
- imsi_length = *((unsigned char *) info->data);
+ request_data.type = IPC_MISC_ME_SN_SERIAL_NUM;
- if (((int) info->length) < imsi_length + 1) {
- RIL_LOGE("%s: missing IMSI data", __func__);
- ril_request_complete(ril_request_get_token(info->aseq),
- RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_MISC_ME_SN, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
}
- imsi = (char *) calloc(1, imsi_length + 1);
- memcpy(imsi, ((unsigned char *) info->data) + sizeof(unsigned char), imsi_length);
- imsi[imsi_length] = '\0';
+ return RIL_REQUEST_HANDLED;
+}
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, imsi, imsi_length + 1);
+int ipc_misc_time_info(struct ipc_message *message)
+{
+ struct ipc_misc_time_info_data *data;
+ char *string = NULL;
- free(imsi);
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_misc_time_info_data))
+ return -1;
- return;
+ data = (struct ipc_misc_time_info_data *) message->data;
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ asprintf(&string, "%02u/%02u/%02u,%02u:%02u:%02u%c%02d,%02d", data->year, data->mon, data->day, data->hour, data->min, data->sec, data->tz < 0 ? '-' : '+', data->tz < 0 ? -data->tz : data->tz, data->dl);
+
+ ril_request_unsolicited(RIL_UNSOL_NITZ_TIME_RECEIVED, string, sizeof(string));
+
+ if (string != NULL)
+ free(string);
+
+ return 0;
}
-void ipc_misc_time_info(struct ipc_message_info *info)
+int ril_request_screen_state(void *data, size_t size, RIL_Token token)
{
- struct ipc_misc_time_info *nitz;
- char str[128];
+ int value;
+ int rc;
+
+ if (data == NULL || size < sizeof(int)) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- if (info->data == NULL || info->length < sizeof(struct ipc_misc_time_info))
- return;
+ value = *((int *) data);
- nitz = (struct ipc_misc_time_info *) info->data;
+ if (value)
+#if RIL_VERSION >= 6
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
+#else
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
+#endif
- sprintf(str, "%02u/%02u/%02u,%02u:%02u:%02u%c%02d,%02d",
- nitz->year, nitz->mon, nitz->day, nitz->hour,
- nitz->min, nitz->sec, nitz->tz < 0 ? '-' : '+',
- nitz->tz < 0 ? -nitz->tz : nitz->tz, nitz->dl);
+ ril_request_complete(token, RIL_E_SUCCESS, NULL, 0);
- ril_request_unsolicited(RIL_UNSOL_NITZ_TIME_RECEIVED,
- str, strlen(str) + 1);
+ return RIL_REQUEST_COMPLETED;
}
diff --git a/net.c b/net.c
deleted file mode 100644
index 04a06ff..0000000
--- a/net.c
+++ /dev/null
@@ -1,916 +0,0 @@
-/*
- * 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>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define LOG_TAG "RIL-NET"
-#include <utils/Log.h>
-
-#include "samsung-ril.h"
-#include "util.h"
-
-#include <plmn_list.h>
-
-unsigned char ipc2ril_reg_state(unsigned char reg_state)
-{
- switch (reg_state) {
- case IPC_NET_REGISTRATION_STATE_NONE:
- return 0;
- case IPC_NET_REGISTRATION_STATE_HOME:
- return 1;
- case IPC_NET_REGISTRATION_STATE_SEARCHING:
- return 2;
- case IPC_NET_REGISTRATION_STATE_EMERGENCY:
- return 10;
- case IPC_NET_REGISTRATION_STATE_ROAMING:
- return 5;
- case IPC_NET_REGISTRATION_STATE_UNKNOWN:
- return 4;
- default:
- RIL_LOGE("%s: invalid reg_state: %d", __func__, reg_state);
- return 0;
- }
-}
-
-unsigned char ipc2ril_act(unsigned char act)
-{
- switch (act) {
- case IPC_NET_ACCESS_TECHNOLOGY_GPRS:
- return 1;
- case IPC_NET_ACCESS_TECHNOLOGY_EDGE:
- return 2;
- case IPC_NET_ACCESS_TECHNOLOGY_UMTS:
- return 3;
- case IPC_NET_ACCESS_TECHNOLOGY_GSM:
- case IPC_NET_ACCESS_TECHNOLOGY_GSM2:
- default:
- return 0;
- }
-}
-
-unsigned char ipc2ril_gprs_act(unsigned char act)
-{
- switch (act) {
- case IPC_NET_ACCESS_TECHNOLOGY_GPRS:
- return 1;
- case IPC_NET_ACCESS_TECHNOLOGY_EDGE:
- return 2;
- case IPC_NET_ACCESS_TECHNOLOGY_UMTS:
- return 3;
- case IPC_NET_ACCESS_TECHNOLOGY_GSM:
- case IPC_NET_ACCESS_TECHNOLOGY_GSM2:
- default:
- return 0;
- }
-}
-
-int ipc2ril_mode_sel(unsigned char mode)
-{
- switch (mode) {
- case 0:
- return 7; // auto mode
- case IPC_NET_MODE_SEL_GSM_UMTS:
- return 0;
- case IPC_NET_MODE_SEL_GSM_ONLY:
- return 1;
- case IPC_NET_MODE_SEL_UMTS_ONLY:
- return 2;
- default:
- return 0;
- }
-}
-
-unsigned char ril2ipc_mode_sel(int mode)
-{
- switch (mode) {
- case 1: // GSM only
- return IPC_NET_MODE_SEL_GSM_ONLY;
- case 2: // WCDMA only
- return IPC_NET_MODE_SEL_UMTS_ONLY;
- case 0:
- default: // GSM/WCDMA + the rest
- return IPC_NET_MODE_SEL_GSM_UMTS;
- }
-}
-
-int ipc2ril_plmn_sel(unsigned char mode)
-{
- switch (mode) {
- case IPC_NET_PLMN_SEL_MANUAL:
- return 1;
- case IPC_NET_PLMN_SEL_AUTO:
- return 0;
- default:
- return 0;
- }
-}
-
-unsigned char ril2ipc_plmn_sel(int mode)
-{
- switch (mode) {
- case 0:
- return IPC_NET_PLMN_SEL_AUTO;
- case 1:
- return IPC_NET_PLMN_SEL_MANUAL;
- default:
- return 0;
- }
-}
-
-void ipc2ril_reg_state_resp(struct ipc_net_regist_response *netinfo, char *response[15])
-{
- unsigned char reg_state;
- unsigned char act;
-
- if (netinfo == NULL || response == NULL)
- return;
-
- reg_state = ipc2ril_reg_state(netinfo->reg_state);
- act = ipc2ril_act(netinfo->act);
-
- memset(response, 0, sizeof(response));
-
- asprintf(&response[0], "%d", reg_state);
- asprintf(&response[1], "%x", netinfo->lac);
- asprintf(&response[2], "%x", netinfo->cid);
- asprintf(&response[3], "%d", act);
-}
-
-void ipc2ril_gprs_reg_state_resp(struct ipc_net_regist_response *netinfo, char *response[4])
-{
- unsigned char reg_state;
- unsigned char act;
-
- if (netinfo == NULL || response == NULL)
- return;
-
- reg_state = ipc2ril_reg_state(netinfo->reg_state);
- act = ipc2ril_gprs_act(netinfo->act);
-
- memset(response, 0, sizeof(response));
-
- asprintf(&response[0], "%d", reg_state);
- asprintf(&response[1], "%x", netinfo->lac);
- asprintf(&response[2], "%x", netinfo->cid);
- asprintf(&response[3], "%d", act);
-}
-
-/*
- * Set all the tokens to data waiting.
- * For instance when only operator is updated by modem NOTI, we don't need
- * to ask the modem new NET Regist and GPRS Net Regist states so act like we got
- * these from modem NOTI too so we don't have to make the requests
- */
-void ril_tokens_net_set_data_waiting(void)
-{
- ril_data.tokens.registration_state = RIL_TOKEN_DATA_WAITING;
- ril_data.tokens.gprs_registration_state = RIL_TOKEN_DATA_WAITING;
- ril_data.tokens.operator = RIL_TOKEN_DATA_WAITING;
-}
-
-/*
- * Returns 1 if unsol data is waiting, 0 if not
- */
-int ril_tokens_net_get_data_waiting(void)
-{
- return ril_data.tokens.registration_state == RIL_TOKEN_DATA_WAITING || ril_data.tokens.gprs_registration_state == RIL_TOKEN_DATA_WAITING || ril_data.tokens.operator == RIL_TOKEN_DATA_WAITING;
-}
-
-void ril_tokens_net_state_dump(void)
-{
- RIL_LOGD("ril_tokens_net_state_dump:\n\
- \tril_data.tokens.registration_state = %p\n\
- \tril_data.tokens.gprs_registration_state = %p\n\
- \tril_data.tokens.operator = %p\n", ril_data.tokens.registration_state, ril_data.tokens.gprs_registration_state, ril_data.tokens.operator);
-}
-
-void ril_plmn_split(char *plmn_data, char **plmn, unsigned int *mcc, unsigned int *mnc)
-{
- char plmn_t[7];
- int i;
-
- memset(plmn_t, 0, sizeof(plmn_t));
- memcpy(plmn_t, plmn_data, 6);
-
- if (plmn_t[5] == '#')
- plmn_t[5] = '\0';
-
- if (plmn != NULL) {
- *plmn = malloc(sizeof(plmn_t));
- memcpy(*plmn, plmn_t, sizeof(plmn_t));
- }
-
- if (mcc == NULL || mnc == NULL)
- return;
-
- sscanf(plmn_t, "%3u%2u", mcc, mnc);
-}
-
-void ril_plmn_string(char *plmn_data, char *response[3])
-{
- unsigned int mcc, mnc;
- char *plmn = NULL;
-
- int plmn_entries;
- int i;
-
- if (plmn_data == NULL || response == NULL)
- return;
-
- ril_plmn_split(plmn_data, &plmn, &mcc, &mnc);
-
- asprintf(&response[2], "%s", plmn);
-
- if (plmn != NULL)
- free(plmn);
-
- plmn_entries = sizeof(plmn_list) / sizeof(struct plmn_list_entry);
-
- RIL_LOGD("Found %d plmn records", plmn_entries);
-
- for (i = 0 ; i < plmn_entries ; i++) {
- if (plmn_list[i].mcc == mcc && plmn_list[i].mnc == mnc) {
- asprintf(&response[0], "%s", plmn_list[i].operator_long);
- asprintf(&response[1], "%s", plmn_list[i].operator_short);
- return;
- }
- }
-
- response[0] = NULL;
- response[1] = NULL;
-}
-
-/*
- * How to handle NET unsol data from modem:
- * 1- Rx UNSOL (NOTI) data from modem
- * 2- copy data in a sized variable stored in radio
- * 3- make sure no SOL request is going on for this token
- * 4- copy data to radio structure
- * 5- if no UNSOL data is already waiting for a token, tell RILJ NETWORK_STATE_CHANGED
- * 6- set all the net tokens to RIL_TOKEN_DATA_WAITING
- * 7- RILJ will ask for OPERATOR, GPRS_REG_STATE and REG_STATE
- * for each request:
- * 8- if token is RIL_TOKEN_DATA_WAITING it's SOL request for modem UNSOL data
- * 9- send back modem data and tell E_SUCCESS to RILJ request
- * 10- set token to 0x00
- *
- * How to handle NET sol requests from RILJ:
- * 1- if token is 0x00 it's UNSOL RILJ request for modem data
- * 2- put RIL_Token in token
- * 3- request data to the modem
- * 4- Rx SOL (RESP) data from modem
- * 5- copy data to radio structure
- * 6- send back data to RILJ with token from modem message
- * 7- if token != RIL_TOKEN_DATA_WAITING, reset token to 0x00
- *
- * What if both are appening at the same time?
- * 1- RILJ requests modem data (UNSOL)
- * 2- token is 0x00 so send request to modem
- * 3- UNSOL data arrives from modem
- * 4- set all tokens to RIL_TOKEN_DATA_WAITING
- * 5- store data, tell RILJ NETWORK_STATE_CHANGED
- * 6- Rx requested data from modem
- * 7- copy data to radio structure
- * 8- token mismatch (is now RIL_TOKEN_DATA_WAITING)
- * 9- send back data to RIL with token from IPC message
- * 10- don't reset token to 0x00
- * 11- RILJ does SOL request for modem data (we know it's SOL because we didn't reset token)
- * 12- send back last data we have (from UNSOL RILJ request here)
- */
-
-void ril_request_operator(RIL_Token t)
-{
- char *response[3];
- size_t i;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- // IPC_NET_REGISTRATION_STATE_ROAMING is the biggest valid value
- if (ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_NONE ||
- ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_SEARCHING ||
- ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_UNKNOWN ||
- ril_data.state.netinfo.reg_state > IPC_NET_REGISTRATION_STATE_ROAMING) {
- ril_request_complete(t, RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW, NULL, 0);
-
- ril_data.tokens.operator = RIL_TOKEN_NULL;
- return;
- }
-
- if (ril_data.tokens.operator == RIL_TOKEN_DATA_WAITING) {
- RIL_LOGD("Got RILJ request for UNSOL data");
-
- /* Send back the data we got UNSOL */
- ril_plmn_string(ril_data.state.plmndata.plmn, response);
-
- ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
- if (response[i] != NULL)
- free(response[i]);
- }
-
- ril_data.tokens.operator = RIL_TOKEN_NULL;
- } else if (ril_data.tokens.operator == RIL_TOKEN_NULL) {
- RIL_LOGD("Got RILJ request for SOL data");
- /* Request data to the modem */
- ril_data.tokens.operator = t;
-
- ipc_fmt_send_get(IPC_NET_CURRENT_PLMN, ril_request_get_id(t));
- } else {
- RIL_LOGE("Another request is going on, returning UNSOL data");
-
- /* Send back the data we got UNSOL */
- ril_plmn_string(ril_data.state.plmndata.plmn, response);
-
- ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
- if (response[i] != NULL)
- free(response[i]);
- }
- }
-
- ril_tokens_net_state_dump();
-}
-
-void ipc_net_current_plmn(struct ipc_message_info *info)
-{
- struct ipc_net_current_plmn_response *plmndata;
- RIL_Token t;
-
- char *response[3];
- size_t i;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_net_current_plmn_response))
- goto error;
-
- plmndata = (struct ipc_net_current_plmn_response *) info->data;
- t = ril_request_get_token(info->aseq);
-
- switch (info->type) {
- case IPC_TYPE_NOTI:
- RIL_LOGD("Got UNSOL Operator message");
-
- // IPC_NET_REGISTRATION_STATE_ROAMING is the biggest valid value
- if (ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_NONE ||
- ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_SEARCHING ||
- ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_UNKNOWN ||
- ril_data.state.netinfo.reg_state > IPC_NET_REGISTRATION_STATE_ROAMING) {
- /* Better keeping it up to date */
- memcpy(&(ril_data.state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn_response));
-
- return;
- } else {
- if (ril_data.tokens.operator != RIL_TOKEN_NULL && ril_data.tokens.operator != RIL_TOKEN_DATA_WAITING) {
- RIL_LOGE("Another Operator Req is in progress, skipping");
- return;
- }
-
- memcpy(&(ril_data.state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn_response));
-
- /* we already told RILJ to get the new data but it wasn't done yet */
- if (ril_tokens_net_get_data_waiting() && ril_data.tokens.operator == RIL_TOKEN_DATA_WAITING) {
- RIL_LOGD("Updating Operator data in background");
- } else {
- ril_tokens_net_set_data_waiting();
-#if RIL_VERSION >= 6
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
-#else
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
-#endif
- }
- }
- break;
- case IPC_TYPE_RESP:
- RIL_LOGD("Got SOL Operator message");
-
- // IPC_NET_REGISTRATION_STATE_ROAMING is the biggest valid value
- if (ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_NONE ||
- ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_SEARCHING ||
- ril_data.state.netinfo.reg_state == IPC_NET_REGISTRATION_STATE_UNKNOWN ||
- ril_data.state.netinfo.reg_state > IPC_NET_REGISTRATION_STATE_ROAMING) {
- /* Better keeping it up to date */
- memcpy(&(ril_data.state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn_response));
-
- ril_request_complete(t, RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW, NULL, 0);
-
- if (ril_data.tokens.operator != RIL_TOKEN_DATA_WAITING)
- ril_data.tokens.operator = RIL_TOKEN_NULL;
- return;
- } else {
- if (ril_data.tokens.operator != t)
- RIL_LOGE("Operator tokens mismatch");
-
- /* Better keeping it up to date */
- memcpy(&(ril_data.state.plmndata), plmndata, sizeof(struct ipc_net_current_plmn_response));
-
- ril_plmn_string(plmndata->plmn, response);
-
- ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
- if (response[i] != NULL)
- free(response[i]);
- }
-
- if (ril_data.tokens.operator != RIL_TOKEN_DATA_WAITING)
- ril_data.tokens.operator = RIL_TOKEN_NULL;
- }
- break;
- default:
- RIL_LOGE("%s: unhandled ipc method: %d", __func__, info->type);
- break;
- }
-
- ril_tokens_net_state_dump();
-
- return;
-
-error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-#if RIL_VERSION >= 6
-void ril_request_voice_registration_state(RIL_Token t)
-#else
-void ril_request_registration_state(RIL_Token t)
-#endif
-{
- struct ipc_net_regist_get regist_req;
- char *response[4];
- int i;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- if (ril_data.tokens.registration_state == RIL_TOKEN_DATA_WAITING) {
- RIL_LOGD("Got RILJ request for UNSOL data");
-
- /* Send back the data we got UNSOL */
- ipc2ril_reg_state_resp(&(ril_data.state.netinfo), response);
-
- ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- for (i = 0; i < (int) (sizeof(response) / sizeof(char *)) ; i++) {
- if (response[i] != NULL)
- free(response[i]);
- }
-
- ril_data.tokens.registration_state = RIL_TOKEN_NULL;
- } else if (ril_data.tokens.registration_state == RIL_TOKEN_NULL) {
- RIL_LOGD("Got RILJ request for SOL data");
- /* Request data to the modem */
- ril_data.tokens.registration_state = t;
-
- ipc_net_regist_get_setup(&regist_req, IPC_NET_SERVICE_DOMAIN_GSM);
- ipc_fmt_send(IPC_NET_REGIST, IPC_TYPE_GET, (void *)&regist_req, sizeof(struct ipc_net_regist_get), ril_request_get_id(t));
- } else {
- RIL_LOGE("Another request is going on, returning UNSOL data");
-
- /* Send back the data we got UNSOL */
- ipc2ril_reg_state_resp(&(ril_data.state.netinfo), response);
-
- ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- for (i = 0; i < (int) (sizeof(response) / sizeof(char *)) ; i++) {
- if (response[i] != NULL)
- free(response[i]);
- }
- }
-
- ril_tokens_net_state_dump();
-}
-
-#if RIL_VERSION >= 6
-void ril_request_data_registration_state(RIL_Token t)
-#else
-void ril_request_gprs_registration_state(RIL_Token t)
-#endif
-{
- struct ipc_net_regist_get regist_req;
- char *response[4];
- size_t i;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- if (ril_data.tokens.gprs_registration_state == RIL_TOKEN_DATA_WAITING) {
- RIL_LOGD("Got RILJ request for UNSOL data");
-
- /* Send back the data we got UNSOL */
- ipc2ril_gprs_reg_state_resp(&(ril_data.state.gprs_netinfo), response);
-
- ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
- if (response[i] != NULL)
- free(response[i]);
- }
-
- ril_data.tokens.gprs_registration_state = RIL_TOKEN_NULL;
- } else if (ril_data.tokens.gprs_registration_state == RIL_TOKEN_NULL) {
- RIL_LOGD("Got RILJ request for SOL data");
-
- /* Request data to the modem */
- ril_data.tokens.gprs_registration_state = t;
-
- ipc_net_regist_get_setup(&regist_req, IPC_NET_SERVICE_DOMAIN_GPRS);
- ipc_fmt_send(IPC_NET_REGIST, IPC_TYPE_GET, (void *)&regist_req, sizeof(struct ipc_net_regist_get), ril_request_get_id(t));
- } else {
- RIL_LOGE("Another request is going on, returning UNSOL data");
-
- /* Send back the data we got UNSOL */
- ipc2ril_gprs_reg_state_resp(&(ril_data.state.gprs_netinfo), response);
-
- ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
- if (response[i] != NULL)
- free(response[i]);
- }
- }
-
- ril_tokens_net_state_dump();
-}
-
-void ipc_net_regist_unsol(struct ipc_message_info *info)
-{
- struct ipc_net_regist_response *netinfo;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_net_regist_response))
- goto error;
-
- netinfo = (struct ipc_net_regist_response *) info->data;
-
- RIL_LOGD("Got UNSOL NetRegist message");
-
- switch (netinfo->domain) {
- case IPC_NET_SERVICE_DOMAIN_GSM:
- if (ril_data.tokens.registration_state != RIL_TOKEN_NULL && ril_data.tokens.registration_state != RIL_TOKEN_DATA_WAITING) {
- RIL_LOGE("Another NetRegist Req is in progress, skipping");
- return;
- }
-
- memcpy(&(ril_data.state.netinfo), netinfo, sizeof(struct ipc_net_regist_response));
-
- /* we already told RILJ to get the new data but it wasn't done yet */
- if (ril_tokens_net_get_data_waiting() && ril_data.tokens.registration_state == RIL_TOKEN_DATA_WAITING) {
- RIL_LOGD("Updating NetRegist data in background");
- } else {
- ril_tokens_net_set_data_waiting();
-#if RIL_VERSION >= 6
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
-#else
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
-#endif
- }
- break;
-
- case IPC_NET_SERVICE_DOMAIN_GPRS:
- if (ril_data.tokens.gprs_registration_state != RIL_TOKEN_NULL && ril_data.tokens.gprs_registration_state != RIL_TOKEN_DATA_WAITING) {
- RIL_LOGE("Another GPRS NetRegist Req is in progress, skipping");
- return;
- }
-
- memcpy(&(ril_data.state.gprs_netinfo), netinfo, sizeof(struct ipc_net_regist_response));
-
- /* we already told RILJ to get the new data but it wasn't done yet */
- if (ril_tokens_net_get_data_waiting() && ril_data.tokens.gprs_registration_state == RIL_TOKEN_DATA_WAITING) {
- RIL_LOGD("Updating GPRSNetRegist data in background");
- } else {
- ril_tokens_net_set_data_waiting();
-#if RIL_VERSION >= 6
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
-#else
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
-#endif
- }
- break;
- default:
- RIL_LOGE("%s: unhandled service domain: %d", __func__, netinfo->domain);
- break;
- }
-
- ril_tokens_net_state_dump();
-
- return;
-
-error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_net_regist_sol(struct ipc_message_info *info)
-{
- struct ipc_net_regist_response *netinfo;
- RIL_Token t;
-
- char *response[4];
- size_t i;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_net_regist_response))
- goto error;
-
- netinfo = (struct ipc_net_regist_response *) info->data;
- t = ril_request_get_token(info->aseq);
-
- RIL_LOGD("Got SOL NetRegist message");
-
- switch (netinfo->domain) {
- case IPC_NET_SERVICE_DOMAIN_GSM:
- if (ril_data.tokens.registration_state != t)
- RIL_LOGE("Registration state tokens mismatch");
-
- /* Better keeping it up to date */
- memcpy(&(ril_data.state.netinfo), netinfo, sizeof(struct ipc_net_regist_response));
-
- ipc2ril_reg_state_resp(netinfo, response);
-
- ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
- if (response[i] != NULL)
- free(response[i]);
- }
-
- if (ril_data.tokens.registration_state != RIL_TOKEN_DATA_WAITING)
- ril_data.tokens.registration_state = RIL_TOKEN_NULL;
- break;
- case IPC_NET_SERVICE_DOMAIN_GPRS:
- if (ril_data.tokens.gprs_registration_state != t)
- RIL_LOGE("GPRS registration state tokens mismatch");
-
- /* Better keeping it up to date */
- memcpy(&(ril_data.state.gprs_netinfo), netinfo, sizeof(struct ipc_net_regist_response));
-
- ipc2ril_gprs_reg_state_resp(netinfo, response);
-
- ril_request_complete(t, RIL_E_SUCCESS, response, sizeof(response));
-
- for (i = 0; i < sizeof(response) / sizeof(char *) ; i++) {
- if (response[i] != NULL)
- free(response[i]);
- }
- if (ril_data.tokens.registration_state != RIL_TOKEN_DATA_WAITING)
- ril_data.tokens.gprs_registration_state = RIL_TOKEN_NULL;
- break;
- default:
- RIL_LOGE("%s: unhandled service domain: %d", __func__, netinfo->domain);
- break;
- }
-
- ril_tokens_net_state_dump();
-
- return;
-
-error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_net_regist(struct ipc_message_info *info)
-{
- if (info == NULL)
- return;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, RIL_TOKEN_NULL))
- return;
-
- switch (info->type) {
- case IPC_TYPE_NOTI:
- ipc_net_regist_unsol(info);
- break;
- case IPC_TYPE_RESP:
- ipc_net_regist_sol(info);
- break;
- default:
- RIL_LOGE("%s: unhandled ipc method: %d", __func__, info->type);
- break;
- }
-
-}
-
-void ril_request_query_available_networks(RIL_Token t)
-{
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- ipc_fmt_send_get(IPC_NET_PLMN_LIST, ril_request_get_id(t));
-}
-
-void ipc_net_plmn_list(struct ipc_message_info *info)
-{
- struct ipc_net_plmn_entries *entries_info;
- struct ipc_net_plmn_entry *entries;
-
- char **response;
- int length;
- int count;
-
- int index;
- int i;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_net_plmn_entries))
- goto error;
-
- entries_info = (struct ipc_net_plmn_entries *) info->data;
- entries = (struct ipc_net_plmn_entry *) (info->data + sizeof(struct ipc_net_plmn_entries));
-
- RIL_LOGD("Listed %d PLMNs\n", entries_info->num);
-
- length = sizeof(char *) * 4 * entries_info->num;
- response = (char **) calloc(1, length);
-
- count = 0;
- for (i = 0 ; i < entries_info->num ; i++) {
- // Assumed type for 'emergency only' PLMNs
- if (entries[i].type == 0x01)
- continue;
-
- index = count * 4;
- ril_plmn_string(entries[i].plmn, &response[index]);
-
- index = count * 4 + 3;
- switch (entries[i].status) {
- case IPC_NET_PLMN_STATUS_AVAILABLE:
- response[index] = strdup("available");
- break;
- case IPC_NET_PLMN_STATUS_CURRENT:
- response[index] = strdup("current");
- break;
- case IPC_NET_PLMN_STATUS_FORBIDDEN:
- response[index] = strdup("forbidden");
- break;
- default:
- response[index] = strdup("unknown");
- break;
- }
-
- count++;
- }
-
- length = sizeof(char *) * 4 * count;
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, response, length);
-
- for (i = 0 ; i < entries_info->num ; i++)
- if (response[i] != NULL)
- free(response[i]);
-
- free(response);
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_get_preferred_network_type(RIL_Token t)
-{
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- ipc_fmt_send_get(IPC_NET_MODE_SEL, ril_request_get_id(t));
-}
-
-void ril_request_set_preferred_network_type(RIL_Token t, void *data, size_t length)
-{
- int ril_mode;
- struct ipc_net_mode_sel mode_sel;
-
- if (data == NULL || length < (int) sizeof(int))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- ril_mode = *((int *) data);
-
- mode_sel.mode_sel = ril2ipc_mode_sel(ril_mode);
-
- ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_NET_MODE_SEL);
-
- ipc_fmt_send(IPC_NET_MODE_SEL, IPC_TYPE_SET, (unsigned char *) &mode_sel, sizeof(mode_sel), ril_request_get_id(t));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_net_mode_sel(struct ipc_message_info *info)
-{
- struct ipc_net_mode_sel *mode_sel;
- int ril_mode;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_net_mode_sel))
- goto error;
-
- mode_sel = (struct ipc_net_mode_sel *) info->data;
- ril_mode = ipc2ril_mode_sel(mode_sel->mode_sel);
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &ril_mode, sizeof(ril_mode));
-
- return;
-
-error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_query_network_selection_mode(RIL_Token t)
-{
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- ipc_fmt_send_get(IPC_NET_PLMN_SEL, ril_request_get_id(t));
-}
-
-void ipc_net_plmn_sel(struct ipc_message_info *info)
-{
- struct ipc_net_plmn_sel_get *plmn_sel;
- int ril_mode;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_net_plmn_sel_get))
- goto error;
-
- plmn_sel = (struct ipc_net_plmn_sel_get *) info->data;
- ril_mode = ipc2ril_plmn_sel(plmn_sel->plmn_sel);
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &ril_mode, sizeof(ril_mode));
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_net_plmn_sel_complete(struct ipc_message_info *info)
-{
- struct ipc_gen_phone_res *phone_res;
- int rc;
-
- phone_res = (struct ipc_gen_phone_res *) info->data;
-
- rc = ipc_gen_phone_res_check(phone_res);
- if (rc < 0) {
- if ((phone_res->code & 0x00ff) == 0x6f) {
- RIL_LOGE("Not authorized to register to this network!");
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_ILLEGAL_SIM_OR_ME, NULL, 0);
- } else {
- RIL_LOGE("There was an error during operator selection!");
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- }
- return;
- }
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0);
-}
-
-void ril_request_set_network_selection_automatic(RIL_Token t)
-{
- struct ipc_net_plmn_sel_set plmn_sel;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- ipc_net_plmn_sel_set_setup(&plmn_sel, IPC_NET_PLMN_SEL_AUTO, NULL, IPC_NET_ACCESS_TECHNOLOGY_UNKNOWN);
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_NET_PLMN_SEL, ipc_net_plmn_sel_complete);
-
- ipc_fmt_send(IPC_NET_PLMN_SEL, IPC_TYPE_SET, (unsigned char *) &plmn_sel, sizeof(plmn_sel), ril_request_get_id(t));
-}
-
-void ril_request_set_network_selection_manual(RIL_Token t, void *data, size_t length)
-{
- struct ipc_net_plmn_sel_set plmn_sel;
-
- if (data == NULL || length < (int) sizeof(char *))
- return;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- // FIXME: We always assume UMTS capability
- ipc_net_plmn_sel_set_setup(&plmn_sel, IPC_NET_PLMN_SEL_MANUAL, data, IPC_NET_ACCESS_TECHNOLOGY_UMTS);
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_NET_PLMN_SEL, ipc_net_plmn_sel_complete);
-
- ipc_fmt_send(IPC_NET_PLMN_SEL, IPC_TYPE_SET, (unsigned char *) &plmn_sel, sizeof(plmn_sel), ril_request_get_id(t));
-}
diff --git a/network.c b/network.c
new file mode 100644
index 0000000..6c70774
--- /dev/null
+++ b/network.c
@@ -0,0 +1,1168 @@
+/*
+ * This file is part of Samsung-RIL.
+ *
+ * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
+ * Copyright (C) 2011-2014 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * Based on the CyanogenMod Smdk4210RIL implementation:
+ * Copyright (C) 2011 The CyanogenMod Project
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Samsung-RIL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
+
+#include <samsung-ril.h>
+#include <utils.h>
+#include <plmn_list.h>
+
+#if RIL_VERSION >= 6
+int ipc2ril_disp_rssi(unsigned char rssi, RIL_SignalStrength_v6 *strength)
+#else
+int ipc2ril_disp_rssi(unsigned char rssi, RIL_SignalStrength *strength)
+#endif
+{
+ int asu;
+
+ if (strength == NULL)
+ return -1;
+
+#if RIL_VERSION >= 6
+ memset(strength, -1, sizeof(RIL_SignalStrength_v6));
+#else
+ memset(strength, -1, sizeof(RIL_SignalStrength));
+#endif
+
+ asu = (int) rssi / -2 + 56;
+
+ if (asu < 0)
+ asu = 0;
+ else if (asu > 31)
+ asu = 31;
+
+ strength->GW_SignalStrength.signalStrength = asu;
+ strength->GW_SignalStrength.bitErrorRate = 99;
+
+ RIL_LOGD("Signal strength is %d", strength->GW_SignalStrength.signalStrength);
+
+ return 0;
+}
+
+#if RIL_VERSION >= 6
+int ipc2ril_disp_icon_info(struct ipc_disp_icon_info_response_data *data,
+ RIL_SignalStrength_v6 *strength)
+#else
+int ipc2ril_disp_icon_info(struct ipc_disp_icon_info_response_data *data,
+ RIL_SignalStrength *strength)
+#endif
+{
+ int asu_bars[] = { 1, 3, 5, 8, 12, 15 };
+ unsigned int asu_bars_count = sizeof(asu_bars) / sizeof(int);
+ unsigned char asu_bars_index;
+ int rc;
+
+ if (data == NULL || strength == NULL)
+ return -1;
+
+ if (!(data->flags & IPC_DISP_ICON_INFO_FLAG_RSSI))
+ return -1;
+
+#if RIL_VERSION >= 6
+ memset(strength, -1, sizeof(RIL_SignalStrength_v6));
+#else
+ memset(strength, -1, sizeof(RIL_SignalStrength));
+#endif
+
+ asu_bars_index = data->rssi;
+ if (asu_bars_index >= asu_bars_count)
+ asu_bars_index = asu_bars_count - 1;
+
+ strength->GW_SignalStrength.signalStrength = asu_bars[asu_bars_index];
+
+ strength->GW_SignalStrength.bitErrorRate = 99;
+
+ RIL_LOGD("Signal strength is %d", strength->GW_SignalStrength.signalStrength);
+
+ return 0;
+}
+
+#if RIL_VERSION >= 6
+int ipc2ril_disp_rssi_info(struct ipc_disp_rssi_info_data *data,
+ RIL_SignalStrength_v6 *strength)
+#else
+int ipc2ril_disp_rssi_info(struct ipc_disp_rssi_info_data *data,
+ RIL_SignalStrength *strength)
+#endif
+{
+ int rc;
+
+ if (data == NULL)
+ return -1;
+
+ rc = ipc2ril_disp_rssi(data->rssi, strength);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int ipc2ril_net_plmn_sel(struct ipc_net_plmn_sel_response_data *data)
+{
+ if (data == NULL)
+ return -1;
+
+ switch (data->plmn_sel) {
+ case IPC_NET_PLMN_SEL_AUTO:
+ return 0;
+ case IPC_NET_PLMN_SEL_MANUAL:
+ return 1;
+ default:
+ return -1;
+ }
+}
+
+int ipc2ril_net_regist_response(struct ipc_net_regist_response_data *data,
+ unsigned char hsdpa_status, char **registration,
+ size_t registration_size)
+{
+#if RIL_VERSION >= 6
+ RIL_RadioTechnology act;
+#else
+ int act;
+#endif
+ unsigned char status;
+
+ if (data == NULL || registration == NULL)
+ return -1;
+
+ memset(registration, 0, registration_size);
+
+#if RIL_VERSION >= 6
+ switch (data->act) {
+ case IPC_NET_ACCESS_TECHNOLOGY_GSM:
+ case IPC_NET_ACCESS_TECHNOLOGY_GSM2:
+#if RIL_VERSION >= 7
+ act = RADIO_TECH_GSM;
+#else
+ act = RADIO_TECH_UNKNOWN;
+#endif
+ break;
+ case IPC_NET_ACCESS_TECHNOLOGY_GPRS:
+ act = RADIO_TECH_GPRS;
+ break;
+ case IPC_NET_ACCESS_TECHNOLOGY_EDGE:
+ act = RADIO_TECH_EDGE;
+ break;
+ case IPC_NET_ACCESS_TECHNOLOGY_UMTS:
+ switch (hsdpa_status) {
+ case IPC_GPRS_HSDPA_STATUS_HSDPA:
+ act = RADIO_TECH_HSDPA;
+ break;
+ case IPC_GPRS_HSDPA_STATUS_HSPAP:
+ act = RADIO_TECH_HSPAP;
+ break;
+ default:
+ act = RADIO_TECH_UMTS;
+ break;
+ }
+ break;
+ default:
+ act = RADIO_TECH_UNKNOWN;
+ break;
+ }
+#else
+ switch (data->act) {
+ case IPC_NET_ACCESS_TECHNOLOGY_GSM:
+ case IPC_NET_ACCESS_TECHNOLOGY_GSM2:
+ act = 0;
+ break;
+ case IPC_NET_ACCESS_TECHNOLOGY_GPRS:
+ act = 1;
+ break;
+ case IPC_NET_ACCESS_TECHNOLOGY_EDGE:
+ act = 2;
+ break;
+ case IPC_NET_ACCESS_TECHNOLOGY_UMTS:
+ switch (hsdpa_status) {
+ case IPC_GPRS_HSDPA_STATUS_HSDPA:
+ case IPC_GPRS_HSDPA_STATUS_HSPAP:
+ act = 9;
+ break;
+ default:
+ act = 3;
+ break;
+ }
+ break;
+ default:
+ act = 0;
+ break;
+ }
+#endif
+
+ switch (data->status) {
+ case IPC_NET_REGISTRATION_STATUS_NONE:
+ status = 0;
+ break;
+ case IPC_NET_REGISTRATION_STATUS_HOME:
+ status = 1;
+ break;
+ case IPC_NET_REGISTRATION_STATUS_SEARCHING:
+ status = 2;
+ break;
+ case IPC_NET_REGISTRATION_STATUS_EMERGENCY:
+ status = 10;
+ break;
+ case IPC_NET_REGISTRATION_STATUS_UNKNOWN:
+ status = 4;
+ break;
+ case IPC_NET_REGISTRATION_STATUS_ROAMING:
+ status = 5;
+ break;
+ default:
+ status = 0;
+ break;
+ }
+
+ asprintf(&registration[0], "%d", status);
+ asprintf(&registration[1], "%x", data->lac);
+ asprintf(&registration[2], "%x", data->cid);
+ asprintf(&registration[3], "%d", act);
+
+ return 0;
+}
+
+int ipc2ril_net_operator(char *data, size_t size, char **plmn,
+ char **operator_long, char **operator_short)
+{
+ char buffer[7] = { 0 };
+ unsigned int mcc = 0;
+ unsigned int mnc = 0;
+ unsigned int count;
+ unsigned int i;
+ int rc;
+
+ if (data == NULL || size == 0 || plmn == NULL)
+ return -1;
+
+ *plmn = NULL;
+
+ count = size / sizeof(char);
+
+ for (i = 0; i < count; i++) {
+ if (!isdigit(data[i])) {
+ buffer[i] = '\0';
+ break;
+ }
+
+ buffer[i] = data[i];
+ }
+
+ if (buffer[0] == '\0')
+ goto error;
+
+ *plmn = strdup(buffer);
+
+ if (operator_long == NULL || operator_short == NULL) {
+ rc = 0;
+ goto complete;
+ }
+
+ *operator_long = NULL;
+ *operator_short = NULL;
+
+ rc = sscanf((char *) &buffer, "%3u%2u", &mcc, &mnc);
+ if (rc < 2)
+ goto error;
+
+ for (i = 0 ; i < plmn_list_count ; i++) {
+ if (plmn_list[i].mcc == mcc && plmn_list[i].mnc == mnc) {
+ *operator_long = strdup(plmn_list[i].operator_long);
+ *operator_short = strdup(plmn_list[i].operator_short);
+ }
+ }
+
+ if (*operator_long == NULL || *operator_short == NULL) {
+ RIL_LOGE("%s: Finding operator with PLMN %d%d failed", __func__, mcc, mnc);
+ goto error;
+ }
+
+ rc = 0;
+ goto complete;
+
+error:
+ if (*plmn != NULL) {
+ free(*plmn);
+ *plmn = NULL;
+ }
+
+ if (operator_long != NULL && *operator_long != NULL) {
+ free(*operator_long);
+ *operator_long = NULL;
+ }
+
+ if (operator_short != NULL && *operator_short != NULL) {
+ free(*operator_short);
+ *operator_short = NULL;
+ }
+
+ rc = -1;
+
+complete:
+ return rc;
+}
+
+int ipc2ril_net_serving_network(struct ipc_net_serving_network_data *data,
+ char **operator)
+{
+ int rc;
+
+ if (operator == NULL)
+ return -1;
+
+ rc = ipc2ril_net_operator((char *) &data->plmn, sizeof(data->plmn), &operator[2], &operator[0], &operator[1]);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+#if RIL_VERSION >= 6
+RIL_PreferredNetworkType ipc2ril_net_mode_sel(struct ipc_net_mode_sel_data *data)
+#else
+int ipc2ril_net_mode_sel(struct ipc_net_mode_sel_data *data)
+#endif
+{
+ if (data == NULL)
+ return -1;
+
+#if RIL_VERSION >= 6
+ switch (data->mode_sel) {
+ case IPC_NET_MODE_SEL_GSM_UMTS:
+ return PREF_NET_TYPE_GSM_WCDMA;
+ case IPC_NET_MODE_SEL_GSM_ONLY:
+ return PREF_NET_TYPE_GSM_ONLY;
+ case IPC_NET_MODE_SEL_UMTS_ONLY:
+ return PREF_NET_TYPE_WCDMA;
+ default:
+ return -1;
+ }
+#else
+ switch (data->mode_sel) {
+ case IPC_NET_MODE_SEL_GSM_UMTS:
+ return 0;
+ case IPC_NET_MODE_SEL_GSM_ONLY:
+ return 1;
+ case IPC_NET_MODE_SEL_UMTS_ONLY:
+ return 2;
+ default:
+ return -1;
+ }
+#endif
+}
+
+#if RIL_VERSION >= 6
+unsigned char ril2ipc_net_mode_sel(RIL_PreferredNetworkType type)
+#else
+unsigned char ril2ipc_net_mode_sel(int type)
+#endif
+{
+#if RIL_VERSION >= 6
+ switch (type) {
+ case PREF_NET_TYPE_GSM_WCDMA:
+ case PREF_NET_TYPE_GSM_WCDMA_AUTO:
+ return IPC_NET_MODE_SEL_GSM_UMTS;
+ case PREF_NET_TYPE_GSM_ONLY:
+ return IPC_NET_MODE_SEL_GSM_ONLY;
+ case PREF_NET_TYPE_WCDMA:
+ return IPC_NET_MODE_SEL_UMTS_ONLY;
+ default:
+ return IPC_NET_MODE_SEL_GSM_UMTS;
+ }
+#else
+ switch (type) {
+ case 0:
+ case 3:
+ return IPC_NET_MODE_SEL_GSM_UMTS;
+ case 1:
+ return IPC_NET_MODE_SEL_GSM_ONLY;
+ case 2:
+ return IPC_NET_MODE_SEL_UMTS_ONLY;
+ default:
+ return IPC_NET_MODE_SEL_GSM_UMTS;
+ }
+#endif
+}
+
+int ipc_disp_icon_info(struct ipc_message *message)
+{
+ struct ipc_disp_icon_info_response_data *data;
+#if RIL_VERSION >= 6
+ RIL_SignalStrength_v6 strength;
+#else
+ RIL_SignalStrength strength;
+#endif
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_disp_icon_info_response_data))
+ return -1;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ data = (struct ipc_disp_icon_info_response_data *) message->data;
+
+ rc = ipc2ril_disp_icon_info(data, &strength);
+ if (rc < 0) {
+ if (message->type == IPC_TYPE_RESP && ipc_seq_valid(message->aseq))
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ return 0;
+ }
+
+ if (message->type == IPC_TYPE_RESP && ipc_seq_valid(message->aseq))
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &strength, sizeof(strength));
+ else
+ ril_request_unsolicited(RIL_UNSOL_SIGNAL_STRENGTH, (void *) &strength, sizeof(strength));
+
+ return 0;
+}
+
+int ril_request_signal_strength(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_disp_icon_info_request_data request_data;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ memset(&request_data, 0, sizeof(request_data));
+ request_data.flags = IPC_DISP_ICON_INFO_FLAG_RSSI;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_DISP_ICON_INFO, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ return RIL_REQUEST_HANDLED;
+}
+
+int ipc_disp_rssi_info(struct ipc_message *message)
+{
+ struct ipc_disp_rssi_info_data *data;
+#if RIL_VERSION >= 6
+ RIL_SignalStrength_v6 strength;
+#else
+ RIL_SignalStrength strength;
+#endif
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_disp_rssi_info_data))
+ return -1;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ data = (struct ipc_disp_rssi_info_data *) message->data;
+
+ rc = ipc2ril_disp_rssi_info(data, &strength);
+ if (rc < 0)
+ return 0;
+
+ ril_request_unsolicited(RIL_UNSOL_SIGNAL_STRENGTH, (void *) &strength, sizeof(strength));
+
+ return 0;
+}
+
+int ipc_net_plmn_sel(struct ipc_message *message)
+{
+ struct ipc_net_plmn_sel_response_data *data;
+ int selection;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_net_plmn_sel_response_data))
+ return -1;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
+
+ data = (struct ipc_net_plmn_sel_response_data *) message->data;
+
+ selection = ipc2ril_net_plmn_sel(data);
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &selection, sizeof(selection));
+
+ return 0;
+}
+
+int ril_request_query_network_selection_mode(void *data, size_t size,
+ RIL_Token token)
+{
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_NET_PLMN_SEL, IPC_TYPE_GET, NULL, 0);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ return RIL_REQUEST_HANDLED;
+}
+
+int ipc_net_plmn_sel_callback(struct ipc_message *message)
+{
+ struct ipc_gen_phone_res_data *data;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data))
+ return -1;
+
+ data = (struct ipc_gen_phone_res_data *) message->data;
+
+ rc = ipc_gen_phone_res_check(data);
+ if (rc < 0) {
+ if ((data->code & 0xff) == 0x6f) {
+ RIL_LOGE("%s: Unauthorized network selection", __func__);
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_ILLEGAL_SIM_OR_ME, NULL, 0);
+ } else {
+ RIL_LOGE("%s: Network selection failed", __func__);
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ }
+ } else {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0);
+ }
+
+ return 0;
+}
+
+int ril_request_set_network_selection_automatic(void *data, size_t size,
+ RIL_Token token)
+{
+ struct ipc_net_plmn_sel_request_data request_data;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ rc = ipc_net_plmn_sel_setup(&request_data, IPC_NET_PLMN_SEL_AUTO, NULL, IPC_NET_ACCESS_TECHNOLOGY_UNKNOWN);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_NET_PLMN_SEL, ipc_net_plmn_sel_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_NET_PLMN_SEL, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ril_request_set_network_selection_manual(void *data, size_t size,
+ RIL_Token token)
+{
+ struct ipc_net_plmn_sel_request_data request_data;
+ int rc;
+
+ if (data == NULL || size < sizeof(char)) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ rc = ipc_net_plmn_sel_setup(&request_data, IPC_NET_PLMN_SEL_MANUAL, (const char *) data, IPC_NET_ACCESS_TECHNOLOGY_UNKNOWN);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_NET_PLMN_SEL, ipc_net_plmn_sel_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_NET_PLMN_SEL, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ipc_net_serving_network(struct ipc_message *message)
+{
+ struct ipc_net_serving_network_data *data;
+ char *operator[3] = { NULL };
+ unsigned char count;
+ unsigned int i;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_net_regist_response_data))
+ return -1;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ data = (struct ipc_net_serving_network_data *) message->data;
+
+ rc = ipc2ril_net_serving_network(data, (char **) &operator);
+ if (rc < 0) {
+ if (message->type == IPC_TYPE_RESP && ipc_seq_valid(message->aseq))
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ return 0;
+ }
+
+ count = sizeof(operator) / sizeof(char *);
+
+ if (message->type == IPC_TYPE_RESP && ipc_seq_valid(message->aseq)) {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &operator, sizeof(operator));
+
+ for (i = 0; i < count; i++) {
+ if (operator[i] != NULL)
+ free(operator[i]);
+ }
+ } else {
+ ril_request_data_set(RIL_REQUEST_OPERATOR, (void *) operator, sizeof(operator));
+#if RIL_VERSION >= 6
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
+#else
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
+#endif
+ }
+
+ return 0;
+}
+
+int ril_request_operator(void *data, size_t size, RIL_Token token)
+{
+ struct ril_request *request;
+ void *operator_data;
+ size_t operator_size;
+ char **operator;
+ unsigned char count;
+ unsigned int i;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_OPERATOR, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ operator_size = ril_request_data_size_get(RIL_REQUEST_OPERATOR);
+ operator_data = ril_request_data_get(RIL_REQUEST_OPERATOR);
+
+ if (operator_data != NULL && operator_size > 0) {
+ ril_request_complete(token, RIL_E_SUCCESS, operator_data, operator_size);
+
+ count = operator_size / sizeof(char *);
+ operator = (char **) operator_data;
+
+ for (i = 0; i < count; i++) {
+ if (operator[i] != NULL)
+ free(operator[i]);
+ }
+
+ free(operator_data);
+
+ return RIL_REQUEST_COMPLETED;
+ } else {
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_NET_SERVING_NETWORK, IPC_TYPE_GET, NULL, 0);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ return RIL_REQUEST_HANDLED;
+ }
+}
+
+int ipc_net_plmn_list(struct ipc_message *message)
+{
+ struct ipc_net_plmn_list_entry *entry;
+ char **networks = NULL;
+ size_t networks_size;
+ unsigned int networks_count = 0;
+ char **network;
+ unsigned char count;
+ unsigned char index;
+ unsigned int i;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_net_plmn_list_header))
+ return -1;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
+
+ count = ipc_net_plmn_list_count_extract(message->data, message->size);
+ if (count == 0) {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0);
+ return 0;
+ }
+
+ networks_size = count * 4 * sizeof(char *);
+ networks = calloc(1, networks_size);
+
+ for (index = 0; index < count; index++) {
+ entry = ipc_net_plmn_list_entry_extract(message->data, message->size, index);
+ if (entry == NULL)
+ goto error;
+
+ network = (char **) ((unsigned char *) networks + networks_count * 4 * sizeof(char *));
+
+ rc = ipc2ril_net_operator(entry->plmn, sizeof(entry->plmn), &network[2], &network[0], &network[1]);
+ if (rc < 0)
+ goto error;
+
+ switch (entry->status) {
+ case IPC_NET_PLMN_STATUS_AVAILABLE:
+ network[3] = strdup("available");
+ break;
+ case IPC_NET_PLMN_STATUS_CURRENT:
+ network[3] = strdup("current");
+ break;
+ case IPC_NET_PLMN_STATUS_FORBIDDEN:
+ network[3] = strdup("forbidden");
+ break;
+ default:
+ network[3] = strdup("unknown");
+ break;
+ }
+
+ networks_count++;
+ }
+
+ RIL_LOGD("Found %d available networks", networks_count);
+
+ networks_size = networks_count * 4 * sizeof(char *);
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) networks, networks_size);
+
+ goto complete;
+
+error:
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ if (networks != NULL && networks_size > 0) {
+ for (index = 0; index < networks_count; index++) {
+ if (networks[index] != NULL)
+ free(networks[index]);
+ }
+
+ free(networks);
+ }
+
+ return 0;
+}
+
+int ril_request_query_available_networks(void *data, size_t size,
+ RIL_Token token)
+{
+ struct ril_request *request;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_QUERY_AVAILABLE_NETWORKS, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_NET_PLMN_LIST, IPC_TYPE_GET, NULL, 0);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ return RIL_REQUEST_HANDLED;
+}
+
+int ipc_net_regist(struct ipc_message *message)
+{
+ struct ipc_net_regist_response_data *data;
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
+ struct ipc_client_gprs_capabilities gprs_capabilities;
+ char *voice_registration[15] = { NULL };
+ char *data_registration[5] = { NULL };
+ char **registration;
+ size_t registration_size;
+ unsigned int count;
+ unsigned int i;
+ int request;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_net_regist_response_data))
+ return -1;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ return 0;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ data = (struct ipc_net_regist_response_data *) message->data;
+
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+
+ if (data->domain == IPC_NET_SERVICE_DOMAIN_GSM) {
+#if RIL_VERSION >= 6
+ request = RIL_REQUEST_VOICE_REGISTRATION_STATE;
+#else
+ request = RIL_REQUEST_REGISTRATION_STATE;
+#endif
+
+ registration = (char **) &voice_registration;
+ registration_size = sizeof(voice_registration);
+ count = registration_size / sizeof(char *);
+ } else if (data->domain == IPC_NET_SERVICE_DOMAIN_GPRS) {
+#if RIL_VERSION >= 6
+ request = RIL_REQUEST_DATA_REGISTRATION_STATE;
+#else
+ request = RIL_REQUEST_GPRS_REGISTRATION_STATE;
+#endif
+
+ registration = (char **) &data_registration;
+ registration_size = sizeof(data_registration);
+ count = registration_size / sizeof(char *);
+ } else {
+ RIL_LOGD("%s: Invalid networking registration domain (0x%x)", __func__, data->domain);
+ return 0;
+ }
+
+ rc = ipc2ril_net_regist_response(data, ipc_fmt_data->hsdpa_status_data.status, registration, registration_size);
+ if (rc < 0)
+ goto error;
+
+ if (data->domain == IPC_NET_SERVICE_DOMAIN_GPRS) {
+ if (ipc_fmt_data->ipc_client == NULL)
+ goto error;
+
+ rc = ipc_client_gprs_get_capabilities(ipc_fmt_data->ipc_client, &gprs_capabilities);
+ if (rc < 0)
+ goto error;
+
+ asprintf(&registration[4], "%d", gprs_capabilities.cid_count);
+ }
+
+ if (message->type == IPC_TYPE_RESP && ipc_seq_valid(message->aseq)) {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) registration, registration_size);
+
+ for (i = 0; i < count; i++) {
+ if (registration[i] != NULL)
+ free(registration[i]);
+ }
+
+ return 0;
+ } else {
+ ril_request_data_set(request, (void *) registration, registration_size);
+
+#if RIL_VERSION >= 6
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
+#else
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED, NULL, 0);
+#endif
+ }
+
+ goto complete;
+
+error:
+ if (ipc_seq_valid(message->aseq))
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ for (i = 0; i < count; i++) {
+ if (registration[i] != NULL)
+ free(registration[i]);
+ }
+
+complete:
+ return 0;
+}
+
+#if RIL_VERSION >= 6
+int ril_request_voice_registration_state(void *data, size_t size,
+ RIL_Token token)
+#else
+int ril_request_registration_state(void *data, size_t size, RIL_Token token)
+#endif
+{
+ struct ipc_net_regist_request_data request_data;
+ struct ril_request *request;
+ void *registration_data;
+ size_t registration_size;
+ char **registration;
+ unsigned int count;
+ unsigned int i;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+#if RIL_VERSION >= 6
+ request = ril_request_find_request_status(RIL_REQUEST_VOICE_REGISTRATION_STATE, RIL_REQUEST_HANDLED);
+#else
+ request = ril_request_find_request_status(RIL_REQUEST_REGISTRATION_STATE, RIL_REQUEST_HANDLED);
+#endif
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+#if RIL_VERSION >= 6
+ registration_size = ril_request_data_size_get(RIL_REQUEST_VOICE_REGISTRATION_STATE);
+ registration_data = ril_request_data_get(RIL_REQUEST_VOICE_REGISTRATION_STATE);
+#else
+ registration_size = ril_request_data_size_get(RIL_REQUEST_REGISTRATION_STATE);
+ registration_data = ril_request_data_get(RIL_REQUEST_REGISTRATION_STATE);
+#endif
+ if (registration_data != NULL && registration_size > 0) {
+ ril_request_complete(token, RIL_E_SUCCESS, registration_data, registration_size);
+
+ count = registration_size / sizeof(char *);
+ registration = (char **) registration_data;
+
+ for (i = 0; i < count; i++) {
+ if (registration[i] != NULL)
+ free(registration[i]);
+ }
+
+ free(registration_data);
+
+ rc = RIL_REQUEST_COMPLETED;
+ } else {
+ rc = ipc_net_regist_setup(&request_data, IPC_NET_SERVICE_DOMAIN_GSM);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_NET_REGIST, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ }
+
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+#if RIL_VERSION >= 6
+int ril_request_data_registration_state(void *data, size_t size,
+ RIL_Token token)
+#else
+int ril_request_gprs_registration_state(void *data, size_t size,
+ RIL_Token token)
+#endif
+{
+ struct ipc_net_regist_request_data request_data;
+ struct ril_request *request;
+ void *registration_data;
+ size_t registration_size;
+ char **registration;
+ unsigned int count;
+ unsigned int i;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+#if RIL_VERSION >= 6
+ request = ril_request_find_request_status(RIL_REQUEST_DATA_REGISTRATION_STATE, RIL_REQUEST_HANDLED);
+#else
+ request = ril_request_find_request_status(RIL_REQUEST_GPRS_REGISTRATION_STATE, RIL_REQUEST_HANDLED);
+#endif
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+#if RIL_VERSION >= 6
+ registration_size = ril_request_data_size_get(RIL_REQUEST_DATA_REGISTRATION_STATE);
+ registration_data = ril_request_data_get(RIL_REQUEST_DATA_REGISTRATION_STATE);
+#else
+ registration_size = ril_request_data_size_get(RIL_REQUEST_GPRS_REGISTRATION_STATE);
+ registration_data = ril_request_data_get(RIL_REQUEST_GPRS_REGISTRATION_STATE);
+#endif
+ if (registration_data != NULL && registration_size > 0) {
+ ril_request_complete(token, RIL_E_SUCCESS, registration_data, registration_size);
+
+ count = registration_size / sizeof(char *);
+ registration = (char **) registration_data;
+
+ for (i = 0; i < count; i++) {
+ if (registration[i] != NULL)
+ free(registration[i]);
+ }
+
+ free(registration_data);
+
+ rc = RIL_REQUEST_COMPLETED;
+ } else {
+ rc = ipc_net_regist_setup(&request_data, IPC_NET_SERVICE_DOMAIN_GPRS);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_NET_REGIST, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ }
+
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ipc_net_mode_sel(struct ipc_message *message)
+{
+ struct ipc_net_mode_sel_data *data;
+ int type;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_net_mode_sel_data))
+ return -1;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
+
+ data = (struct ipc_net_mode_sel_data *) message->data;
+
+ type = ipc2ril_net_mode_sel(data);
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &type, sizeof(type));
+
+ return 0;
+}
+
+int ril_request_get_preferred_network_type(void *data, size_t size,
+ RIL_Token token)
+{
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_NET_MODE_SEL, IPC_TYPE_GET, NULL, 0);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ return RIL_REQUEST_HANDLED;
+}
+
+int ril_request_set_preferred_network_type(void *data, size_t size,
+ RIL_Token token)
+{
+ struct ipc_net_mode_sel_data request_data;
+ int type;
+ int rc;
+
+ if (data == NULL || size < sizeof(int))
+ goto error;
+
+ type = *((int *) data);
+
+ memset(&request_data, 0, sizeof(request_data));
+ request_data.mode_sel = ril2ipc_net_mode_sel(type);
+
+ if (request_data.mode_sel == 0) {
+ ril_request_complete(token, RIL_E_MODE_NOT_SUPPORTED, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+ goto complete;
+ }
+
+ rc = ipc_gen_phone_res_expect_complete(ipc_fmt_request_seq(token), IPC_NET_MODE_SEL);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_NET_MODE_SEL, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
diff --git a/oem.c b/oem.c
new file mode 100644
index 0000000..a5781c0
--- /dev/null
+++ b/oem.c
@@ -0,0 +1,238 @@
+/*
+ * This file is part of Samsung-RIL.
+ *
+ * Copyright (C) 2013-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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Samsung-RIL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
+
+#include <samsung-ril.h>
+#include <ril_oem.h>
+
+int ipc_svc_display_screen(struct ipc_message *message)
+{
+ struct ipc_svc_display_screen_entry *entry;
+ char svc_end_message[34] = " End service mode";
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
+ struct ril_request *request;
+ void *screen_data = NULL;
+ size_t screen_size = 0;
+ unsigned char count;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_svc_display_screen_header))
+ return -1;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ return 0;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+
+ count = ipc_svc_display_screen_count_extract(message->data, message->size);
+
+ if (count > 0) {
+ if (!ipc_fmt_data->svc_session)
+ ipc_fmt_data->svc_session = 1;
+
+ entry = ipc_svc_display_screen_extract(message->data, message->size, 0);
+ if (entry == NULL)
+ goto error;
+
+ // Invalid messages have bogus first entry index
+ if (entry->index != 0)
+ goto complete;
+
+ screen_size = count * sizeof(struct ipc_svc_display_screen_entry);
+ screen_data = (void *) entry;
+ } else {
+ if (ipc_fmt_data->svc_session)
+ ipc_fmt_data->svc_session = 0;
+
+ ril_request_data_free(RIL_REQUEST_OEM_HOOK_RAW);
+
+ screen_size = sizeof(svc_end_message);
+ screen_data = (void *) &svc_end_message;
+ }
+
+ request = ril_request_find_request_status(RIL_REQUEST_OEM_HOOK_RAW, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ ril_request_complete(request->token, RIL_E_SUCCESS, screen_data, screen_size);
+ else
+ ril_request_data_set_uniq(RIL_REQUEST_OEM_HOOK_RAW, screen_data, screen_size);
+
+ goto complete;
+
+error:
+ request = ril_request_find_request_status(RIL_REQUEST_OEM_HOOK_RAW, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ ril_request_complete(request->token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ return 0;
+}
+
+int ril_request_oem_hook_raw(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_svc_enter_data svc_enter_data;
+ struct ipc_svc_end_data svc_end_data;
+ struct ipc_svc_pro_keycode_data svc_pro_keycode_data;
+ RIL_OEMHookHeader *header;
+ RIL_OEMHookSvcEnterMode *svc_enter_mode;
+ RIL_OEMHookSvcEndMode *svc_end_mode;
+ RIL_OEMHookSvcKey *svc_key;
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
+ struct ril_request *request;
+ void *screen_data = NULL;
+ size_t screen_size = 0;
+ unsigned int length;
+ int rc;
+
+ if (data == NULL || size < sizeof(RIL_OEMHookHeader))
+ goto error;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_OEM_HOOK_RAW, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+
+ header = (RIL_OEMHookHeader *) data;
+
+ // Only SVC is supported
+ if (header->tag != RIL_OEM_HOOK_TAG_SVC)
+ goto error;
+
+ length = size - sizeof(RIL_OEMHookHeader);
+
+ switch (header->command) {
+ case RIL_OEM_COMMAND_SVC_ENTER_MODE:
+ if (length < sizeof(RIL_OEMHookSvcEnterMode))
+ goto error;
+
+ svc_enter_mode = (RIL_OEMHookSvcEnterMode *) ((unsigned char *) data + sizeof(RIL_OEMHookHeader));
+
+ if (svc_enter_mode->query) {
+ screen_size = ril_request_data_size_get(RIL_REQUEST_OEM_HOOK_RAW);
+ screen_data = ril_request_data_get(RIL_REQUEST_OEM_HOOK_RAW);
+
+ ril_request_complete(token, RIL_E_SUCCESS, screen_data, screen_size);
+
+ rc = RIL_REQUEST_COMPLETED;
+ goto complete;
+ } else {
+ rc = ipc_svc_enter_setup(&svc_enter_data, svc_enter_mode->mode, svc_enter_mode->type);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_SVC_ENTER);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SVC_ENTER, IPC_TYPE_SET, (void *) &svc_enter_data, sizeof(svc_enter_data));
+ if (rc < 0)
+ goto error;
+ }
+ break;
+ case RIL_OEM_COMMAND_SVC_END_MODE:
+ if (length < sizeof(RIL_OEMHookSvcEndMode))
+ goto error;
+
+ svc_end_mode = (RIL_OEMHookSvcEndMode *) ((unsigned char *) data + sizeof(RIL_OEMHookHeader));
+
+ memset(&svc_end_data, 0, sizeof(svc_end_data));
+ svc_end_data.mode = svc_end_mode->mode;
+
+ rc = ipc_gen_phone_res_expect_complete(ipc_fmt_request_seq(token), IPC_SVC_END);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SVC_END, IPC_TYPE_SET, (void *) &svc_end_data, sizeof(svc_end_data));
+ if (rc < 0)
+ goto error;
+
+ if (ipc_fmt_data->svc_session)
+ ipc_fmt_data->svc_session = 0;
+
+ ril_request_data_free(RIL_REQUEST_OEM_HOOK_RAW);
+ break;
+ case RIL_OEM_COMMAND_SVC_KEY:
+ if (length < sizeof(RIL_OEMHookSvcKey))
+ goto error;
+
+ svc_key = (RIL_OEMHookSvcKey *) ((unsigned char *) data + sizeof(RIL_OEMHookHeader));
+
+ if (svc_key->query) {
+ screen_size = ril_request_data_size_get(RIL_REQUEST_OEM_HOOK_RAW);
+ screen_data = ril_request_data_get(RIL_REQUEST_OEM_HOOK_RAW);
+
+ ril_request_complete(token, RIL_E_SUCCESS, screen_data, screen_size);
+
+ rc = RIL_REQUEST_COMPLETED;
+ goto complete;
+ } else {
+ if (!ipc_fmt_data->svc_session)
+ goto error;
+
+ memset(&svc_pro_keycode_data, 0, sizeof(svc_pro_keycode_data));
+ svc_pro_keycode_data.key = svc_key->key;
+
+ rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_SVC_PRO_KEYCODE);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SVC_PRO_KEYCODE, IPC_TYPE_SET, (void *) &svc_pro_keycode_data, sizeof(svc_pro_keycode_data));
+ if (rc < 0)
+ goto error;
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ ril_request_data_free(RIL_REQUEST_OEM_HOOK_RAW);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ if (screen_data != NULL && screen_size > 0)
+ free(screen_data);
+
+ return rc;
+}
diff --git a/power.c b/power.c
new file mode 100644
index 0000000..6de7eb0
--- /dev/null
+++ b/power.c
@@ -0,0 +1,117 @@
+/*
+ * This file is part of Samsung-RIL.
+ *
+ * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Samsung-RIL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
+
+#include <samsung-ril.h>
+#include <utils.h>
+
+int ipc_pwr_phone_pwr_up(struct ipc_message *message)
+{
+ ril_radio_state_update(RADIO_STATE_OFF);
+
+ return 0;
+}
+
+int ipc_pwr_phone_reset(struct ipc_message *message)
+{
+ ril_radio_state_update(RADIO_STATE_OFF);
+
+ return 0;
+}
+
+int ipc_pwr_phone_state(struct ipc_message *message)
+{
+ struct ipc_pwr_phone_state_response_data *data;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_pwr_phone_state_response_data))
+ return -1;
+
+ if (!ipc_seq_valid(message->aseq))
+ return 0;
+
+ data = (struct ipc_pwr_phone_state_response_data *) message->data;
+
+ switch (data->state) {
+ case IPC_PWR_PHONE_STATE_RESPONSE_LPM:
+ RIL_LOGD("Power state is low power mode");
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0);
+ ril_radio_state_update(RADIO_STATE_OFF);
+ break;
+ case IPC_PWR_PHONE_STATE_RESPONSE_NORMAL:
+ RIL_LOGD("Power state is normal");
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0);
+ ril_radio_state_update(RADIO_STATE_SIM_NOT_READY);
+ break;
+ }
+
+ return 0;
+}
+
+int ril_request_radio_power(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_pwr_phone_state_request_data request_data;
+ struct ril_request *request;
+ int power_state;
+ int rc;
+
+ if (data == NULL || size < sizeof(power_state))
+ goto error;
+
+ request = ril_request_find_request_status(RIL_REQUEST_RADIO_POWER, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ power_state = *((int *)data);
+
+ memset(&request_data, 0, sizeof(request_data));
+
+ if (power_state > 0) {
+ RIL_LOGD("Requesting normal power state");
+ request_data.state = IPC_PWR_PHONE_STATE_REQUEST_NORMAL;
+ } else {
+ RIL_LOGD("Requesting low power mode power state");
+ request_data.state = IPC_PWR_PHONE_STATE_REQUEST_LPM;
+ }
+
+ rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_PWR_PHONE_STATE);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_PWR_PHONE_STATE, IPC_TYPE_EXEC, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
diff --git a/pwr.c b/pwr.c
deleted file mode 100644
index e6c4eb4..0000000
--- a/pwr.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define LOG_TAG "RIL-PWR"
-#include <utils/Log.h>
-
-#include "samsung-ril.h"
-#include "util.h"
-
-/*
- * Modem lets us know it's powered on. Though, it's still in LPM and should
- * be considered as OFF. This request is used as a first indication that
- * we can communicate with the modem, so unlock RIL start from here.
- */
-
-void ipc_pwr_phone_pwr_up(void)
-{
- ril_radio_state_update(RADIO_STATE_OFF);
-}
-
-void ipc_pwr_phone_reset(void)
-{
- ril_radio_state_update(RADIO_STATE_OFF);
-}
-
-void ipc_pwr_phone_state(struct ipc_message_info *info)
-{
- unsigned char state;
-
- if (info->data == NULL || info->length < sizeof(unsigned char))
- return;
-
- state = *((unsigned char *) info->data);
-
- switch (state) {
- case IPC_PWR_R(IPC_PWR_PHONE_STATE_LPM):
- RIL_LOGD("Got power to LPM");
-
- if (ril_data.tokens.radio_power != RIL_TOKEN_NULL) {
- ril_request_complete(ril_data.tokens.radio_power, RIL_E_SUCCESS, NULL, 0);
- ril_data.tokens.radio_power = RIL_TOKEN_NULL;
- }
-
- ril_radio_state_update(RADIO_STATE_OFF);
- break;
- case IPC_PWR_R(IPC_PWR_PHONE_STATE_NORMAL):
- RIL_LOGD("Got power to NORMAL");
-
- if (ril_data.tokens.radio_power != RIL_TOKEN_NULL) {
- ril_request_complete(ril_data.tokens.radio_power, RIL_E_SUCCESS, NULL, 0);
- ril_data.tokens.radio_power = RIL_TOKEN_NULL;
- }
-
- ril_radio_state_update(RADIO_STATE_SIM_NOT_READY);
- break;
- }
-
- ril_tokens_check();
-}
-
-void ril_request_radio_power(RIL_Token t, void *data, int length)
-{
- int power_state;
- unsigned short power_data;
-
- if (data == NULL || length < (int) sizeof(int))
- return;
-
- if (ril_radio_state_complete(RADIO_STATE_UNAVAILABLE, t))
- return;
-
- power_state = *((int *) data);
-
- RIL_LOGD("requested power_state is %d", power_state);
-
- if (power_state > 0) {
- RIL_LOGD("Request power to NORMAL");
- power_data = IPC_PWR_PHONE_STATE_NORMAL;
-
- ipc_gen_phone_res_expect_to_abort(ril_request_get_id(t), IPC_PWR_PHONE_STATE);
- ipc_fmt_send(IPC_PWR_PHONE_STATE, IPC_TYPE_EXEC, (void *) &power_data, sizeof(power_data), ril_request_get_id(t));
-
- ril_data.tokens.radio_power = t;
- } else {
- RIL_LOGD("Request power to LPM");
- power_data = IPC_PWR_PHONE_STATE_LPM;
-
- ipc_gen_phone_res_expect_to_abort(ril_request_get_id(t), IPC_PWR_PHONE_STATE);
- ipc_fmt_send(IPC_PWR_PHONE_STATE, IPC_TYPE_EXEC, (void *) &power_data, sizeof(power_data), ril_request_get_id(t));
-
- ril_data.tokens.radio_power = t;
- }
-}
diff --git a/rfs.c b/rfs.c
index da2a77e..74d5325 100644
--- a/rfs.c
+++ b/rfs.c
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * 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
@@ -17,84 +17,132 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
+
#define LOG_TAG "RIL-RFS"
#include <utils/Log.h>
-#include "samsung-ril.h"
-#include "util.h"
+#include <samsung-ril.h>
+#include <utils.h>
-void ipc_rfs_nv_read_item(struct ipc_message_info *info)
+int ipc_rfs_nv_read_item(struct ipc_message *message)
{
- struct ipc_client *ipc_client;
+ struct ipc_rfs_nv_read_item_response_header response_header;
+ struct ipc_rfs_nv_read_item_request_data *data;
+ struct ril_client *client;
+ struct ipc_rfs_data *ipc_rfs_data;
+ void *response_data = NULL;
+ size_t response_size = 0;
+ void *nv_data = NULL;
+ int rc;
- struct ipc_rfs_io *rfs_io;
- struct ipc_rfs_io_confirm *rfs_io_conf;
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_rfs_nv_read_item_request_data))
+ return -1;
- void *rfs_data;
- int rc;
+ client = ril_client_find_id(RIL_CLIENT_IPC_RFS);
+ if (client == NULL || client->data == NULL)
+ return 0;
+
+ ipc_rfs_data = (struct ipc_rfs_data *) client->data;
+ if (ipc_rfs_data->ipc_client == NULL)
+ return 0;
+
+ data = (struct ipc_rfs_nv_read_item_request_data *) message->data;
+
+ memset(&response_header, 0, sizeof(response_header));
- if (info->data == NULL || info->length < sizeof(struct ipc_rfs_io))
- return;
+ nv_data = ipc_nv_data_read(ipc_rfs_data->ipc_client, data->length, data->offset);
+ if (nv_data == NULL) {
+ RIL_LOGE("Reading %d nv_data bytes at offset 0x%x failed", data->length, data->offset);
- rfs_io = (struct ipc_rfs_io *) info->data;
+ response_header.confirm = 0;
- if (ril_data.ipc_rfs_client == NULL || ril_data.ipc_rfs_client->data == NULL)
- return;
+ rc = ipc_rfs_send(message->aseq, IPC_RFS_NV_READ_ITEM, (void *) &response_header, sizeof(response_header));
+ if (rc < 0)
+ goto complete;
- ipc_client = (struct ipc_client *) ril_data.ipc_rfs_client->data;
+ goto complete;
+ }
- rfs_io_conf = calloc(1, rfs_io->length + sizeof(struct ipc_rfs_io_confirm));
- rfs_data = rfs_io_conf + sizeof(struct ipc_rfs_io_confirm);
+ RIL_LOGD("Read %d nv_data bytes at offset 0x%x", data->length, data->offset);
- RIL_LOGD("Asked to read 0x%x bytes at offset 0x%x", rfs_io->length, rfs_io->offset);
- rc = nv_data_read(ipc_client, rfs_io->offset, rfs_io->length, rfs_data);
+ response_header.confirm = 1;
+ response_header.offset = data->offset;
+ response_header.length = data->length;
- RIL_LOGD("Read rfs_data dump:");
- hex_dump(rfs_data, rfs_io->length > 0x100 ? 0x100 : rfs_io->length);
+ response_size = ipc_rfs_nv_data_item_size_setup(&response_header, nv_data, data->length);
+ if (response_size == 0)
+ goto complete;
- RIL_LOGD("Sending RFS IO Confirm message (rc is %d)", rc);
- rfs_io_conf->confirm = rc < 0 ? 0 : 1;
- rfs_io_conf->offset = rfs_io->offset;
- rfs_io_conf->length = rfs_io->length;
+ response_data = ipc_rfs_nv_read_item_setup(&response_header, nv_data, data->length);
+ if (response_data == NULL)
+ goto complete;
- ipc_rfs_send(IPC_RFS_NV_READ_ITEM, (unsigned char *) rfs_io_conf, rfs_io->length + sizeof(struct ipc_rfs_io_confirm), info->aseq);
+ rc = ipc_rfs_send(message->aseq, IPC_RFS_NV_READ_ITEM, response_data, response_size);
+ if (rc < 0)
+ goto complete;
- free(rfs_io_conf);
+ goto complete;
+
+complete:
+ if (response_data != NULL && response_size > 0)
+ free(response_data);
+
+ if (nv_data != NULL)
+ free(nv_data);
+
+ return 0;
}
-void ipc_rfs_nv_write_item(struct ipc_message_info *info)
+int ipc_rfs_nv_write_item(struct ipc_message *message)
{
- struct ipc_client *ipc_client;
+ struct ipc_rfs_nv_write_item_request_header *header;
+ struct ipc_rfs_nv_write_item_response_data data;
+ struct ril_client *client;
+ struct ipc_rfs_data *ipc_rfs_data;
+ void *nv_data;
+ size_t nv_size;
+ int rc;
- struct ipc_rfs_io *rfs_io;
- struct ipc_rfs_io_confirm rfs_io_conf;
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_rfs_nv_write_item_request_header))
+ return -1;
- void *rfs_data;
- int rc;
+ client = ril_client_find_id(RIL_CLIENT_IPC_RFS);
+ if (client == NULL || client->data == NULL)
+ return 0;
+
+ ipc_rfs_data = (struct ipc_rfs_data *) client->data;
+ if (ipc_rfs_data->ipc_client == NULL)
+ return 0;
- if (info->data == NULL || info->length < sizeof(struct ipc_rfs_io))
- return;
+ header = (struct ipc_rfs_nv_write_item_request_header *) message->data;
- rfs_io = (struct ipc_rfs_io *) info->data;
+ nv_size = ipc_rfs_nv_write_item_size_extract(message->data, message->size);
+ if (nv_size == 0)
+ return 0;
- if (ril_data.ipc_rfs_client == NULL || ril_data.ipc_rfs_client->data == NULL)
- return;
+ nv_data = ipc_rfs_nv_write_item_extract(message->data, message->size);
+ if (nv_data == NULL)
+ return 0;
- ipc_client = (struct ipc_client *) ril_data.ipc_rfs_client->data;
+ memset(&data, 0, sizeof(data));
- memset(&rfs_io_conf, 0, sizeof(rfs_io_conf));
- rfs_data = info->data + sizeof(struct ipc_rfs_io);
+ rc = ipc_nv_data_write(ipc_rfs_data->ipc_client, nv_data, header->length, header->offset);
+ if (rc < 0) {
+ RIL_LOGD("Writing %d nv_data byte(s) at offset 0x%x failed", header->length, header->offset);
- RIL_LOGD("Write rfs_data dump:");
- hex_dump(rfs_data, rfs_io->length > 0x100 ? 0x100 : rfs_io->length);
+ data.confirm = 0;
+ } else {
+ RIL_LOGD("Wrote %d nv_data byte(s) at offset 0x%x", header->length, header->offset);
- RIL_LOGD("Asked to write 0x%x bytes at offset 0x%x", rfs_io->length, rfs_io->offset);
- rc = nv_data_write(ipc_client, rfs_io->offset, rfs_io->length, rfs_data);
+ data.confirm = 1;
+ data.offset = header->offset;
+ data.length = header->length;
+ }
- RIL_LOGD("Sending RFS IO Confirm message (rc is %d)", rc);
- rfs_io_conf.confirm = rc < 0 ? 0 : 1;
- rfs_io_conf.offset = rfs_io->offset;
- rfs_io_conf.length = rfs_io->length;
+ rc = ipc_rfs_send(message->aseq, IPC_RFS_NV_WRITE_ITEM, (void *) &data, sizeof(data));
+ if (rc < 0)
+ return 0;
- ipc_rfs_send(IPC_RFS_NV_WRITE_ITEM, (unsigned char *) &rfs_io_conf, sizeof(struct ipc_rfs_io_confirm), info->aseq);
+ return 0;
}
diff --git a/samsung-ril.c b/samsung-ril.c
index 245685e..43784a7 100644
--- a/samsung-ril.c
+++ b/samsung-ril.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,805 +18,1501 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
+#include <ctype.h>
+
#define LOG_TAG "RIL"
-#include "samsung-ril.h"
-#include "util.h"
+#include <utils/Log.h>
+#include <telephony/ril.h>
+
+#include <samsung-ril.h>
+#include <utils.h>
/*
* RIL data
*/
-struct ril_data ril_data;
+struct ril_data *ril_data = NULL;
/*
- * RIL requests
+ * RIL clients
*/
-int ril_request_id_get(void)
-{
- ril_data.request_id++;
- ril_data.request_id %= 0xff;
+struct ril_client *ril_clients[] = {
+ &ipc_fmt_client,
+ &ipc_rfs_client,
+ &srs_client,
+};
- return ril_data.request_id;
-}
+unsigned int ril_clients_count = sizeof(ril_clients) /
+ sizeof(struct ril_client *);
+
+struct ipc_dispatch_handler ipc_fmt_dispatch_handlers[] = {
+ /* Power */
+ {
+ .command = IPC_PWR_PHONE_PWR_UP,
+ .handler = ipc_pwr_phone_pwr_up,
+ },
+ {
+ .command = IPC_PWR_PHONE_RESET,
+ .handler = ipc_pwr_phone_reset,
+ },
+ {
+ .command = IPC_PWR_PHONE_STATE,
+ .handler = ipc_pwr_phone_state,
+ },
+ /* Call */
+ {
+ .command = IPC_CALL_INCOMING,
+ .handler = ipc_call_incoming,
+ },
+ {
+ .command = IPC_CALL_STATUS,
+ .handler = ipc_call_status,
+ },
+ {
+ .command = IPC_CALL_LIST,
+ .handler = ipc_call_list,
+ },
+ {
+ .command = IPC_CALL_BURST_DTMF,
+ .handler = ipc_call_burst_dtmf,
+ },
+ /* SMS */
+ {
+ .command = IPC_SMS_SEND_MSG,
+ .handler = ipc_sms_send_msg,
+ },
+ {
+ .command = IPC_SMS_INCOMING_MSG,
+ .handler = ipc_sms_incoming_msg,
+ },
+ {
+ .command = IPC_SMS_SAVE_MSG,
+ .handler = ipc_sms_save_msg,
+ },
+ {
+ .command = IPC_SMS_DEL_MSG,
+ .handler = ipc_sms_del_msg,
+ },
+ {
+ .command = IPC_SMS_DELIVER_REPORT,
+ .handler = ipc_sms_deliver_report,
+ },
+ {
+ .command = IPC_SMS_SVC_CENTER_ADDR,
+ .handler = ipc_sms_svc_center_addr,
+ },
+ /* SIM */
+ {
+ .command = IPC_SEC_PIN_STATUS,
+ .handler = ipc_sec_pin_status,
+ },
+ {
+ .command = IPC_SEC_PHONE_LOCK,
+ .handler = ipc_sec_phone_lock,
+ },
+ {
+ .command = IPC_SEC_RSIM_ACCESS,
+ .handler = ipc_sec_rsim_access,
+ },
+ {
+ .command = IPC_SEC_SIM_ICC_TYPE,
+ .handler = ipc_sec_sim_icc_type,
+ },
+ {
+ .command = IPC_SEC_LOCK_INFOMATION,
+ .handler = ipc_sec_lock_infomation,
+ },
+ /* Network */
+ {
+ .command = IPC_DISP_ICON_INFO,
+ .handler = ipc_disp_icon_info,
+ },
+ {
+ .command = IPC_DISP_RSSI_INFO,
+ .handler = ipc_disp_rssi_info,
+ },
+ {
+ .command = IPC_NET_PLMN_SEL,
+ .handler = ipc_net_plmn_sel,
+ },
+ {
+ .command = IPC_NET_SERVING_NETWORK,
+ .handler = ipc_net_serving_network,
+ },
+ {
+ .command = IPC_NET_PLMN_LIST,
+ .handler = ipc_net_plmn_list,
+ },
+ {
+ .command = IPC_NET_REGIST,
+ .handler = ipc_net_regist,
+ },
+ {
+ .command = IPC_NET_MODE_SEL,
+ .handler = ipc_net_mode_sel,
+ },
+ /* Misc */
+ {
+ .command = IPC_MISC_ME_VERSION,
+ .handler = ipc_misc_me_version,
+ },
+ {
+ .command = IPC_MISC_ME_IMSI,
+ .handler = ipc_misc_me_imsi,
+ },
+ {
+ .command = IPC_MISC_ME_SN,
+ .handler = ipc_misc_me_sn,
+ },
+ {
+ .command = IPC_MISC_TIME_INFO,
+ .handler = ipc_misc_time_info,
+ },
+ /* OEM */
+ {
+ .command = IPC_SVC_DISPLAY_SCREEN,
+ .handler = ipc_svc_display_screen,
+ },
+ /* Data */
+ {
+ .command = IPC_GPRS_PS,
+ .handler = ipc_gprs_ps,
+ },
+ {
+ .command = IPC_GPRS_PDP_CONTEXT,
+ .handler = ipc_gprs_pdp_context,
+ },
+ {
+ .command = IPC_GPRS_IP_CONFIGURATION,
+ .handler = ipc_gprs_ip_configuration,
+ },
+ {
+ .command = IPC_GPRS_HSDPA_STATUS,
+ .handler = ipc_gprs_hsdpa_status,
+ },
+ {
+ .command = IPC_GPRS_CALL_STATUS,
+ .handler = ipc_gprs_call_status,
+ },
+ /* GEN */
+ {
+ .command = IPC_GEN_PHONE_RES,
+ .handler = ipc_gen_phone_res,
+ },
+};
+
+unsigned int ipc_fmt_dispatch_handlers_count = sizeof(ipc_fmt_dispatch_handlers) /
+ sizeof(struct ipc_dispatch_handler);
+
+struct ipc_dispatch_handler ipc_rfs_dispatch_handlers[] = {
+ {
+ .command = IPC_RFS_NV_READ_ITEM,
+ .handler = ipc_rfs_nv_read_item,
+ },
+ {
+ .command = IPC_RFS_NV_WRITE_ITEM,
+ .handler = ipc_rfs_nv_write_item,
+ },
+};
+
+unsigned int ipc_rfs_dispatch_handlers_count = sizeof(ipc_rfs_dispatch_handlers) /
+ sizeof(struct ipc_dispatch_handler);
+
+struct srs_dispatch_handler srs_dispatch_handlers[] = {
+ {
+ .command = SRS_CONTROL_PING,
+ .handler = srs_control_ping,
+ },
+ {
+ .command = SRS_SND_SET_CALL_VOLUME,
+ .handler = srs_snd_set_call_volume,
+ },
+ {
+ .command = SRS_SND_SET_CALL_AUDIO_PATH,
+ .handler = srs_snd_set_call_audio_path,
+ },
+ {
+ .command = SRS_SND_SET_CALL_CLOCK_SYNC,
+ .handler = srs_snd_set_call_clock_sync,
+ },
+};
+
+unsigned int srs_dispatch_handlers_count = sizeof(srs_dispatch_handlers) /
+ sizeof(struct srs_dispatch_handler);
+
+/*
+ * RIL request
+ */
+
+struct ril_request_handler ril_request_handlers[] = {
+ /* Power */
+ {
+ .request = RIL_REQUEST_RADIO_POWER,
+ .handler = ril_request_radio_power,
+ },
+ /* Call */
+ {
+ .request = RIL_REQUEST_DIAL,
+ .handler = ril_request_dial,
+ },
+ {
+ .request = RIL_REQUEST_HANGUP,
+ .handler = ril_request_hangup,
+ },
+ {
+ .request = RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND,
+ .handler = ril_request_hangup,
+ },
+ {
+ .request = RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
+ .handler = ril_request_hangup,
+ },
+ {
+ .request = RIL_REQUEST_ANSWER,
+ .handler = ril_request_answer,
+ },
+ {
+ .request = RIL_REQUEST_LAST_CALL_FAIL_CAUSE,
+ .handler = ril_request_last_call_fail_cause,
+ },
+ {
+ .request = RIL_REQUEST_GET_CURRENT_CALLS,
+ .handler = ril_request_get_current_calls,
+ },
+ {
+ .request = RIL_REQUEST_DTMF,
+ .handler = ril_request_dtmf,
+ },
+ {
+ .request = RIL_REQUEST_DTMF_START,
+ .handler = ril_request_dtmf_start,
+ },
+ {
+ .request = RIL_REQUEST_DTMF_STOP,
+ .handler = ril_request_dtmf_stop,
+ },
+ /* SMS */
+ {
+ .request = RIL_REQUEST_SEND_SMS,
+ .handler = ril_request_send_sms,
+ },
+ {
+ .request = RIL_REQUEST_SEND_SMS_EXPECT_MORE,
+ .handler = ril_request_send_sms,
+ },
+ {
+ .request = RIL_REQUEST_WRITE_SMS_TO_SIM,
+ .handler = ril_request_write_sms_to_sim,
+ },
+ {
+ .request = RIL_REQUEST_DELETE_SMS_ON_SIM,
+ .handler = ril_request_delete_sms_on_sim,
+ },
+ {
+ .request = RIL_REQUEST_SMS_ACKNOWLEDGE,
+ .handler = ril_request_sms_acknowledge,
+ },
+ /* SIM */
+ {
+ .request = RIL_REQUEST_GET_SIM_STATUS,
+ .handler = ril_request_get_sim_status,
+ },
+ {
+ .request = RIL_REQUEST_QUERY_FACILITY_LOCK,
+ .handler = ril_request_query_facility_lock,
+ },
+ {
+ .request = RIL_REQUEST_SET_FACILITY_LOCK,
+ .handler = ril_request_set_facility_lock,
+ },
+ {
+ .request = RIL_REQUEST_ENTER_SIM_PIN,
+ .handler = ril_request_enter_sim_pin,
+ },
+ {
+ .request = RIL_REQUEST_ENTER_SIM_PUK,
+ .handler = ril_request_enter_sim_puk,
+ },
+ {
+ .request = RIL_REQUEST_ENTER_SIM_PIN2,
+ .handler = ril_request_enter_sim_pin2,
+ },
+ {
+ .request = RIL_REQUEST_ENTER_SIM_PUK2,
+ .handler = ril_request_enter_sim_puk2,
+ },
+ {
+ .request = RIL_REQUEST_CHANGE_SIM_PIN,
+ .handler = ril_request_change_sim_pin,
+ },
+ {
+ .request = RIL_REQUEST_CHANGE_SIM_PIN2,
+ .handler = ril_request_change_sim_pin2,
+ },
+ {
+ .request = RIL_REQUEST_SIM_IO,
+ .handler = ril_request_sim_io,
+ },
+ /* Network */
+ {
+ .request = RIL_REQUEST_SIGNAL_STRENGTH,
+ .handler = ril_request_signal_strength,
+ },
+ {
+ .request = RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE,
+ .handler = ril_request_query_network_selection_mode,
+ },
+ {
+ .request = RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC,
+ .handler = ril_request_set_network_selection_automatic,
+ },
+ {
+ .request = RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
+ .handler = ril_request_set_network_selection_manual,
+ },
+ {
+ .request = RIL_REQUEST_OPERATOR,
+ .handler = ril_request_operator,
+ },
+ {
+ .request = RIL_REQUEST_QUERY_AVAILABLE_NETWORKS,
+ .handler = ril_request_query_available_networks,
+ },
+ {
+#if RIL_VERSION >= 6
+ .request = RIL_REQUEST_VOICE_REGISTRATION_STATE,
+ .handler = ril_request_voice_registration_state,
+#else
+ .request = RIL_REQUEST_REGISTRATION_STATE,
+ .handler = ril_request_registration_state,
+#endif
+ },
+ {
+#if RIL_VERSION >= 6
+ .request = RIL_REQUEST_DATA_REGISTRATION_STATE,
+ .handler = ril_request_data_registration_state,
+#else
+ .request = RIL_REQUEST_GPRS_REGISTRATION_STATE,
+ .handler = ril_request_gprs_registration_state,
+#endif
+ },
+ {
+ .request = RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE,
+ .handler = ril_request_get_preferred_network_type,
+ },
+ {
+ .request = RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
+ .handler = ril_request_set_preferred_network_type,
+ },
+ /* Sound */
+ {
+ .request = RIL_REQUEST_SET_MUTE,
+ .handler = ril_request_set_mute,
+ },
+ /* Misc */
+ {
+ .request = RIL_REQUEST_BASEBAND_VERSION,
+ .handler = ril_request_baseband_version,
+ },
+ {
+ .request = RIL_REQUEST_GET_IMSI,
+ .handler = ril_request_get_imsi,
+ },
+ {
+ .request = RIL_REQUEST_GET_IMEI,
+ .handler = ril_request_get_imei,
+ },
+ {
+ .request = RIL_REQUEST_GET_IMEISV,
+ .handler = ril_request_get_imeisv,
+ },
+ {
+ .request = RIL_REQUEST_SCREEN_STATE,
+ .handler = ril_request_screen_state,
+ },
+ /* OEM */
+ {
+ .request = RIL_REQUEST_OEM_HOOK_RAW,
+ .handler = ril_request_oem_hook_raw,
+ },
+ /* Data */
+ {
+ .request = RIL_REQUEST_SETUP_DATA_CALL,
+ .handler = ril_request_setup_data_call,
+ },
+ {
+ .request = RIL_REQUEST_DEACTIVATE_DATA_CALL,
+ .handler = ril_request_deactivate_data_call,
+ },
+ {
+ .request = RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE,
+ .handler = ril_request_last_data_call_fail_cause,
+ },
+ {
+ .request = RIL_REQUEST_DATA_CALL_LIST,
+ .handler = ril_request_data_call_list,
+ },
+};
-int ril_request_id_set(int id)
+unsigned int ril_request_handlers_count = sizeof(ril_request_handlers) /
+ sizeof(struct ril_request_handler);
+
+int ril_request_stats_log(void)
{
- id %= 0xff;
+ struct ril_request *request;
+ struct list_head *list;
+ unsigned int pending = 0;
+ unsigned int handled = 0;
+ unsigned int unhandled = 0;
+ unsigned int count = 0;
+
+ if (ril_data == NULL)
+ return -1;
+
+ RIL_REQUEST_LOCK();
+
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ request = (struct ril_request *) list->data;
+
+ switch (request->status) {
+ case RIL_REQUEST_PENDING:
+ pending++;
+ break;
+ case RIL_REQUEST_HANDLED:
+ handled++;
+ break;
+ case RIL_REQUEST_UNHANDLED:
+ unhandled++;
+ break;
+ }
+
+ count++;
+
+list_continue:
+ list = list->next;
+ }
+
+ RIL_LOGD("%d RIL request%s in the queue (%d pending, %d handled, %d unhandled)", count, count > 1 ? "s" : "", pending, handled, unhandled);
+
+ count = 0;
- while (ril_data.request_id < id) {
- ril_data.request_id++;
- ril_data.request_id %= 0xff;
+ list = ril_data->requests_data;
+ while (list != NULL) {
+ count++;
+
+ list = list->next;
}
- return ril_data.request_id;
+ if (count > 0)
+ RIL_LOGD("%d RIL request%s data in the queue", count, count > 1 ? "s" : "");
+
+ RIL_REQUEST_UNLOCK();
+
+ return 0;
}
-int ril_request_register(RIL_Token t, int id)
+int ril_request_register(int request, void *data, size_t size, RIL_Token token)
{
- struct ril_request_info *request;
+ struct ril_request *ril_request;
struct list_head *list_end;
struct list_head *list;
+ unsigned int i;
- request = calloc(1, sizeof(struct ril_request_info));
- if (request == NULL)
+ if (ril_data == NULL)
return -1;
- request->token = t;
- request->id = id;
- request->canceled = 0;
+ RIL_REQUEST_LOCK();
+
+ ril_request = (struct ril_request *) calloc(1, sizeof(struct ril_request));
+ ril_request->request = request;
+ ril_request->data = NULL;
+ ril_request->size = size;
+ ril_request->token = token;
+ ril_request->status = RIL_REQUEST_PENDING;
- list_end = ril_data.requests;
+ if (size > 0) {
+ ril_request->data = calloc(1, size);
+ memcpy(ril_request->data, data, size);
+ }
+
+ list_end = ril_data->requests;
while (list_end != NULL && list_end->next != NULL)
list_end = list_end->next;
- list = list_head_alloc((void *) request, list_end, NULL);
+ list = list_head_alloc(list_end, NULL, (void *) ril_request);
+
+ if (ril_data->requests == NULL)
+ ril_data->requests = list;
+
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
- if (ril_data.requests == NULL)
- ril_data.requests = list;
+ ril_client_request_register(ril_clients[i], request, token);
+ }
+
+ RIL_REQUEST_UNLOCK();
return 0;
}
-void ril_request_unregister(struct ril_request_info *request)
+int ril_request_unregister(struct ril_request *request)
{
struct list_head *list;
+ unsigned int i;
- if (request == NULL)
- return;
+ if (request == NULL || ril_data == NULL)
+ return -1;
+
+ RIL_REQUEST_LOCK();
+
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
+
+ ril_client_request_unregister(ril_clients[i], request->request, request->token);
+ }
- list = ril_data.requests;
+ list = ril_data->requests;
while (list != NULL) {
if (list->data == (void *) request) {
- memset(request, 0, sizeof(struct ril_request_info));
+ if (request->data != NULL && request->size > 0)
+ free(request->data);
+
+ memset(request, 0, sizeof(struct ril_request));
free(request);
- if (list == ril_data.requests)
- ril_data.requests = list->next;
+ if (list == ril_data->requests)
+ ril_data->requests = list->next;
list_head_free(list);
break;
}
+
list_continue:
list = list->next;
}
+
+ RIL_REQUEST_UNLOCK();
+
+ return 0;
}
-struct ril_request_info *ril_request_info_find_id(int id)
+int ril_request_flush(void)
{
- struct ril_request_info *request;
+ struct ril_request *request;
struct list_head *list;
+ struct list_head *list_next;
+
+ if (ril_data == NULL)
+ return -1;
+
+ RIL_REQUEST_LOCK();
- list = ril_data.requests;
+ list = ril_data->requests;
while (list != NULL) {
- request = (struct ril_request_info *) list->data;
- if (request == NULL)
+ if (list->data != NULL) {
+ request = (struct ril_request *) list->data;
+
+ if (request->data != NULL && request->size > 0)
+ free(request->data);
+
+ memset(request, 0, sizeof(struct ril_request));
+ free(request);
+ }
+
+ if (list == ril_data->requests)
+ ril_data->requests = list->next;
+
+ list_next = list->next;
+
+ list_head_free(list);
+
+list_continue:
+ list = list_next;
+ }
+
+ RIL_REQUEST_UNLOCK();
+
+ return 0;
+}
+
+struct ril_request *ril_request_find(void)
+{
+ struct ril_request *request;
+ struct list_head *list;
+
+ if (ril_data == NULL)
+ return NULL;
+
+ RIL_REQUEST_LOCK();
+
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
goto list_continue;
- if (request->id == id)
- return request;
+ request = (struct ril_request *) list->data;
+
+ RIL_REQUEST_UNLOCK();
+ return request;
list_continue:
list = list->next;
}
+ RIL_REQUEST_UNLOCK();
+
return NULL;
}
-struct ril_request_info *ril_request_info_find_token(RIL_Token t)
+struct ril_request *ril_request_find_request_status(int request, int status)
{
- struct ril_request_info *request;
+ struct ril_request *ril_request;
struct list_head *list;
- list = ril_data.requests;
+ if (ril_data == NULL)
+ return NULL;
+
+ RIL_REQUEST_LOCK();
+
+ list = ril_data->requests;
while (list != NULL) {
- request = (struct ril_request_info *) list->data;
- if (request == NULL)
+ if (list->data == NULL)
goto list_continue;
- if (request->token == t)
- return request;
+ ril_request = (struct ril_request *) list->data;
+
+ if (ril_request->request == request && ril_request->status == status) {
+ RIL_REQUEST_UNLOCK();
+ return ril_request;
+ }
list_continue:
list = list->next;
}
+ RIL_REQUEST_UNLOCK();
+
return NULL;
}
-int ril_request_set_canceled(RIL_Token t, int canceled)
+struct ril_request *ril_request_find_request(int request)
{
- struct ril_request_info *request;
+ struct ril_request *ril_request;
+ struct list_head *list;
- request = ril_request_info_find_token(t);
- if (request == NULL)
- return -1;
+ if (ril_data == NULL)
+ return NULL;
- request->canceled = canceled ? 1 : 0;
+ RIL_REQUEST_LOCK();
- return 0;
-}
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
-int ril_request_get_canceled(RIL_Token t)
-{
- struct ril_request_info *request;
+ ril_request = (struct ril_request *) list->data;
- request = ril_request_info_find_token(t);
- if (request == NULL)
- return -1;
+ if (ril_request->request == request) {
+ RIL_REQUEST_UNLOCK();
+ return ril_request;
+ }
+
+list_continue:
+ list = list->next;
+ }
+
+ RIL_REQUEST_UNLOCK();
- return request->canceled;
+ return NULL;
}
-RIL_Token ril_request_get_token(int id)
+struct ril_request *ril_request_find_token(RIL_Token token)
{
- struct ril_request_info *request;
+ struct ril_request *request;
+ struct list_head *list;
- request = ril_request_info_find_id(id);
- if (request == NULL)
- return RIL_TOKEN_NULL;
+ if (ril_data == NULL)
+ return NULL;
+
+ RIL_REQUEST_LOCK();
+
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ request = (struct ril_request *) list->data;
+
+ if (request->token == token) {
+ RIL_REQUEST_UNLOCK();
+ return request;
+ }
+
+list_continue:
+ list = list->next;
+ }
- return request->token;
+ RIL_REQUEST_UNLOCK();
+
+ return NULL;
}
-int ril_request_get_id(RIL_Token t)
+struct ril_request *ril_request_find_status(int status)
{
- struct ril_request_info *request;
- int id, rc;
+ struct ril_request *request;
+ struct list_head *list;
- request = ril_request_info_find_token(t);
- if (request != NULL)
- return request->id;
+ if (ril_data == NULL)
+ return NULL;
- id = ril_request_id_get();
+ RIL_REQUEST_LOCK();
- // Unregister a previous request with the same id
- request = ril_request_info_find_id(id);
- if (request != NULL)
- ril_request_unregister(request);
+ list = ril_data->requests;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
- rc = ril_request_register(t, id);
- if (rc < 0)
- return -1;
+ request = (struct ril_request *) list->data;
+
+ if (request->status == status) {
+ RIL_REQUEST_UNLOCK();
+ return request;
+ }
- return id;
+list_continue:
+ list = list->next;
+ }
+
+ RIL_REQUEST_UNLOCK();
+
+ return NULL;
}
-void ril_request_complete(RIL_Token t, RIL_Errno e, void *data, size_t length)
+int ril_request_complete(RIL_Token token, RIL_Errno error, void *data,
+ size_t size)
{
- struct ril_request_info *request;
- int canceled = 0;
+ struct ril_request *request;
+
+ if (ril_data == NULL || ril_data->env == NULL || ril_data->env->OnRequestComplete == NULL)
+ return -1;
- request = ril_request_info_find_token(t);
+ if (token == NULL)
+ return 0;
+
+ request = ril_request_find_token(token);
if (request == NULL)
goto complete;
- canceled = ril_request_get_canceled(t);
ril_request_unregister(request);
- if (canceled)
- return;
+ ril_request_stats_log();
complete:
- ril_data.env->OnRequestComplete(t, e, data, length);
+ ril_data->env->OnRequestComplete(token, error, data, size);
+
+ RIL_REQUEST_LOOP_UNLOCK();
+
+ return 0;
}
-void ril_request_unsolicited(int request, void *data, size_t length)
+int ril_request_unsolicited(int request, void *data, size_t size)
{
- ril_data.env->OnUnsolicitedResponse(request, data, length);
+ if (ril_data == NULL || ril_data->env == NULL || ril_data->env->OnUnsolicitedResponse == NULL)
+ return -1;
+
+ ril_data->env->OnUnsolicitedResponse(request, data, size);
+
+ return 0;
}
-void ril_request_timed_callback(RIL_TimedCallback callback, void *data, const struct timeval *time)
+int ril_request_timed_callback(RIL_TimedCallback callback, void *data,
+ const struct timeval *time)
{
- ril_data.env->RequestTimedCallback(callback, data, time);
-}
+ if (ril_data == NULL || ril_data->env == NULL || ril_data->env->RequestTimedCallback == NULL)
+ return -1;
-/*
- * RIL radio state
- */
+ ril_data->env->RequestTimedCallback(callback, data, time);
-int ril_radio_state_complete(RIL_RadioState radio_state, RIL_Token token)
-{
- RIL_Errno error = RIL_E_SUCCESS;
+ return 0;
+}
- // This goes from best case of failure to worst case of failure
- switch (radio_state) {
- case RADIO_STATE_SIM_NOT_READY:
- if (ril_data.state.radio_state == RADIO_STATE_SIM_NOT_READY)
- error = RIL_E_GENERIC_FAILURE;
- case RADIO_STATE_SIM_LOCKED_OR_ABSENT:
- if (ril_data.state.radio_state == RADIO_STATE_SIM_LOCKED_OR_ABSENT)
- error = RIL_E_GENERIC_FAILURE;
- case RADIO_STATE_OFF:
- if (ril_data.state.radio_state == RADIO_STATE_OFF)
- error = RIL_E_RADIO_NOT_AVAILABLE;
- case RADIO_STATE_UNAVAILABLE:
- default:
- if (ril_data.state.radio_state == RADIO_STATE_UNAVAILABLE)
- error = RIL_E_RADIO_NOT_AVAILABLE;
- break;
- }
+int ril_request_dispatch(struct ril_request *request)
+{
+ unsigned int i;
+ int status;
+ int rc;
- if (error != RIL_E_SUCCESS) {
- if (token != RIL_TOKEN_NULL)
- ril_request_complete(token, error, NULL, 0);
+ if (request == NULL || ril_data == NULL)
+ return -1;
- return 1;
+ for (i = 0; i < ril_request_handlers_count; i++) {
+ if (ril_request_handlers[i].handler == NULL)
+ continue;
+
+ if (ril_request_handlers[i].request == request->request) {
+ status = ril_request_handlers[i].handler(request->data, request->size, request->token);
+ switch (status) {
+ case RIL_REQUEST_PENDING:
+ case RIL_REQUEST_HANDLED:
+ case RIL_REQUEST_UNHANDLED:
+ request->status = status;
+ break;
+ case RIL_REQUEST_COMPLETED:
+ break;
+ default:
+ RIL_LOGE("Handling RIL request %d failed", request->request);
+ return -1;
+ }
+
+ return 0;
+ }
}
+ RIL_LOGD("Unhandled RIL request: %d", request->request);
+ ril_request_complete(request->token, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
+
return 0;
}
-void ril_radio_state_update(RIL_RadioState radio_state)
+void *ril_request_loop(void *data)
{
- RIL_LOGD("Setting radio state to %d", radio_state);
- ril_data.state.radio_state = radio_state;
+ struct ril_request *request;
+ int rc;
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
+ if (ril_data == NULL)
+ return NULL;
+
+ while (1) {
+ RIL_REQUEST_LOOP_LOCK();
+
+ RIL_LOCK();
+
+ rc = ril_radio_state_check(RADIO_STATE_OFF);
+ if (rc < 0) {
+ RIL_UNLOCK();
+ continue;
+ }
- ril_tokens_check();
+ do {
+ request = ril_request_find_status(RIL_REQUEST_UNHANDLED);
+ if (request == NULL)
+ break;
+
+ request->status = RIL_REQUEST_PENDING;
+ } while (request != NULL);
+
+ do {
+ request = ril_request_find_status(RIL_REQUEST_PENDING);
+ if (request == NULL)
+ break;
+
+ rc = ril_request_dispatch(request);
+ if (rc < 0)
+ ril_request_unregister(request);
+ } while (request != NULL);
+
+ RIL_UNLOCK();
+ }
+
+ return NULL;
}
/*
- * RIL tokens
+ * RIL request data
*/
-void ril_tokens_check(void)
+int ril_request_data_register(int request, void *data, size_t size)
{
- RIL_Token t;
+ struct ril_request_data *request_data;
+ struct list_head *list_end;
+ struct list_head *list;
+ unsigned int i;
+
+ if (data == NULL || ril_data == NULL)
+ return -1;
+
+ request_data = (struct ril_request_data *) calloc(1, sizeof(struct ril_request_data));
+ request_data->request = request;
+ request_data->data = data;
+ request_data->size = size;
+
+ list_end = ril_data->requests_data;
+ while (list_end != NULL && list_end->next != NULL)
+ list_end = list_end->next;
+
+ list = list_head_alloc(list_end, NULL, (void *) request_data);
+
+ if (ril_data->requests_data == NULL)
+ ril_data->requests_data = list;
- if (ril_data.tokens.baseband_version != 0) {
- if (ril_data.state.radio_state != RADIO_STATE_OFF) {
- t = ril_data.tokens.baseband_version;
- ril_data.tokens.baseband_version = 0;
- ril_request_baseband_version(t);
+ return 0;
+}
+
+int ril_request_data_unregister(struct ril_request_data *request_data)
+{
+ struct list_head *list;
+ unsigned int i;
+
+ if (request_data == NULL || ril_data == NULL)
+ return -1;
+
+ list = ril_data->requests_data;
+ while (list != NULL) {
+ if (list->data == (void *) request_data) {
+ memset(request_data, 0, sizeof(struct ril_request_data));
+ free(request_data);
+
+ if (list == ril_data->requests_data)
+ ril_data->requests_data = list->next;
+
+ list_head_free(list);
+
+ break;
}
+
+list_continue:
+ list = list->next;
}
- if (ril_data.tokens.get_imei != 0 && ril_data.tokens.get_imeisv != 0) {
- if (ril_data.state.radio_state != RADIO_STATE_OFF) {
- t = ril_data.tokens.get_imei;
- ril_data.tokens.get_imei = 0;
- ril_request_get_imei(t);
+ return 0;
+}
+
+int ril_request_data_flush(void)
+{
+ struct ril_request_data *request_data;
+ struct list_head *list;
+ struct list_head *list_next;
+
+ if (ril_data == NULL)
+ return -1;
+
+ list = ril_data->requests_data;
+ while (list != NULL) {
+ if (list->data != NULL) {
+ request_data = (struct ril_request_data *) list->data;
+
+ if (request_data->data != NULL && request_data->size > 0)
+ free(request_data->data);
+
+ memset(request_data, 0, sizeof(struct ril_request_data));
+ free(request_data);
}
+
+ if (list == ril_data->requests_data)
+ ril_data->requests_data = list->next;
+
+ list_next = list->next;
+
+ list_head_free(list);
+
+list_continue:
+ list = list_next;
}
+
+ return 0;
+}
+
+struct ril_request_data *ril_request_data_find_request(int request)
+{
+ struct ril_request_data *request_data;
+ struct list_head *list;
+
+ if (ril_data == NULL)
+ return NULL;
+
+ list = ril_data->requests_data;
+ while (list != NULL) {
+ if (list->data == NULL)
+ goto list_continue;
+
+ request_data = (struct ril_request_data *) list->data;
+
+ if (request_data->request == request)
+ return request_data;
+
+list_continue:
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+int ril_request_data_free(int request)
+{
+ struct ril_request_data *request_data;
+
+ do {
+ request_data = ril_request_data_find_request(request);
+ if (request_data == NULL)
+ break;
+
+ if (request_data->data != NULL && request_data->size > 0)
+ free(request_data->data);
+
+ ril_request_data_unregister(request_data);
+ } while (request_data != NULL);
+
+ return 0;
+}
+
+int ril_request_data_set(int request, void *data, size_t size)
+{
+ void *buffer;
+ int rc;
+
+ if (data == NULL || size == 0)
+ return -1;
+
+ buffer = calloc(1, size);
+ memcpy(buffer, data, size);
+
+ rc = ril_request_data_register(request, buffer, size);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int ril_request_data_set_uniq(int request, void *data, size_t size)
+{
+ int rc;
+
+ ril_request_data_free(request);
+
+ rc = ril_request_data_set(request, data, size);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+size_t ril_request_data_size_get(int request)
+{
+ struct ril_request_data *request_data;
+
+ request_data = ril_request_data_find_request(request);
+ if (request_data == NULL)
+ return 0;
+
+ return request_data->size;
+}
+
+void *ril_request_data_get(int request)
+{
+ struct ril_request_data *request_data;
+ void *buffer;
+
+ request_data = ril_request_data_find_request(request);
+ if (request_data == NULL)
+ return NULL;
+
+ buffer = request_data->data;
+
+ ril_request_data_unregister(request_data);
+
+ return buffer;
}
/*
- * Clients dispatch functions
+ * RIL radio state
*/
-void ipc_fmt_dispatch(struct ipc_message_info *info)
+int ril_radio_state_update(RIL_RadioState radio_state)
{
- if (info == NULL)
- return;
+ struct ril_request *request;
+ unsigned int i;
+ int rc;
- RIL_LOCK();
+ if (ril_data == NULL)
+ return -1;
- ril_request_id_set(info->aseq);
+ if (ril_data->radio_state == radio_state)
+ return 0;
- switch (IPC_COMMAND(info)) {
- /* GEN */
- case IPC_GEN_PHONE_RES:
- ipc_gen_phone_res(info);
- break;
- /* PWR */
- case IPC_PWR_PHONE_PWR_UP:
- ipc_pwr_phone_pwr_up();
- break;
- case IPC_PWR_PHONE_RESET:
- ipc_pwr_phone_reset();
- break;
- case IPC_PWR_PHONE_STATE:
- ipc_pwr_phone_state(info);
- break;
- /* DISP */
- case IPC_DISP_ICON_INFO:
- ipc_disp_icon_info(info);
- break;
- case IPC_DISP_RSSI_INFO:
- ipc_disp_rssi_info(info);
- break;
- /* MISC */
- case IPC_MISC_ME_SN:
- ipc_misc_me_sn(info);
- break;
- case IPC_MISC_ME_VERSION:
- ipc_misc_me_version(info);
- break;
- case IPC_MISC_ME_IMSI:
- ipc_misc_me_imsi(info);
- break;
- case IPC_MISC_TIME_INFO:
- ipc_misc_time_info(info);
- break;
- /* SAT */
-#ifndef DISABLE_STK
- case IPC_SAT_PROACTIVE_CMD:
- ipc_sat_proactive_cmd(info);
- break;
- case IPC_SAT_ENVELOPE_CMD:
- ipc_sat_envelope_cmd(info);
- break;
-#endif
- /* SS */
- case IPC_SS_USSD:
- ipc_ss_ussd(info);
- break;
- /* SEC */
- case IPC_SEC_SIM_STATUS:
- ipc_sec_sim_status(info);
- break;
- case IPC_SEC_SIM_ICC_TYPE:
- ipc_sec_sim_icc_type(info);
- break;
- case IPC_SEC_LOCK_INFO:
- ipc_sec_lock_info(info);
- break;
- case IPC_SEC_RSIM_ACCESS:
- ipc_sec_rsim_access(info);
- break;
- case IPC_SEC_PHONE_LOCK:
- ipc_sec_phone_lock(info);
- break;
- /* NET */
- case IPC_NET_CURRENT_PLMN:
- ipc_net_current_plmn(info);
- break;
- case IPC_NET_REGIST:
- ipc_net_regist(info);
- break;
- case IPC_NET_PLMN_LIST:
- ipc_net_plmn_list(info);
- break;
- case IPC_NET_PLMN_SEL:
- ipc_net_plmn_sel(info);
- break;
- case IPC_NET_MODE_SEL:
- ipc_net_mode_sel(info);
- break;
- /* SMS */
- case IPC_SMS_INCOMING_MSG:
- ipc_sms_incoming_msg(info);
- break;
- case IPC_SMS_DELIVER_REPORT:
- ipc_sms_deliver_report(info);
- break;
- case IPC_SMS_SVC_CENTER_ADDR:
- ipc_sms_svc_center_addr(info);
- break;
- case IPC_SMS_SEND_MSG:
- ipc_sms_send_msg(info);
- break;
- case IPC_SMS_DEVICE_READY:
- ipc_sms_device_ready(info);
- break;
- case IPC_SMS_SAVE_MSG:
- ipc_sms_save_msg(info);
- break;
- case IPC_SMS_DEL_MSG:
- ipc_sms_del_msg(info);
- break;
- /* SVC */
- case IPC_SVC_DISPLAY_SCREEN:
- ipc_svc_display_screen(info);
- break;
- /* CALL */
- case IPC_CALL_INCOMING:
- ipc_call_incoming(info);
- break;
- case IPC_CALL_LIST:
- ipc_call_list(info);
- break;
- case IPC_CALL_STATUS:
- ipc_call_status(info);
- break;
- case IPC_CALL_BURST_DTMF:
- ipc_call_burst_dtmf(info);
- break;
- /* GPRS */
- case IPC_GPRS_IP_CONFIGURATION:
- ipc_gprs_ip_configuration(info);
- break;
- case IPC_GPRS_CALL_STATUS:
- ipc_gprs_call_status(info);
- break;
- case IPC_GPRS_PDP_CONTEXT:
- ipc_gprs_pdp_context(info);
+ RIL_LOGD("Updating RIL radio state to %d", radio_state);
+
+ ril_data->radio_state = radio_state;
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
+
+ switch (ril_data->radio_state) {
+ case RADIO_STATE_UNAVAILABLE:
+ do {
+ request = ril_request_find();
+ if (request == NULL)
+ break;
+
+ ril_request_complete(request->token, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
+
+ ril_request_unregister(request);
+ } while (request != NULL);
+
+ ril_request_flush();
+ ril_request_data_flush();
+
+ ril_request_stats_log();
+
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
+
+ ril_client_flush(ril_clients[i]);
+ }
+ case RADIO_STATE_OFF:
+ ril_data_connection_flush();
+
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL, 0);
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, NULL, 0);
+ ril_request_unsolicited(RIL_UNSOL_DATA_CALL_LIST_CHANGED, NULL, 0);
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
break;
default:
- RIL_LOGE("%s: Unhandled request: %s (%04x)", __func__, ipc_command_to_str(IPC_COMMAND(info)), IPC_COMMAND(info));
+ RIL_REQUEST_LOOP_UNLOCK();
break;
}
- RIL_UNLOCK();
+ return 0;
}
-void ipc_rfs_dispatch(struct ipc_message_info *info)
+int ril_radio_state_check(RIL_RadioState radio_state)
{
- if (info == NULL)
- return;
+ RIL_RadioState radio_states[] = {
+ RADIO_STATE_UNAVAILABLE,
+ RADIO_STATE_OFF,
+ RADIO_STATE_ON,
+ RADIO_STATE_NV_NOT_READY,
+ RADIO_STATE_NV_READY,
+ RADIO_STATE_SIM_NOT_READY,
+ RADIO_STATE_SIM_LOCKED_OR_ABSENT,
+ RADIO_STATE_SIM_READY,
+ };
+ unsigned int index;
+ unsigned int count;
+ unsigned int i;
+
+ if (ril_data == NULL)
+ return -1;
- RIL_LOCK();
+ count = sizeof(radio_states) / sizeof(RIL_RadioState);
- switch (IPC_COMMAND(info)) {
- case IPC_RFS_NV_READ_ITEM:
- ipc_rfs_nv_read_item(info);
- break;
- case IPC_RFS_NV_WRITE_ITEM:
- ipc_rfs_nv_write_item(info);
+ for (i = 0; i < count; i++)
+ if (radio_states[i] == radio_state)
break;
- default:
- RIL_LOGE("%s: Unhandled request: %s (%04x)", __func__, ipc_command_to_str(IPC_COMMAND(info)), IPC_COMMAND(info));
+
+ index = i;
+
+ for (i = 0; i < count; i++)
+ if (radio_states[i] == ril_data->radio_state)
break;
- }
- RIL_UNLOCK();
+ if (i < index)
+ return -1;
+
+ return 0;
}
-void srs_dispatch(struct srs_message *message)
+/*
+ * RIL data
+ */
+
+int ril_data_create(void)
{
- if (message == NULL)
- return;
+ ril_data = (struct ril_data *) calloc(1, sizeof(struct ril_data));
- RIL_LOCK();
+ pthread_mutex_init(&ril_data->mutex, NULL);
+ pthread_mutex_init(&ril_data->request_mutex, NULL);
+ pthread_mutex_init(&ril_data->request_loop_mutex, NULL);
- switch (message->command) {
- case SRS_CONTROL_PING:
- srs_control_ping(message);
- break;
- case SRS_SND_SET_CALL_CLOCK_SYNC:
- srs_snd_set_call_clock_sync(message);
- break;
- case SRS_SND_SET_CALL_VOLUME:
- srs_snd_set_call_volume(message);
- break;
- case SRS_SND_SET_CALL_AUDIO_PATH:
- srs_snd_set_call_audio_path(message);
- break;
- default:
- RIL_LOGE("%s: Unhandled request: (%04x)", __func__, message->command);
- break;
- }
+ RIL_REQUEST_LOOP_LOCK();
- RIL_UNLOCK();
+ ril_data->radio_state = RADIO_STATE_UNAVAILABLE;
+
+ return 0;
+}
+
+int ril_data_destroy(void)
+{
+ if (ril_data == NULL)
+ return -1;
+
+ pthread_mutex_destroy(&ril_data->mutex);
+ pthread_mutex_destroy(&ril_data->request_mutex);
+ pthread_mutex_destroy(&ril_data->request_loop_mutex);
+
+ free(ril_data);
+ ril_data = NULL;
+
+ return 0;
}
/*
* RIL interface
*/
-void ril_on_request(int request, void *data, size_t length, RIL_Token t)
+void ril_on_request(int request, void *data, size_t size, RIL_Token token)
{
+ struct ril_request *ril_request;
+ void *buffer = NULL;
+ unsigned int strings_count = 0;
+ unsigned int i;
+ char *c;
+
RIL_LOCK();
+ ril_request = ril_request_find_token(token);
+ if (ril_request != NULL)
+ ril_request_unregister(ril_request);
+
switch (request) {
- /* PWR */
- case RIL_REQUEST_RADIO_POWER:
- ril_request_radio_power(t, data, length);
- break;
- case RIL_REQUEST_BASEBAND_VERSION:
- ril_request_baseband_version(t);
- break;
- /* DISP */
- case RIL_REQUEST_SIGNAL_STRENGTH:
- ril_request_signal_strength(t);
- break;
- /* MISC */
- case RIL_REQUEST_GET_IMEI:
- ril_request_get_imei(t);
- break;
- case RIL_REQUEST_GET_IMEISV:
- ril_request_get_imeisv(t);
- break;
- case RIL_REQUEST_GET_IMSI:
- ril_request_get_imsi(t);
- break;
- /* SAT */
-#ifndef DISABLE_STK
- case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING:
- ril_request_report_stk_service_is_running(t);
- break;
- case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE:
- ril_request_stk_send_terminal_response(t, data, length);
- break;
- case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND:
- ril_request_stk_send_envelope_command(t, data, length);
- break;
- case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM:
- ril_request_complete(t, RIL_E_SUCCESS, NULL, 0);
- break;
-#endif
- /* SS */
- case RIL_REQUEST_SEND_USSD:
- ril_request_send_ussd(t, data, length);
- break;
- case RIL_REQUEST_CANCEL_USSD:
- ril_request_cancel_ussd(t, data, length);
- break;
- /* SEC */
- case RIL_REQUEST_GET_SIM_STATUS:
- ril_request_get_sim_status(t);
- break;
- case RIL_REQUEST_SIM_IO:
- ril_request_sim_io(t, data, length);
- break;
- case RIL_REQUEST_ENTER_SIM_PIN:
- ril_request_enter_sim_pin(t, data, length);
- break;
- case RIL_REQUEST_CHANGE_SIM_PIN:
- ril_request_change_sim_pin(t, data, length);
+ case RIL_REQUEST_DIAL:
+ if (data == NULL || size < sizeof(RIL_Dial))
+ break;
+
+ buffer = calloc(1, size);
+
+ memcpy(buffer, data, size);
+
+ if (((RIL_Dial *) data)->address != NULL)
+ ((RIL_Dial *) buffer)->address = strdup(((RIL_Dial *) data)->address);
+
+ data = buffer;
break;
- case RIL_REQUEST_ENTER_SIM_PUK:
- ril_request_enter_sim_puk(t, data, length);
+ case RIL_REQUEST_WRITE_SMS_TO_SIM:
+ if (data == NULL || size < sizeof(RIL_SMS_WriteArgs))
+ break;
+
+
+ buffer = calloc(1, size);
+
+ memcpy(buffer, data, size);
+
+ if (((RIL_SMS_WriteArgs *) data)->pdu != NULL)
+ ((RIL_SMS_WriteArgs *) buffer)->pdu = strdup(((RIL_SMS_WriteArgs *) data)->pdu);
+
+ if (((RIL_SMS_WriteArgs *) data)->smsc != NULL)
+ ((RIL_SMS_WriteArgs *) buffer)->smsc = strdup(((RIL_SMS_WriteArgs *) data)->smsc);
+
+ data = buffer;
break;
+ case RIL_REQUEST_SEND_SMS:
+ case RIL_REQUEST_SEND_SMS_EXPECT_MORE:
case RIL_REQUEST_QUERY_FACILITY_LOCK:
- ril_request_query_facility_lock(t, data, length);
- break;
case RIL_REQUEST_SET_FACILITY_LOCK:
- ril_request_set_facility_lock(t, data, length);
- break;
- /* SVC */
- case RIL_REQUEST_OEM_HOOK_RAW:
- ril_request_oem_hook_raw(t, data, length);
- break;
- /* NET */
- case RIL_REQUEST_OPERATOR:
- ril_request_operator(t);
+ case RIL_REQUEST_ENTER_SIM_PIN:
+ case RIL_REQUEST_ENTER_SIM_PUK:
+ case RIL_REQUEST_ENTER_SIM_PIN2:
+ case RIL_REQUEST_ENTER_SIM_PUK2:
+ case RIL_REQUEST_CHANGE_SIM_PIN:
+ case RIL_REQUEST_CHANGE_SIM_PIN2:
+ strings_count = size / sizeof(char *);
break;
+ case RIL_REQUEST_SIM_IO:
#if RIL_VERSION >= 6
- case RIL_REQUEST_VOICE_REGISTRATION_STATE:
- ril_request_voice_registration_state(t);
- break;
- case RIL_REQUEST_DATA_REGISTRATION_STATE:
- ril_request_data_registration_state(t);
- break;
+ if (data == NULL || size < sizeof(RIL_SIM_IO_v6))
#else
- case RIL_REQUEST_REGISTRATION_STATE:
- ril_request_registration_state(t);
- break;
- case RIL_REQUEST_GPRS_REGISTRATION_STATE:
- ril_request_gprs_registration_state(t);
- break;
+ if (data == NULL || size < sizeof(RIL_SIM_IO))
#endif
- case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS:
- ril_request_query_available_networks(t);
- break;
- case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
- ril_request_get_preferred_network_type(t);
- break;
- case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
- ril_request_set_preferred_network_type(t, data, length);
- break;
- case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
- ril_request_query_network_selection_mode(t);
- break;
- case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
- ril_request_set_network_selection_automatic(t);
- break;
- case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL:
- ril_request_set_network_selection_manual(t, data, length);
- break;
- /* SMS */
- case RIL_REQUEST_SEND_SMS:
- ril_request_send_sms(t, data, length);
- break;
- case RIL_REQUEST_SEND_SMS_EXPECT_MORE:
- ril_request_send_sms_expect_more(t, data, length);
- break;
- case RIL_REQUEST_SMS_ACKNOWLEDGE:
- ril_request_sms_acknowledge(t, data, length);
- break;
- case RIL_REQUEST_WRITE_SMS_TO_SIM:
- ril_request_write_sms_to_sim(t, data, length);
- break;
- case RIL_REQUEST_DELETE_SMS_ON_SIM:
- ril_request_delete_sms_on_sim(t, data, length);
- break;
- /* CALL */
- case RIL_REQUEST_DIAL:
- ril_request_dial(t, data, length);
- break;
- case RIL_REQUEST_GET_CURRENT_CALLS:
- ril_request_get_current_calls(t);
- break;
- case RIL_REQUEST_HANGUP:
- case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
- case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
- ril_request_hangup(t);
- break;
- case RIL_REQUEST_ANSWER:
- ril_request_answer(t);
- break;
- case RIL_REQUEST_LAST_CALL_FAIL_CAUSE:
- ril_request_last_call_fail_cause(t);
- break;
- case RIL_REQUEST_DTMF:
- ril_request_dtmf(t, data, length);
- break;
- case RIL_REQUEST_DTMF_START:
- ril_request_dtmf_start(t, data, length);
- break;
- case RIL_REQUEST_DTMF_STOP:
- ril_request_dtmf_stop(t);
+ break;
+
+ buffer = calloc(1, size);
+
+ memcpy(buffer, data, size);
+
+#if RIL_VERSION >= 6
+ if (((RIL_SIM_IO_v6 *) data)->path != NULL)
+ ((RIL_SIM_IO_v6 *) buffer)->path = strdup(((RIL_SIM_IO_v6 *) data)->path);
+
+ if (((RIL_SIM_IO_v6 *) data)->data != NULL)
+ ((RIL_SIM_IO_v6 *) buffer)->data = strdup(((RIL_SIM_IO_v6 *) data)->data);
+
+ if (((RIL_SIM_IO_v6 *) data)->pin2 != NULL)
+ ((RIL_SIM_IO_v6 *) buffer)->pin2 = strdup(((RIL_SIM_IO_v6 *) data)->pin2);
+
+ if (((RIL_SIM_IO_v6 *) data)->aidPtr != NULL)
+ ((RIL_SIM_IO_v6 *) buffer)->aidPtr = strdup(((RIL_SIM_IO_v6 *) data)->aidPtr);
+#else
+ if (((RIL_SIM_IO *) data)->path != NULL)
+ ((RIL_SIM_IO *) buffer)->path = strdup(((RIL_SIM_IO *) data)->path);
+
+ if (((RIL_SIM_IO *) data)->data != NULL)
+ ((RIL_SIM_IO *) buffer)->data = strdup(((RIL_SIM_IO *) data)->data);
+
+ if (((RIL_SIM_IO *) data)->pin2 != NULL)
+ ((RIL_SIM_IO *) buffer)->pin2 = strdup(((RIL_SIM_IO *) data)->pin2);
+#endif
+
+ data = buffer;
break;
- /* GPRS */
case RIL_REQUEST_SETUP_DATA_CALL:
- ril_request_setup_data_call(t, data, length);
- break;
case RIL_REQUEST_DEACTIVATE_DATA_CALL:
- ril_request_deactivate_data_call(t, data, length);
- break;
- case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE:
- ril_request_last_data_call_fail_cause(t);
- break;
- case RIL_REQUEST_DATA_CALL_LIST:
- ril_request_data_call_list(t);
- break;
- /* SND */
- case RIL_REQUEST_SET_MUTE:
- ril_request_set_mute(t, data, length);
- break;
- /* OTHER */
- case RIL_REQUEST_SCREEN_STATE:
- /* This doesn't affect anything */
- ril_request_complete(t, RIL_E_SUCCESS, NULL, 0);
+ strings_count = size / sizeof(char *);
break;
default:
- RIL_LOGE("%s: Unhandled request: %d", __func__, request);
- ril_request_complete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
+ if (data == NULL || size != sizeof(char *))
+ break;
+
+ c = (char *) data;
+
+ for (i = 0; isprint(c[i]); i++);
+
+ if (i > 0 && c[i] == '\0') {
+ size = i + 1;
+ RIL_LOGD("Detected string with a size of %d byte%s", size, size > 0 ? "s" : "");
+ }
+
break;
}
+ if (strings_count > 0 && data != NULL && size >= strings_count * sizeof(char *)) {
+ buffer = calloc(1, size);
+
+ for (i = 0; i < strings_count; i++) {
+ if (((char **) data)[i] != NULL) {
+ c = strdup(((char **) data)[i]);
+ ((char **) buffer)[i] = c;
+ }
+ }
+
+ data = buffer;
+ }
+
+ ril_request_register(request, data, size, token);
+
+ if (buffer != NULL)
+ free(buffer);
+
+ ril_request_stats_log();
+
RIL_UNLOCK();
+
+ RIL_REQUEST_LOOP_UNLOCK();
}
+
RIL_RadioState ril_on_state_request(void)
{
- return ril_data.state.radio_state;
-}
+ if (ril_data == NULL)
+ return RADIO_STATE_UNAVAILABLE;
-int ril_on_supports(int request)
-{
- return 1;
+ return ril_data->radio_state;
}
-void ril_on_cancel(RIL_Token t)
+int ril_supports(int request)
{
- ril_request_set_canceled(t, 1);
+ unsigned int i;
+
+ for (i = 0; i < ril_request_handlers_count; i++) {
+ if (ril_request_handlers[i].handler == NULL)
+ continue;
+
+ if (ril_request_handlers[i].request == request)
+ return 1;
+ }
+
+ return 0;
}
-const char *ril_get_version(void)
+void ril_on_cancel(RIL_Token token)
{
- return RIL_VERSION_STRING;
-}
+ struct ril_request *request;
-/*
- * RIL init
- */
+ RIL_LOCK();
-void ril_data_init(void)
-{
- memset(&ril_data, 0, sizeof(ril_data));
+ request = ril_request_find_token(token);
+ if (request == NULL) {
+ RIL_UNLOCK();
+ return;
+ }
- pthread_mutex_init(&ril_data.mutex, NULL);
+ ril_request_unregister(request);
- ril_data.state.radio_state = RADIO_STATE_UNAVAILABLE;
+ ril_request_stats_log();
+
+ RIL_UNLOCK();
}
-/*
- * RIL interface
- */
+const char *ril_get_version(void)
+{
+ return RIL_VERSION_STRING;
+}
-static const RIL_RadioFunctions ril_ops = {
- RIL_VERSION >= 6 ? 6 : RIL_VERSION,
+RIL_RadioFunctions ril_radio_functions = {
+ RIL_VERSION,
ril_on_request,
ril_on_state_request,
- ril_on_supports,
+ ril_supports,
ril_on_cancel,
ril_get_version
};
-const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
+const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc,
+ char **argv)
{
- struct ril_client *ipc_fmt_client;
- struct ril_client *ipc_rfs_client;
- struct ril_client *srs_client;
+ RIL_RadioFunctions *radio_functions;
+ pthread_attr_t attr;
+ unsigned int i;
int rc;
if (env == NULL)
return NULL;
- ril_data_init();
- ril_data.env = (struct RIL_Env *) env;
-
- RIL_LOCK();
-
- RIL_LOGD("Creating IPC FMT client");
-
- ipc_fmt_client = ril_client_new(&ipc_fmt_client_funcs);
- rc = ril_client_create(ipc_fmt_client);
-
+ rc = ril_data_create();
if (rc < 0) {
- RIL_LOGE("IPC FMT client creation failed.");
- goto ipc_rfs;
- }
-
- rc = ril_client_thread_start(ipc_fmt_client);
-
- if (rc < 0) {
- RIL_LOGE("IPC FMT thread creation failed.");
- goto ipc_rfs;
+ RIL_LOGE("Creating RIL data failed");
+ return NULL;
}
- ril_data.ipc_fmt_client = ipc_fmt_client;
- RIL_LOGD("IPC FMT client ready");
-
-ipc_rfs:
- RIL_LOGD("Creating IPC RFS client");
-
- ipc_rfs_client = ril_client_new(&ipc_rfs_client_funcs);
- rc = ril_client_create(ipc_rfs_client);
+ RIL_LOCK();
- if (rc < 0) {
- RIL_LOGE("IPC RFS client creation failed.");
- goto srs;
- }
+ ril_data->env = env;
- rc = ril_client_thread_start(ipc_rfs_client);
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
- if (rc < 0) {
- RIL_LOGE("IPC RFS thread creation failed.");
- goto srs;
+ rc = ril_client_create(ril_clients[i]);
+ if (rc < 0)
+ goto error;
}
- ril_data.ipc_rfs_client = ipc_rfs_client;
- RIL_LOGD("IPC RFS client ready");
-
-srs:
- RIL_LOGD("Creating SRS client");
+ for (i = 0; i < ril_clients_count; i++) {
+ if (ril_clients[i] == NULL)
+ continue;
- srs_client = ril_client_new(&srs_client_funcs);
- rc = ril_client_create(srs_client);
+ rc = ril_client_open(ril_clients[i]);
+ if (rc < 0)
+ goto error;
- if (rc < 0) {
- RIL_LOGE("SRS client creation failed.");
- goto end;
+ rc = ril_client_loop(ril_clients[i]);
+ if (rc < 0)
+ goto error;
}
- rc = ril_client_thread_start(srs_client);
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (rc < 0) {
- RIL_LOGE("SRS thread creation failed.");
- goto end;
+ rc = pthread_create(&ril_data->request_thread, &attr, ril_request_loop, NULL);
+ if (rc != 0) {
+ RIL_LOGE("Starting request loop failed");
+ goto error;
}
- ril_data.srs_client = srs_client;
- RIL_LOGD("SRS client ready");
+ radio_functions = &ril_radio_functions;
+ goto complete;
-end:
+error:
+ radio_functions = NULL;
+
+complete:
RIL_UNLOCK();
- return &ril_ops;
+ return radio_functions;
}
diff --git a/samsung-ril.h b/samsung-ril.h
index a154218..2879782 100644
--- a/samsung-ril.h
+++ b/samsung-ril.h
@@ -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
@@ -21,54 +21,58 @@
#ifndef _SAMSUNG_RIL_H_
#define _SAMSUNG_RIL_H_
-#include <errno.h>
+#include <stdlib.h>
#include <string.h>
#include <pthread.h>
-#include <utils/Log.h>
#include <telephony/ril.h>
#include <samsung-ipc.h>
+#include <samsung-ril-socket.h>
-#include "ipc.h"
-#include "srs.h"
+#include <ipc.h>
+#include <srs.h>
+#include <utils.h>
/*
- * Defines
+ * Values
+ */
+
+#define RIL_VERSION_STRING "Samsung-RIL"
+
+#define RIL_CLIENT_RETRY_COUNT 5
+#define RIL_CLIENT_RETRY_DELAY 50000
+
+/*
+ * Macros
*/
#ifdef ALOGI
-#define RIL_LOGI ALOGI
+#define RIL_LOGI ALOGI
#else
-#define RIL_LOGI LOGI
+#define RIL_LOGI LOGI
#endif
#ifdef ALOGD
-#define RIL_LOGD ALOGD
+#define RIL_LOGD ALOGD
#else
-#define RIL_LOGD LOGD
+#define RIL_LOGD LOGD
#endif
#ifdef ALOGE
-#define RIL_LOGE ALOGE
+#define RIL_LOGE ALOGE
#else
-#define RIL_LOGE LOGE
+#define RIL_LOGE LOGE
#endif
-#define RIL_VERSION_STRING "Samsung RIL"
-
-#define RIL_LOCK() pthread_mutex_lock(&ril_data.mutex)
-#define RIL_UNLOCK() pthread_mutex_unlock(&ril_data.mutex)
-#define RIL_CLIENT_LOCK(client) pthread_mutex_lock(&(client->mutex))
-#define RIL_CLIENT_UNLOCK(client) pthread_mutex_unlock(&(client->mutex))
-
-#define RIL_TOKEN_DATA_WAITING (RIL_Token) 0xff
-#define RIL_TOKEN_NULL (RIL_Token) 0x00
-
-#define RIL_SMS_TPID 0xff
-#define RIL_SMS_NUMBER "0123456789"
-
-#define RIL_CLIENT_MAX_TRIES 7
+#define RIL_LOCK() pthread_mutex_lock(&ril_data->mutex)
+#define RIL_UNLOCK() pthread_mutex_unlock(&ril_data->mutex)
+#define RIL_REQUEST_LOCK() pthread_mutex_lock(&ril_data->request_mutex)
+#define RIL_REQUEST_UNLOCK() pthread_mutex_unlock(&ril_data->request_mutex)
+#define RIL_REQUEST_LOOP_LOCK() pthread_mutex_lock(&ril_data->request_loop_mutex)
+#define RIL_REQUEST_LOOP_UNLOCK() pthread_mutex_unlock(&ril_data->request_loop_mutex)
+#define RIL_CLIENT_LOCK(client) pthread_mutex_lock(&client->mutex)
+#define RIL_CLIENT_UNLOCK(client) pthread_mutex_unlock(&client->mutex)
/*
* RIL client
@@ -76,431 +80,377 @@
struct ril_client;
-struct ril_client_funcs {
+enum {
+ RIL_CLIENT_IPC_FMT,
+ RIL_CLIENT_IPC_RFS,
+ RIL_CLIENT_SRS,
+};
+
+struct ril_client_handlers {
int (*create)(struct ril_client *client);
int (*destroy)(struct ril_client *client);
- int (*read_loop)(struct ril_client *client);
+ int (*open)(struct ril_client *client);
+ int (*close)(struct ril_client *client);
+ int (*loop)(struct ril_client *client);
};
-typedef enum {
- RIL_CLIENT_NULL = 0,
- RIL_CLIENT_CREATED = 1,
- RIL_CLIENT_READY = 2,
- RIL_CLIENT_DESTROYED = 3,
- RIL_CLIENT_ERROR = 4,
-} ril_client_state;
+struct ril_client_callbacks {
+ int (*request_register)(struct ril_client *client, int request, RIL_Token token);
+ int (*request_unregister)(struct ril_client *client, int request, RIL_Token token);
+ int (*flush)(struct ril_client *client);
+};
struct ril_client {
- struct ril_client_funcs funcs;
- ril_client_state state;
+ int id;
+ char *name;
+ int critical;
+ struct ril_client_handlers *handlers;
+ struct ril_client_callbacks *callbacks;
+ int failures;
+ int available;
void *data;
pthread_t thread;
pthread_mutex_t mutex;
};
-struct ril_client *ril_client_new(struct ril_client_funcs *client_funcs);
-int ril_client_free(struct ril_client *client);
+extern struct ril_client *ril_clients[];
+extern unsigned int ril_clients_count;
+
+extern struct ipc_dispatch_handler ipc_fmt_dispatch_handlers[];
+extern unsigned int ipc_fmt_dispatch_handlers_count;
+extern struct ipc_dispatch_handler ipc_rfs_dispatch_handlers[];
+extern unsigned int ipc_rfs_dispatch_handlers_count;
+extern struct srs_dispatch_handler srs_dispatch_handlers[];
+extern unsigned int srs_dispatch_handlers_count;
+
+struct ril_client *ril_client_find_id(int id);
int ril_client_create(struct ril_client *client);
int ril_client_destroy(struct ril_client *client);
-int ril_client_thread_start(struct ril_client *client);
+int ril_client_open(struct ril_client *client);
+int ril_client_close(struct ril_client *client);
+int ril_client_loop(struct ril_client *client);
+int ril_client_request_register(struct ril_client *client, int request,
+ RIL_Token token);
+int ril_client_request_unregister(struct ril_client *client, int request,
+ RIL_Token token);
+int ril_client_flush(struct ril_client *client);
/*
- * RIL requests
+ * RIL request
*/
-struct ril_request_info {
+enum {
+ RIL_REQUEST_PENDING,
+ RIL_REQUEST_HANDLED,
+ RIL_REQUEST_UNHANDLED,
+ RIL_REQUEST_COMPLETED,
+};
+
+struct ril_request_handler {
+ int request;
+ int (*handler)(void *data, size_t size, RIL_Token token);
+};
+
+struct ril_request {
+ int request;
+ void *data;
+ size_t size;
RIL_Token token;
- int id;
- int canceled;
+
+ int status;
};
-int ril_request_id_get(void);
-int ril_request_id_set(int id);
-int ril_request_register(RIL_Token t, int id);
-void ril_request_unregister(struct ril_request_info *request);
-struct ril_request_info *ril_request_info_find_id(int id);
-struct ril_request_info *ril_request_info_find_token(RIL_Token t);
-int ril_request_set_canceled(RIL_Token t, int canceled);
-int ril_request_get_canceled(RIL_Token t);
-RIL_Token ril_request_get_token(int id);
-int ril_request_get_id(RIL_Token t);
-
-void ril_request_complete(RIL_Token t, RIL_Errno e, void *data, size_t length);
-void ril_request_unsolicited(int request, void *data, size_t length);
-void ril_request_timed_callback(RIL_TimedCallback callback, void *data, const struct timeval *time);
+extern struct ril_request_handler ril_request_handlers[];
+extern unsigned int ril_request_handlers_count;
+
+int ril_request_register(int request, void *data, size_t size, RIL_Token token);
+int ril_request_unregister(struct ril_request *request);
+int ril_request_flush(void);
+struct ril_request *ril_request_find(void);
+struct ril_request *ril_request_find_request_status(int request, int status);
+struct ril_request *ril_request_find_request(int request);
+struct ril_request *ril_request_find_token(RIL_Token token);
+struct ril_request *ril_request_find_status(int status);
+int ril_request_complete(RIL_Token token, RIL_Errno error, void *data,
+ size_t size);
+int ril_request_unsolicited(int request, void *data, size_t size);
+int ril_request_timed_callback(RIL_TimedCallback callback, void *data,
+ const struct timeval *time);
+
+/*
+ * RIL request data
+ */
+
+struct ril_request_data {
+ int request;
+ void *data;
+ size_t size;
+};
+
+int ril_request_data_register(int request, void *data, size_t size);
+int ril_request_data_unregister(struct ril_request_data *request_data);
+int ril_request_data_flush(void);
+struct ril_request_data *ril_request_data_find_request(int request);
+int ril_request_data_free(int request);
+int ril_request_data_set(int request, void *data, size_t size);
+int ril_request_data_set_uniq(int request, void *data, size_t size);
+size_t ril_request_data_size_get(int request);
+void *ril_request_data_get(int request);
/*
* RIL radio state
*/
-int ril_radio_state_complete(RIL_RadioState radio_state, RIL_Token token);
-void ril_radio_state_update(RIL_RadioState radio_state);
+int ril_radio_state_update(RIL_RadioState radio_state);
+int ril_radio_state_check(RIL_RadioState radio_state);
/*
- * RIL tokens
+ * RIL data
*/
-struct ril_tokens {
- RIL_Token radio_power;
- RIL_Token pin_status;
- RIL_Token get_imei;
- RIL_Token get_imeisv;
- RIL_Token baseband_version;
+struct ril_data {
+ const struct RIL_Env *env;
+
+ RIL_RadioState radio_state;
+ char *sim_pin;
- RIL_Token registration_state;
- RIL_Token gprs_registration_state;
- RIL_Token operator;
+ struct list_head *requests;
+ struct list_head *requests_data;
+
+ struct list_head *data_connections;
- RIL_Token outgoing_sms;
- RIL_Token sim_io;
+ pthread_mutex_t mutex;
+
+ pthread_t request_thread;
+ pthread_mutex_t request_mutex;
+ pthread_mutex_t request_loop_mutex;
};
-void ril_tokens_check(void);
+extern struct ril_data *ril_data;
+
+int ril_data_create(void);
+int ril_data_destroy(void);
/*
- * RIL state
+ * Power
*/
-typedef enum {
- SIM_STATE_ABSENT = 0,
- SIM_STATE_NOT_READY = 1,
- SIM_STATE_READY = 2,
- SIM_STATE_PIN = 3,
- SIM_STATE_PUK = 4,
- SIM_STATE_BLOCKED = 5,
- SIM_STATE_NETWORK_PERSO = 6,
- SIM_STATE_NETWORK_SUBSET_PERSO = 7,
- SIM_STATE_CORPORATE_PERSO = 8,
- SIM_STATE_SERVICE_PROVIDER_PERSO = 9,
-} ril_sim_state;
-
-struct ril_state {
- RIL_RadioState radio_state;
- ril_sim_state sim_state;
+int ipc_pwr_phone_pwr_up(struct ipc_message *message);
+int ipc_pwr_phone_reset(struct ipc_message *message);
+int ipc_pwr_phone_state(struct ipc_message *message);
+int ril_request_radio_power(void *data, size_t size, RIL_Token token);
- struct ipc_sec_sim_status_response sim_pin_status;
- struct ipc_sec_sim_icc_type sim_icc_type;
+/*
+ * Call
+ */
- struct ipc_net_regist_response netinfo;
- struct ipc_net_regist_response gprs_netinfo;
- struct ipc_net_current_plmn_response plmndata;
+int ril_request_dial(void *data, size_t size, RIL_Token token);
+int ipc_call_incoming(struct ipc_message *message);
+int ril_request_hangup(void *data, size_t size, RIL_Token token);
+int ril_request_answer(void *data, size_t size, RIL_Token token);
+int ipc_call_status(struct ipc_message *message);
+int ril_request_last_call_fail_cause(void *data, size_t size, RIL_Token token);
+int ipc_call_list(struct ipc_message *message);
+int ril_request_get_current_calls(void *data, size_t size, RIL_Token token);
+int ipc_call_cont_dtmf_callback(struct ipc_message *message);
+int ipc_call_burst_dtmf(struct ipc_message *message);
+int ril_request_dtmf_complete(unsigned char aseq, char tone);
+int ril_request_dtmf(void *data, size_t size, RIL_Token token);
+int ril_request_dtmf_start_complete(unsigned char aseq, char tone);
+int ril_request_dtmf_start(void *data, size_t size, RIL_Token token);
+int ril_request_dtmf_stop_complete(unsigned char aseq, int callback);
+int ril_request_dtmf_stop(void *data, size_t size, RIL_Token token);
- struct ipc_call_status call_status;
+/*
+ * SMS
+ */
- int gprs_last_failed_cid;
+int ipc_sms_send_msg(struct ipc_message *message);
+int ril_request_send_sms_complete(unsigned char seq, const void *smsc,
+ size_t smsc_size, const void *pdu, size_t pdu_size);
+int ril_request_send_sms(void *data, size_t size, RIL_Token token);
+int ipc_sms_incoming_msg(struct ipc_message *message);
+int ipc_sms_save_msg(struct ipc_message *message);
+int ril_request_write_sms_to_sim(void *data, size_t size, RIL_Token token);
+int ipc_sms_del_msg(struct ipc_message *message);
+int ril_request_delete_sms_on_sim(void *data, size_t size, RIL_Token token);
+int ipc_sms_deliver_report(struct ipc_message *message);
+int ril_request_sms_acknowledge(void *data, size_t size, RIL_Token token);
+int ipc_sms_svc_center_addr(struct ipc_message *message);
- unsigned char dtmf_tone;
- unsigned char ussd_state;
+/*
+ * SIM
+ */
- unsigned char sms_incoming_msg_tpid;
- unsigned char ril_sms_tpid;
-};
+int ipc_sec_pin_status_callback(struct ipc_message *message);
+int ipc_sec_pin_status(struct ipc_message *message);
+int ril_request_get_sim_status(void *data, size_t size, RIL_Token token);
+int ipc_sec_phone_lock(struct ipc_message *message);
+int ril_request_query_facility_lock(void *data, size_t size, RIL_Token token);
+int ipc_sec_callback(struct ipc_message *message);
+int ril_request_set_facility_lock(void *data, size_t size, RIL_Token token);
+int ril_request_enter_sim_pin(void *data, size_t size, RIL_Token token);
+int ril_request_enter_sim_puk(void *data, size_t size, RIL_Token token);
+int ril_request_enter_sim_pin2(void *data, size_t size, RIL_Token token);
+int ril_request_enter_sim_puk2(void *data, size_t size, RIL_Token token);
+int ril_request_change_sim_pin(void *data, size_t size, RIL_Token token);
+int ril_request_change_sim_pin2(void *data, size_t size, RIL_Token token);
+int ipc_sec_rsim_access(struct ipc_message *message);
+int ril_request_sim_io(void *data, size_t size, RIL_Token token);
+int ipc_sec_sim_icc_type(struct ipc_message *message);
+int ipc_sec_lock_infomation(struct ipc_message *message);
/*
- * RIL data
+ * Network
*/
-struct ril_data {
- struct RIL_Env *env;
-
- struct ril_state state;
- struct ril_tokens tokens;
- struct ril_oem_hook_svc_session *oem_hook_svc_session;
- struct list_head *gprs_connections;
- struct list_head *incoming_sms;
- struct list_head *outgoing_sms;
- struct list_head *sim_io;
- struct list_head *generic_responses;
- struct list_head *requests;
- int request_id;
-
- struct ril_client *ipc_fmt_client;
- struct ril_client *ipc_rfs_client;
- struct ril_client *srs_client;
+int ipc_disp_icon_info(struct ipc_message *message);
+int ril_request_signal_strength(void *data, size_t size, RIL_Token token);
+int ipc_disp_rssi_info(struct ipc_message *message);
+int ipc_net_plmn_sel(struct ipc_message *message);
+int ril_request_query_network_selection_mode(void *data, size_t size,
+ RIL_Token token);
+int ipc_net_plmn_sel_callback(struct ipc_message *message);
+int ril_request_set_network_selection_automatic(void *data, size_t size,
+ RIL_Token token);
+int ril_request_set_network_selection_manual(void *data, size_t size,
+ RIL_Token token);
+int ipc_net_serving_network(struct ipc_message *message);
+int ril_request_operator(void *data, size_t size, RIL_Token token);
+int ipc_net_plmn_list(struct ipc_message *message);
+int ril_request_query_available_networks(void *data, size_t size,
+ RIL_Token token);
+int ipc_net_regist(struct ipc_message *message);
+#if RIL_VERSION >= 6
+int ril_request_voice_registration_state(void *data, size_t size,
+ RIL_Token token);
+#else
+int ril_request_registration_state(void *data, size_t size, RIL_Token token);
+#endif
+#if RIL_VERSION >= 6
+int ril_request_data_registration_state(void *data, size_t size,
+ RIL_Token token);
+#else
+int ril_request_gprs_registration_state(void *data, size_t size,
+ RIL_Token token);
+#endif
+int ipc_net_mode_sel(struct ipc_message *message);
+int ril_request_get_preferred_network_type(void *data, size_t size,
+ RIL_Token token);
+int ril_request_set_preferred_network_type(void *data, size_t size,
+ RIL_Token token);
- pthread_mutex_t mutex;
-};
+/*
+ * Sound
+ */
-extern struct ril_data ril_data;
+int srs_snd_set_call_volume(struct srs_message *message);
+int ril_request_set_mute(void *data, size_t size, RIL_Token token);
+int srs_snd_set_call_audio_path(struct srs_message *message);
+int srs_snd_set_call_clock_sync(struct srs_message *message);
/*
- * Dispatch functions
+ * Misc
*/
-void ipc_fmt_dispatch(struct ipc_message_info *info);
-void ipc_rfs_dispatch(struct ipc_message_info *info);
-void srs_dispatch(struct srs_message *message);
+int ipc_misc_me_version(struct ipc_message *message);
+int ril_request_baseband_version(void *data, size_t size, RIL_Token token);
+int ipc_misc_me_imsi(struct ipc_message *message);
+int ril_request_get_imsi(void *data, size_t size, RIL_Token token);
+int ipc_misc_me_sn(struct ipc_message *message);
+int ril_request_get_imei(void *data, size_t size, RIL_Token token);
+int ril_request_get_imeisv(void *data, size_t size, RIL_Token token);
+int ipc_misc_time_info(struct ipc_message *message);
+int ril_request_screen_state(void *data, size_t size, RIL_Token token);
-/* GEN */
+/*
+ * OEM
+ */
-struct ipc_gen_phone_res_expect_info {
- unsigned char aseq;
- unsigned short command;
- void (*func)(struct ipc_message_info *info);
- int complete;
- int abort;
-};
+int ipc_svc_display_screen(struct ipc_message *message);
+int ril_request_oem_hook_raw(void *data, size_t size, RIL_Token token);
-int ipc_gen_phone_res_expect_register(unsigned char aseq, unsigned short command,
- void (*func)(struct ipc_message_info *info), int complete, int abort);
-void ipc_gen_phone_res_expect_unregister(struct ipc_gen_phone_res_expect_info *expect);
-struct ipc_gen_phone_res_expect_info *ipc_gen_phone_res_expect_find_aseq(unsigned char aseq);
-int ipc_gen_phone_res_expect_to_func(unsigned char aseq, unsigned short command,
- void (*func)(struct ipc_message_info *info));
-int ipc_gen_phone_res_expect_to_complete(unsigned char aseq, unsigned short command);
-int ipc_gen_phone_res_expect_to_abort(unsigned char aseq, unsigned short command);
-
-void ipc_gen_phone_res(struct ipc_message_info *info);
-
-/* PWR */
-
-void ipc_pwr_phone_pwr_up(void);
-void ipc_pwr_phone_reset(void);
-void ipc_pwr_phone_state(struct ipc_message_info *info);
-void ril_request_radio_power(RIL_Token t, void *data, int length);
-
-/* DISP */
-
-void ril_request_signal_strength(RIL_Token t);
-void ipc_disp_icon_info(struct ipc_message_info *info);
-void ipc_disp_rssi_info(struct ipc_message_info *info);
-
-/* MISC */
-
-void ril_request_get_imei(RIL_Token t);
-void ril_request_get_imeisv(RIL_Token t);
-void ipc_misc_me_sn(struct ipc_message_info *info);
-void ril_request_baseband_version(RIL_Token t);
-void ipc_misc_me_version(struct ipc_message_info *info);
-void ril_request_get_imsi(RIL_Token t);
-void ipc_misc_me_imsi(struct ipc_message_info *info);
-void ipc_misc_time_info(struct ipc_message_info *info);
-
-/* SAT */
-void ril_request_report_stk_service_is_running(RIL_Token t);
-void ipc_sat_proactive_cmd(struct ipc_message_info *info);
-void ril_request_stk_send_terminal_response(RIL_Token t, void *data, size_t length);
-void ril_request_stk_send_envelope_command(RIL_Token t, void *data, size_t length);
-void ipc_sat_envelope_cmd(struct ipc_message_info *info);
-
-/* SS */
-
-void ril_request_send_ussd(RIL_Token t, void *data, size_t datalen);
-void ril_request_cancel_ussd(RIL_Token t, void *data, size_t datalen);
-void ipc_ss_ussd(struct ipc_message_info *info);
-
-/* SEC */
-
-struct ril_request_sim_io_info {
- unsigned char command;
- unsigned short fileid;
- unsigned char p1;
- unsigned char p2;
- unsigned char p3;
- void *data;
- int length;
+/*
+ * Data
+ */
- int waiting;
+struct ril_data_connection {
+ unsigned int cid;
RIL_Token token;
-};
-void ril_state_update(ril_sim_state status);
-void ipc_sec_sim_status(struct ipc_message_info *info);
-void ril_request_get_sim_status(RIL_Token t);
-void ipc_sec_sim_icc_type(struct ipc_message_info *info);
-void ril_request_sim_io_next(void);
-void ril_request_sim_io_complete(RIL_Token t, unsigned char command, unsigned short fileid,
- unsigned char p1, unsigned char p2, unsigned char p3, void *data, int length);
-void ril_request_sim_io(RIL_Token t, void *data, int length);
-void ipc_sec_rsim_access(struct ipc_message_info *info);
-void ipc_sec_sim_status_complete(struct ipc_message_info *info);
-void ipc_sec_lock_info(struct ipc_message_info *info);
-void ril_request_enter_sim_pin(RIL_Token t, void *data, size_t length);
-void ril_request_change_sim_pin(RIL_Token t, void *data, size_t length);
-void ril_request_enter_sim_puk(RIL_Token t, void *data, size_t length);
-void ril_request_query_facility_lock(RIL_Token t, void *data, size_t length);
-void ipc_sec_phone_lock(struct ipc_message_info *info);
-void ipc_sec_phone_lock_complete(struct ipc_message_info *info);
-void ril_request_set_facility_lock(RIL_Token t, void *data, size_t length);
-
-/* SVC */
-
-typedef enum {
- RIL_OEM_HOOK_TAG_SVC = 1,
-} RIL_OEMHookTag;
-
-typedef enum {
- RIL_OEM_COMMAND_SVC_ENTER_MODE = 1,
- RIL_OEM_COMMAND_SVC_END_MODE = 2,
- RIL_OEM_COMMAND_SVC_KEY = 3,
-} RIL_OEMCommandSvc;
-
-typedef struct {
- unsigned char tag;
- unsigned char command;
- unsigned short length;
-} RIL_OEMHookHeader;
-
-typedef struct {
- unsigned char mode;
- unsigned char type;
- unsigned char query;
-} RIL_OEMHookSvcEnterMode;
-
-typedef struct {
- unsigned char mode;
-} RIL_OEMHookSvcEndMode;
-
-typedef struct {
- unsigned char key;
- unsigned char query;
-} RIL_OEMHookSvcKey;
-
-struct ril_oem_hook_svc_session {
- RIL_Token token;
- void *display_screen;
- size_t display_screen_length;
+ int enabled;
+ int attached;
+
+ char *apn;
+ char *username;
+ char *password;
+
+ char *iface;
+ char *ip;
+ char *gateway;
+ char *subnet_mask;
+ char *dns1;
+ char *dns2;
};
-void ipc_svc_display_screen(struct ipc_message_info *info);
-void ril_request_oem_hook_raw(RIL_Token t, void *data, int length);
-
-/* NET */
-
-void ril_plmn_split(char *plmn_data, char **plmn, unsigned int *mcc, unsigned int *mnc);
-void ril_plmn_string(char *plmn_data, char *response[3]);
-unsigned char ril_plmn_act_get(char *plmn_data);
-void ril_request_operator(RIL_Token t);
-void ipc_net_current_plmn(struct ipc_message_info *message);
-#if RIL_VERSION >= 6
-void ril_request_voice_registration_state(RIL_Token t);
-void ril_request_data_registration_state(RIL_Token t);
-#else
-void ril_request_registration_state(RIL_Token t);
-void ril_request_gprs_registration_state(RIL_Token t);
-#endif
-void ipc_net_regist(struct ipc_message_info *message);
-void ril_request_query_available_networks(RIL_Token t);
-void ipc_net_plmn_list(struct ipc_message_info *info);
-void ril_request_get_preferred_network_type(RIL_Token t);
-void ril_request_set_preferred_network_type(RIL_Token t, void *data, size_t length);
-void ipc_net_mode_sel(struct ipc_message_info *info);
-void ril_request_query_network_selection_mode(RIL_Token t);
-void ipc_net_plmn_sel(struct ipc_message_info *info);
-void ril_request_set_network_selection_automatic(RIL_Token t);
-void ril_request_set_network_selection_manual(RIL_Token t, void *data, size_t length);
-
-/* SMS */
-
-struct ipc_sms_incoming_msg_info {
- char *pdu;
- int length;
-
- unsigned char type;
- unsigned char tpid;
-};
+int ril_data_connection_register(unsigned int cid, char *apn, char *username,
+ char *password, char *iface);
+int ril_data_connection_unregister(struct ril_data_connection *data_connection);
+int ril_data_connection_flush(void);
+struct ril_data_connection *ril_data_connection_find_cid(unsigned int cid);
+struct ril_data_connection *ril_data_connection_find_token(RIL_Token token);
+struct ril_data_connection *ril_data_connection_start(char *apn, char *username,
+ char *password);
+int ril_data_connection_stop(struct ril_data_connection *data_connection);
+int ril_data_connection_enable(struct ril_data_connection *data_connection);
+int ril_data_connection_disable(struct ril_data_connection *data_connection);
+int ipc_gprs_define_pdp_context_callback(struct ipc_message *message);
+int ril_request_setup_data_call(void *data, size_t size, RIL_Token token);
+int ipc_gprs_ps(struct ipc_message *message);
+int ipc_gprs_pdp_context(struct ipc_message *message);
+int ril_request_data_call_list(void *data, size_t size, RIL_Token token);
+int ipc_gprs_pdp_context_callback(struct ipc_message *message);
+int ril_request_deactivate_data_call(void *data, size_t size, RIL_Token token);
+int ipc_gprs_ip_configuration(struct ipc_message *message);
+int ipc_gprs_hsdpa_status(struct ipc_message *message);
+int ipc_gprs_call_status(struct ipc_message *message);
+int ril_request_last_data_call_fail_cause(void *data, size_t size,
+ RIL_Token token);
-struct ril_request_send_sms_info {
- char *pdu;
- int pdu_length;
- unsigned char *smsc;
- int smsc_length;
+/*
+ * RFS
+ */
- RIL_Token token;
-};
+int ipc_rfs_nv_read_item(struct ipc_message *message);
+int ipc_rfs_nv_write_item(struct ipc_message *message);
-int ril_request_send_sms_register(char *pdu, int pdu_length, unsigned char *smsc, int smsc_length, RIL_Token t);
-void ril_request_send_sms_unregister(struct ril_request_send_sms_info *send_sms);
-struct ril_request_send_sms_info *ril_request_send_sms_info_find(void);
-struct ril_request_send_sms_info *ril_request_send_sms_info_find_token(RIL_Token t);
-
-void ril_request_send_sms_next(void);
-void ril_request_send_sms_complete(RIL_Token t, char *pdu, int pdu_length, unsigned char *smsc, int smsc_length);
-void ril_request_send_sms(RIL_Token t, void *data, size_t length);
-void ril_request_send_sms_expect_more(RIL_Token t, void *data, size_t length);
-void ipc_sms_svc_center_addr(struct ipc_message_info *info);
-void ipc_sms_send_msg_complete(struct ipc_message_info *info);
-void ipc_sms_send_msg(struct ipc_message_info *info);
-
-int ipc_sms_incoming_msg_register(char *pdu, int length, unsigned char type, unsigned char tpid);
-void ipc_sms_incoming_msg_unregister(struct ipc_sms_incoming_msg_info *incoming_msg);
-struct ipc_sms_incoming_msg_info *ipc_sms_incoming_msg_info_find(void);
-
-void ipc_sms_incoming_msg_complete(char *pdu, int length, unsigned char type, unsigned char tpid);
-void ipc_sms_incoming_msg(struct ipc_message_info *info);
-void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t length);
-void ipc_sms_deliver_report(struct ipc_message_info *info);
-
-void ril_request_write_sms_to_sim(RIL_Token token, void *data, size_t size);
-void ipc_sms_save_msg(struct ipc_message_info *info);
-void ril_request_delete_sms_on_sim(RIL_Token token, void *data, size_t size);
-void ipc_sms_del_msg(struct ipc_message_info *info);
-
-int ril_sms_send(char *number, char *message);
-
-void ipc_sms_device_ready(struct ipc_message_info *info);
-
-/* Call */
-
-void ipc_call_incoming(struct ipc_message_info *info);
-void ipc_call_status(struct ipc_message_info *info);
-void ril_request_dial(RIL_Token t, void *data, size_t length);
-void ril_request_get_current_calls(RIL_Token t);
-void ipc_call_list(struct ipc_message_info *info);
-void ril_request_hangup(RIL_Token t);
-void ril_request_answer(RIL_Token t);
-void ril_request_last_call_fail_cause(RIL_Token t);
-void ril_request_dtmf(RIL_Token t, void *data, int length);
-void ipc_call_burst_dtmf(struct ipc_message_info *info);
-void ril_request_dtmf_start(RIL_Token t, void *data, int length);
-void ril_request_dtmf_stop(RIL_Token t);
-
-/* SND */
-
-void ril_request_set_mute(RIL_Token t, void *data, int length);
-void srs_snd_set_call_clock_sync(struct srs_message *message);
-void srs_snd_set_call_volume(struct srs_message *message);
-void srs_snd_set_call_audio_path(struct srs_message *message);
-
-/* GPRS */
-
-struct ril_gprs_connection {
- int cid;
- int enabled;
-#if RIL_VERSION >= 6
- RIL_DataCallFailCause fail_cause;
-#else
- RIL_LastDataCallActivateFailCause fail_cause;
-#endif
- char *interface;
+/*
+ * GEN
+ */
- RIL_Token token;
- struct ipc_gprs_pdp_context_set context;
- struct ipc_gprs_define_pdp_context define_context;
- struct ipc_gprs_ip_configuration ip_configuration;
+struct ipc_gen_phone_res_expect {
+ unsigned char aseq;
+ unsigned short command;
+ int (*callback)(struct ipc_message *message);
+ int complete;
+ int abort;
};
-int ril_gprs_connection_register(int cid);
-void ril_gprs_connection_unregister(struct ril_gprs_connection *gprs_connection);
-struct ril_gprs_connection *ril_gprs_connection_find_cid(int cid);
-struct ril_gprs_connection *ril_gprs_connection_find_token(RIL_Token t);
-struct ril_gprs_connection *ril_gprs_connection_start(void);
-void ril_gprs_connection_stop(struct ril_gprs_connection *gprs_connection);
-
-void ril_request_setup_data_call(RIL_Token t, void *data, int length);
-void ril_request_deactivate_data_call(RIL_Token t, void *data, int length);
-void ipc_gprs_ip_configuration(struct ipc_message_info *info);
-void ipc_gprs_call_status(struct ipc_message_info *info);
-void ril_request_last_data_call_fail_cause(RIL_Token t);
-void ipc_gprs_pdp_context(struct ipc_message_info *info);
-void ril_unsol_data_call_list_changed(void);
-void ril_request_data_call_list(RIL_Token t);
-
-/* RFS */
-
-void ipc_rfs_nv_read_item(struct ipc_message_info *info);
-void ipc_rfs_nv_write_item(struct ipc_message_info *info);
+int ipc_gen_phone_res_expect_register(struct ril_client *client,
+ unsigned char aseq, unsigned short command,
+ int (*callback)(struct ipc_message *message),
+ int complete, int abort);
+int ipc_gen_phone_res_expect_unregister(struct ril_client *client,
+ struct ipc_gen_phone_res_expect *expect);
+int ipc_gen_phone_res_expect_flush(struct ril_client *client);
+struct ipc_gen_phone_res_expect *ipc_gen_phone_res_expect_find_aseq(struct ril_client *client,
+ unsigned char aseq);
+int ipc_gen_phone_res_expect_callback(unsigned char aseq, unsigned short command,
+ int (*callback)(struct ipc_message *message));
+int ipc_gen_phone_res_expect_complete(unsigned char aseq, unsigned short command);
+int ipc_gen_phone_res_expect_abort(unsigned char aseq, unsigned short command);
+int ipc_gen_phone_res(struct ipc_message *message);
#endif
diff --git a/sat.c b/sat.c
deleted file mode 100644
index d05e674..0000000
--- a/sat.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define LOG_TAG "RIL-SAT"
-#include <utils/Log.h>
-
-#include "samsung-ril.h"
-#include "util.h"
-
-void ril_request_report_stk_service_is_running(RIL_Token t)
-{
-#ifndef DISABLE_STK
- ril_request_complete(t, RIL_E_SUCCESS, NULL, 0);
-#else
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-#endif
-}
-
-void ipc_sat_proactive_cmd_unsol(struct ipc_message_info *info)
-{
- char *hexdata;
- int length;
-
- if (info->data == NULL || info->length < 2)
- return;
-
- length = (info->length - 2);
- hexdata = (char *) calloc(1, length * 2 + 1);
-
- bin2hex((unsigned char *) info->data + 2, length, hexdata);
-
- ril_request_unsolicited(RIL_UNSOL_STK_PROACTIVE_COMMAND, hexdata, sizeof(char *));
-
- free(hexdata);
-}
-
-void ipc_sat_proactive_cmd_sol(struct ipc_message_info *info)
-{
- unsigned char sw1, sw2;
-
- if (info->data == NULL || info->length < 2 * sizeof(unsigned char))
- goto error;
-
- sw1 = ((unsigned char*) info->data)[0];
- sw2 = ((unsigned char*) info->data)[1];
-
- if (sw1 == 0x90 && sw2 == 0x00) {
- ril_request_unsolicited(RIL_UNSOL_STK_SESSION_END, NULL, 0);
- } else {
- RIL_LOGE("%s: unhandled response sw1=%02x sw2=%02x", __func__, sw1, sw2);
- }
-
- return;
-
-error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_sat_proactive_cmd(struct ipc_message_info *info)
-{
- if (info->type == IPC_TYPE_INDI) {
- ipc_sat_proactive_cmd_unsol(info);
- } else if (info->type == IPC_TYPE_RESP) {
- ipc_sat_proactive_cmd_sol(info);
- } else {
- RIL_LOGE("%s: unhandled proactive command response type %d",__func__, info->type);
- }
-}
-
-void ril_request_stk_send_terminal_response(RIL_Token t, void *data, size_t length)
-{
- unsigned char buffer[264];
- int size;
-
- if (data == NULL || length < sizeof(char *))
- goto error;
-
- size = strlen(data) / 2;
- if (size > 255) {
- RIL_LOGE("%s: data exceeds maximum length", __func__);
- goto error;
- }
-
- memset(buffer, 0, sizeof(buffer));
-
- buffer[0] = (unsigned char) size;
- hex2bin(data, strlen(data), &buffer[1]);
-
- ipc_fmt_send(IPC_SAT_PROACTIVE_CMD, IPC_TYPE_GET, buffer, sizeof(buffer), ril_request_get_id(t));
-
- ril_request_complete(t, RIL_E_SUCCESS, buffer, sizeof(char *));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_stk_send_envelope_command(RIL_Token t, void *data, size_t length)
-{
- unsigned char buffer[264];
- int size;
-
- if (data == NULL || length < sizeof(char *))
- goto error;
-
- size = strlen(data) / 2;
- if (size > 255) {
- RIL_LOGE("%s: data exceeds maximum length", __func__);
- goto error;
- }
-
- memset(buffer, 0, sizeof(buffer));
-
- buffer[0] = (unsigned char) size;
- hex2bin(data, strlen(data), &buffer[1]);
-
- ipc_fmt_send(IPC_SAT_ENVELOPE_CMD, IPC_TYPE_EXEC, buffer, sizeof(buffer), ril_request_get_id(t));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_sat_envelope_cmd(struct ipc_message_info *info)
-{
- char *hexdata;
- int size;
-
- if (info->data == NULL || info->length < 2)
- goto error;
-
- size = (info->length - 2);
- hexdata = (char *) calloc(1, size * 2 + 1);
-
- bin2hex((unsigned char *) info->data + 2, size, hexdata);
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, hexdata, sizeof(char *));
-
- free(hexdata);
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
diff --git a/sec.c b/sec.c
deleted file mode 100644
index 7d92f26..0000000
--- a/sec.c
+++ /dev/null
@@ -1,981 +0,0 @@
-/*
- * 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>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define LOG_TAG "RIL-SEC"
-#include <utils/Log.h>
-
-#include "samsung-ril.h"
-#include "util.h"
-
-#include <sim.h>
-
-ril_sim_state ipc2ril_sim_state(struct ipc_sec_sim_status_response *pin_status)
-{
- if (pin_status == NULL)
- return -EINVAL;
-
- switch (pin_status->status) {
- case IPC_SEC_SIM_STATUS_LOCK_SC:
- switch (pin_status->facility_lock) {
- case IPC_SEC_FACILITY_LOCK_TYPE_SC_UNLOCKED:
- return SIM_STATE_READY;
- case IPC_SEC_FACILITY_LOCK_TYPE_SC_PIN1_REQ:
- return SIM_STATE_PIN;
- case IPC_SEC_FACILITY_LOCK_TYPE_SC_PUK_REQ:
- return SIM_STATE_PUK;
- case IPC_SEC_FACILITY_LOCK_TYPE_SC_CARD_BLOCKED:
- return SIM_STATE_BLOCKED;
- default:
- RIL_LOGE("Unknown SIM facility lock: 0x%x", pin_status->facility_lock);
- return SIM_STATE_ABSENT;
- }
- break;
- case IPC_SEC_SIM_STATUS_LOCK_FD:
- return SIM_STATE_ABSENT;
- case IPC_SEC_SIM_STATUS_LOCK_PN:
- return SIM_STATE_NETWORK_PERSO;
- case IPC_SEC_SIM_STATUS_LOCK_PU:
- return SIM_STATE_NETWORK_SUBSET_PERSO;
- case IPC_SEC_SIM_STATUS_LOCK_PP:
- return SIM_STATE_SERVICE_PROVIDER_PERSO;
- case IPC_SEC_SIM_STATUS_LOCK_PC:
- return SIM_STATE_CORPORATE_PERSO;
- case IPC_SEC_SIM_STATUS_READY:
- case IPC_SEC_SIM_STATUS_INIT_COMPLETE:
- case IPC_SEC_SIM_STATUS_PB_INIT_COMPLETE:
- return SIM_STATE_READY;
- case IPC_SEC_SIM_STATUS_SIM_LOCK_REQUIRED:
- case IPC_SEC_SIM_STATUS_INSIDE_PF_ERROR:
- case IPC_SEC_SIM_STATUS_CARD_NOT_PRESENT:
- case IPC_SEC_SIM_STATUS_CARD_ERROR:
- return SIM_STATE_ABSENT;
- default:
- RIL_LOGE("Unknown SIM status: 0x%x", pin_status->status);
- return SIM_STATE_ABSENT;
- }
-}
-
-void ril_state_update(ril_sim_state sim_state)
-{
- RIL_RadioState radio_state;
-
- ril_data.state.sim_state = sim_state;
-
- switch (sim_state) {
- case SIM_STATE_READY:
-#if RIL_VERSION >= 7
- radio_state = RADIO_STATE_ON;
-#else
- radio_state = RADIO_STATE_SIM_READY;
-#endif
- break;
- case SIM_STATE_NOT_READY:
- radio_state = RADIO_STATE_SIM_NOT_READY;
- break;
- case SIM_STATE_ABSENT:
- case SIM_STATE_PIN:
- case SIM_STATE_PUK:
- case SIM_STATE_BLOCKED:
- case SIM_STATE_NETWORK_PERSO:
- case SIM_STATE_NETWORK_SUBSET_PERSO:
- case SIM_STATE_CORPORATE_PERSO:
- case SIM_STATE_SERVICE_PROVIDER_PERSO:
- radio_state = RADIO_STATE_SIM_LOCKED_OR_ABSENT;
- break;
- default:
- radio_state = RADIO_STATE_SIM_NOT_READY;
- break;
- }
-
- ril_radio_state_update(radio_state);
-}
-
-#if RIL_VERSION >= 6
-void ipc2ril_card_status(struct ipc_sec_sim_status_response *pin_status, RIL_CardStatus_v6 *card_status)
-#else
-void ipc2ril_card_status(struct ipc_sec_sim_status_response *pin_status, RIL_CardStatus *card_status)
-#endif
-{
- ril_sim_state sim_state;
- int app_status_array_length;
- int app_index;
- int i;
-
- if (pin_status == NULL || card_status == NULL)
- return;
-
- static RIL_AppStatus app_status_array[] = {
- /* SIM_ABSENT = 0 */
- { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- /* SIM_NOT_READY = 1 */
- { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- /* SIM_READY = 2 */
- { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
- NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
- /* SIM_PIN = 3 */
- { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- /* SIM_PUK = 4 */
- { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
- /* SIM_BLOCKED = 4 */
- { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_PERM_BLOCKED, RIL_PINSTATE_UNKNOWN },
- /* SIM_NETWORK_PERSO = 6 */
- { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- /* SIM_NETWORK_SUBSET_PERSO = 7 */
- { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- /* SIM_CORPORATE_PERSO = 8 */
- { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_CORPORATE,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- /* SIM_SERVICE_PROVIDER_PERSO = 9 */
- { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
- NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
- };
-
- app_status_array_length = sizeof(app_status_array) / sizeof(RIL_AppStatus);
-
- if (app_status_array_length > RIL_CARD_MAX_APPS)
- app_status_array_length = RIL_CARD_MAX_APPS;
-
- sim_state = ipc2ril_sim_state(pin_status);
-
- /* Card is assumed to be present if not explicitly absent */
- if (sim_state == SIM_STATE_ABSENT) {
- card_status->card_state = RIL_CARDSTATE_ABSENT;
- } else {
- card_status->card_state = RIL_CARDSTATE_PRESENT;
- }
-
- // FIXME: How do we know that?
- card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
-
- // Initialize the apps
- for (i = 0 ; i < app_status_array_length ; i++) {
- memcpy((void *) &(card_status->applications[i]), (void *) &(app_status_array[i]), sizeof(RIL_AppStatus));
- }
- for (i = app_status_array_length ; i < RIL_CARD_MAX_APPS ; i++) {
- memset((void *) &(card_status->applications[i]), 0, sizeof(RIL_AppStatus));
- }
-
- // sim_state corresponds to the app index on the table
- card_status->gsm_umts_subscription_app_index = (int) sim_state;
- card_status->cdma_subscription_app_index = (int) sim_state;
- card_status->num_applications = app_status_array_length;
-
- RIL_LOGD("Selecting application #%d on %d", (int) sim_state, app_status_array_length);
-}
-
-void ril_tokens_pin_status_dump(void)
-{
- RIL_LOGD("ril_tokens_pin_status_dump:\n\
- \tril_data.tokens.pin_status = %p\n", ril_data.tokens.pin_status);
-}
-
-void ipc_sec_sim_status(struct ipc_message_info *info)
-{
- struct ipc_sec_sim_status_response *pin_status;
- RIL_Token t;
-#if RIL_VERSION >= 6
- RIL_CardStatus_v6 card_status;
-#else
- RIL_CardStatus card_status;
-#endif
- ril_sim_state sim_state;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_sec_sim_status_response))
- goto error;
-
- pin_status = (struct ipc_sec_sim_status_response *) info->data;
- t = ril_request_get_token(info->aseq);
-
- switch (info->type) {
- case IPC_TYPE_NOTI:
- if (ril_radio_state_complete(RADIO_STATE_OFF, RIL_TOKEN_NULL))
- return;
-
- RIL_LOGD("Got UNSOL PIN status message");
-
- if (ril_data.tokens.pin_status != RIL_TOKEN_NULL && ril_data.tokens.pin_status != RIL_TOKEN_DATA_WAITING) {
- RIL_LOGE("Another PIN status Req is in progress, skipping");
- return;
- }
-
- sim_state = ipc2ril_sim_state(pin_status);
- ril_state_update(sim_state);
-
- memcpy(&(ril_data.state.sim_pin_status), pin_status, sizeof(struct ipc_sec_sim_status_response));
-
- ril_data.tokens.pin_status = RIL_TOKEN_DATA_WAITING;
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
- break;
- case IPC_TYPE_RESP:
- RIL_LOGD("Got SOL PIN status message");
-
- if (ril_data.tokens.pin_status != t)
- RIL_LOGE("PIN status tokens mismatch");
-
- sim_state = ipc2ril_sim_state(pin_status);
- ril_state_update(sim_state);
-
- // Better keeping this up to date
- memcpy(&(ril_data.state.sim_pin_status), pin_status, sizeof(struct ipc_sec_sim_status_response));
-
- ipc2ril_card_status(pin_status, &card_status);
- ril_request_complete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
-
- if (ril_data.tokens.pin_status != RIL_TOKEN_DATA_WAITING)
- ril_data.tokens.pin_status = RIL_TOKEN_NULL;
- break;
- default:
- RIL_LOGE("%s: unhandled ipc method: %d", __func__, info->type);
- break;
- }
-
- ril_tokens_pin_status_dump();
-
- return;
-
-error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_get_sim_status(RIL_Token t)
-{
- struct ipc_sec_sim_status_response *pin_status;
-#if RIL_VERSION >= 6
- RIL_CardStatus_v6 card_status;
-#else
- RIL_CardStatus card_status;
-#endif
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- if (ril_data.tokens.pin_status == RIL_TOKEN_DATA_WAITING) {
- RIL_LOGD("Got RILJ request for UNSOL data");
- hex_dump(&(ril_data.state.sim_pin_status), sizeof(struct ipc_sec_sim_status_response));
- pin_status = &(ril_data.state.sim_pin_status);
-
- ipc2ril_card_status(pin_status, &card_status);
-
- ril_request_complete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
-
- ril_data.tokens.pin_status = RIL_TOKEN_NULL;
- } else if (ril_data.tokens.pin_status == RIL_TOKEN_NULL) {
- RIL_LOGD("Got RILJ request for SOL data");
-
- /* Request data to the modem */
- ril_data.tokens.pin_status = t;
-
- ipc_fmt_send_get(IPC_SEC_SIM_STATUS, ril_request_get_id(t));
- } else {
- RIL_LOGE("Another request is going on, returning UNSOL data");
-
- pin_status = &(ril_data.state.sim_pin_status);
-
- ipc2ril_card_status(pin_status, &card_status);
- ril_request_complete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
- }
-
- ril_tokens_pin_status_dump();
-}
-
-void ipc_sec_sim_icc_type(struct ipc_message_info *info)
-{
- struct ipc_sec_sim_icc_type *sim_icc_type;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_sec_sim_icc_type))
- goto error;
-
- sim_icc_type = (struct ipc_sec_sim_icc_type *) info->data;
-
- memcpy(&ril_data.state.sim_icc_type, sim_icc_type, sizeof(struct ipc_sec_sim_icc_type));
-
- return;
-
-error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-/*
- * SIM I/O
- */
-
-int ril_request_sim_io_register(RIL_Token t, unsigned char command, unsigned short fileid,
- unsigned char p1, unsigned char p2, unsigned char p3, void *data, int length,
- struct ril_request_sim_io_info **sim_io_p)
-{
- struct ril_request_sim_io_info *sim_io;
- struct list_head *list_end;
- struct list_head *list;
-
- sim_io = calloc(1, sizeof(struct ril_request_sim_io_info));
- if (sim_io == NULL)
- return -1;
-
- sim_io->command = command;
- sim_io->fileid = fileid;
- sim_io->p1 = p1;
- sim_io->p2 = p2;
- sim_io->p3 = p3;
- sim_io->data = data;
- sim_io->length = length;
- sim_io->waiting = 1;
- sim_io->token = t;
-
- list_end = ril_data.sim_io;
- while (list_end != NULL && list_end->next != NULL)
- list_end = list_end->next;
-
- list = list_head_alloc((void *) sim_io, list_end, NULL);
-
- if (ril_data.sim_io == NULL)
- ril_data.sim_io = list;
-
- if (sim_io_p != NULL)
- *sim_io_p = sim_io;
-
- return 0;
-}
-
-void ril_request_sim_io_unregister(struct ril_request_sim_io_info *sim_io)
-{
- struct list_head *list;
-
- if (sim_io == NULL)
- return;
-
- list = ril_data.sim_io;
- while (list != NULL) {
- if (list->data == (void *) sim_io) {
- memset(sim_io, 0, sizeof(struct ril_request_sim_io_info));
- free(sim_io);
-
- if (list == ril_data.sim_io)
- ril_data.sim_io = list->next;
-
- list_head_free(list);
-
- break;
- }
-list_continue:
- list = list->next;
- }
-}
-
-struct ril_request_sim_io_info *ril_request_sim_io_info_find(void)
-{
- struct ril_request_sim_io_info *sim_io;
- struct list_head *list;
-
- list = ril_data.sim_io;
- while (list != NULL) {
- sim_io = (struct ril_request_sim_io_info *) list->data;
- if (sim_io == NULL)
- goto list_continue;
-
- return sim_io;
-
-list_continue:
- list = list->next;
- }
-
- return NULL;
-}
-
-struct ril_request_sim_io_info *ril_request_sim_io_info_find_token(RIL_Token t)
-{
- struct ril_request_sim_io_info *sim_io;
- struct list_head *list;
-
- list = ril_data.sim_io;
- while (list != NULL) {
- sim_io = (struct ril_request_sim_io_info *) list->data;
- if (sim_io == NULL)
- goto list_continue;
-
- if (sim_io->token == t)
- return sim_io;
-
-list_continue:
- list = list->next;
- }
-
- return NULL;
-}
-
-void ril_request_sim_io_info_clear(struct ril_request_sim_io_info *sim_io)
-{
- if (sim_io == NULL)
- return;
-
- if (sim_io->data != NULL)
- free(sim_io->data);
-}
-
-void ril_request_sim_io_next(void)
-{
- struct ril_request_sim_io_info *sim_io;
- int rc;
-
- ril_data.tokens.sim_io = RIL_TOKEN_NULL;
-
- sim_io = ril_request_sim_io_info_find();
- if (sim_io == NULL)
- return;
-
- sim_io->waiting = 0;
- ril_data.tokens.sim_io = sim_io->token;
-
- ril_request_sim_io_complete(sim_io->token, sim_io->command, sim_io->fileid,
- sim_io->p1, sim_io->p2, sim_io->p3, sim_io->data, sim_io->length);
-
- if (sim_io->data != NULL)
- free(sim_io->data);
- sim_io->data = NULL;
- sim_io->length = 0;
-}
-
-void ril_request_sim_io_complete(RIL_Token t, unsigned char command, unsigned short fileid,
- unsigned char p1, unsigned char p2, unsigned char p3, void *data, int length)
-{
- struct ipc_sec_rsim_access_get *rsim_access = NULL;
- void *rsim_access_data = NULL;
- int rsim_access_length = 0;
-
- rsim_access_length += sizeof(struct ipc_sec_rsim_access_get);
-
- if (data != NULL && length > 0)
- rsim_access_length += length;
-
- rsim_access_data = calloc(1, rsim_access_length);
- rsim_access = (struct ipc_sec_rsim_access_get *) rsim_access_data;
-
- rsim_access->command = command;
- rsim_access->fileid = fileid;
- rsim_access->p1 = p1;
- rsim_access->p2 = p2;
- rsim_access->p3 = p3;
-
- if (data != NULL && length > 0)
- memcpy((void *) ((int) rsim_access_data + sizeof(struct ipc_sec_rsim_access_get)), data, length);
-
- ipc_fmt_send(IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, rsim_access_data, rsim_access_length, ril_request_get_id(t));
-
- free(rsim_access_data);
-}
-
-void ril_request_sim_io(RIL_Token t, void *data, int length)
-{
- struct ril_request_sim_io_info *sim_io_info = NULL;
-#if RIL_VERSION >= 6
- RIL_SIM_IO_v6 *sim_io = NULL;
-#else
- RIL_SIM_IO *sim_io = NULL;
-#endif
- void *sim_io_data = NULL;
- int sim_io_data_length = 0;
- int rc;
-
- if (data == NULL || length < (int) sizeof(*sim_io))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_SIM_NOT_READY, t))
- return;
-
-#if RIL_VERSION >= 6
- sim_io = (RIL_SIM_IO_v6 *) data;
-#else
- sim_io = (RIL_SIM_IO *) data;
-#endif
-
- // SIM IO data should be a string if present
- if (sim_io->data != NULL) {
- sim_io_data_length = strlen(sim_io->data) / 2;
- if (sim_io_data_length > 0) {
- sim_io_data = calloc(1, sim_io_data_length);
- hex2bin(sim_io->data, sim_io_data_length * 2, sim_io_data);
- }
- }
-
- rc = ril_request_sim_io_register(t, sim_io->command, sim_io->fileid,
- sim_io->p1, sim_io->p2, sim_io->p3, sim_io_data, sim_io_data_length,
- &sim_io_info);
- if (rc < 0 || sim_io_info == NULL) {
- RIL_LOGE("Unable to add the request to the list");
-
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- if (sim_io_data != NULL)
- free(sim_io_data);
-
- // Send the next SIM I/O in the list
- ril_request_sim_io_next();
- }
-
- if (ril_data.tokens.sim_io != RIL_TOKEN_NULL) {
- RIL_LOGD("Another SIM I/O is being processed, adding to the list");
- return;
- }
-
- sim_io_info->waiting = 0;
- ril_data.tokens.sim_io = t;
-
- ril_request_sim_io_complete(t, sim_io->command, sim_io->fileid,
- sim_io->p1, sim_io->p2, sim_io->p3, sim_io_data, sim_io_data_length);
-
- if (sim_io_data != NULL)
- free(sim_io_data);
- sim_io_info->data = NULL;
- sim_io_info->length = 0;
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_sec_rsim_access(struct ipc_message_info *info)
-{
- struct ril_request_sim_io_info *sim_io_info;
- struct sim_file_response sim_file_response;
- RIL_SIM_IO_Response sim_io_response;
- struct ipc_sec_rsim_access_response *rsim_access = NULL;
- struct ipc_sec_rsim_access_response_data *rsim_data = NULL;
- void *rsim_access_data = NULL;
- char *sim_response = NULL;
- unsigned char *buf = NULL;
- int offset;
- int i;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_sec_rsim_access_response))
- goto error;
-
- sim_io_info = ril_request_sim_io_info_find_token(ril_request_get_token(info->aseq));
- if (sim_io_info == NULL) {
- RIL_LOGE("Unable to find SIM I/O in the list!");
-
- // Send the next SIM I/O in the list
- ril_request_sim_io_next();
-
- return;
- }
-
- rsim_access = (struct ipc_sec_rsim_access_response *) info->data;
- rsim_access_data = (void *) ((int) info->data + sizeof(struct ipc_sec_rsim_access_response));
-
- memset(&sim_io_response, 0, sizeof(sim_io_response));
- sim_io_response.sw1 = rsim_access->sw1;
- sim_io_response.sw2 = rsim_access->sw2;
-
- switch (sim_io_info->command) {
- case SIM_COMMAND_READ_BINARY:
- case SIM_COMMAND_READ_RECORD:
- if (rsim_access->len <= 0)
- break;
-
- // Copy the data as-is
- sim_response = (char *) malloc(rsim_access->len * 2 + 1);
- bin2hex(rsim_access_data, rsim_access->len, sim_response);
- sim_io_response.simResponse = sim_response;
- break;
- case SIM_COMMAND_GET_RESPONSE:
- if (rsim_access->len < sizeof(struct ipc_sec_rsim_access_response_data))
- break;
-
- // SIM ICC type 1 requires direct copy
- if (ril_data.state.sim_icc_type.type == 1) {
- sim_response = (char *) malloc(rsim_access->len * 2 + 1);
- bin2hex(rsim_access_data, rsim_access->len, sim_response);
- sim_io_response.simResponse = sim_response;
- break;
- }
-
- rsim_data = (struct ipc_sec_rsim_access_response_data *)
- rsim_access_data;
-
- memset(&sim_file_response, 0, sizeof(sim_file_response));
-
- buf = (unsigned char *) rsim_data;
- buf += sizeof(struct ipc_sec_rsim_access_response_data);
- buf += rsim_data->offset - 2;
- if (((int) buf + 1 - (int) rsim_access_data) > rsim_access->len)
- break;
-
- sim_file_response.file_id[0] = buf[0];
- sim_file_response.file_id[1] = buf[1];
-
- buf = (unsigned char *) rsim_data;
- buf += rsim_access->len - 2;
- while ((int) buf > (int) rsim_data + 2) {
- if (buf[0] == 0x88) {
- buf -= 2;
- break;
- }
- buf--;
- }
-
- if ((int) buf <= (int) rsim_data + 2)
- break;
-
- sim_file_response.file_size[0] = buf[0];
- sim_file_response.file_size[1] = buf[1];
-
- // Fallback to EF
- sim_file_response.file_type = SIM_FILE_TYPE_EF;
- for (i = 0 ; i < sim_file_ids_count ; i++) {
- if (sim_io_info->fileid == sim_file_ids[i].file_id) {
- sim_file_response.file_type = sim_file_ids[i].type;
- break;
- }
- }
-
- sim_file_response.access_condition[0] = 0x00;
- sim_file_response.access_condition[1] = 0xff;
- sim_file_response.access_condition[2] = 0xff;
-
- sim_file_response.file_status = 0x01;
- sim_file_response.file_length = 0x02;
-
- switch (rsim_data->file_structure) {
- case IPC_SEC_RSIM_FILE_STRUCTURE_TRANSPARENT:
- sim_file_response.file_structure = SIM_FILE_STRUCTURE_TRANSPARENT;
- break;
- case IPC_SEC_RSIM_FILE_STRUCTURE_LINEAR_FIXED:
- default:
- sim_file_response.file_structure = SIM_FILE_STRUCTURE_LINEAR_FIXED;
- break;
- }
-
- sim_file_response.record_length = rsim_data->record_length;
-
- sim_response = (char *) malloc(sizeof(struct sim_file_response) * 2 + 1);
- bin2hex((void *) &sim_file_response, sizeof(struct sim_file_response), sim_response);
- sim_io_response.simResponse = sim_response;
- break;
- case SIM_COMMAND_UPDATE_BINARY:
- case SIM_COMMAND_UPDATE_RECORD:
- case SIM_COMMAND_SEEK:
- default:
- sim_io_response.simResponse = NULL;
- break;
- }
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &sim_io_response, sizeof(sim_io_response));
-
- if (sim_io_response.simResponse != NULL) {
- RIL_LOGD("SIM response: %s", sim_io_response.simResponse);
- free(sim_io_response.simResponse);
- }
-
- ril_request_sim_io_unregister(sim_io_info);
-
- // Send the next SIM I/O in the list
- ril_request_sim_io_next();
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_sec_sim_status_complete(struct ipc_message_info *info)
-{
- struct ipc_gen_phone_res *phone_res;
- int attempts = -1;
- int rc;
-
- phone_res = (struct ipc_gen_phone_res *) info->data;
-
- rc = ipc_gen_phone_res_check(phone_res);
- if (rc < 0) {
- if ((phone_res->code & 0x00ff) == 0x10) {
- RIL_LOGE("Wrong password!");
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_PASSWORD_INCORRECT, &attempts, sizeof(attempts));
- } else if ((phone_res->code & 0x00ff) == 0x0c) {
- RIL_LOGE("Wrong password and no attempts left!");
-
- attempts = 0;
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_PASSWORD_INCORRECT, &attempts, sizeof(attempts));
-
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
- } else {
- RIL_LOGE("There was an error during pin status complete!");
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- }
- return;
- }
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &attempts, sizeof(attempts));
-}
-
-void ipc_sec_lock_info(struct ipc_message_info *info)
-{
- struct ipc_sec_lock_info_response *lock_info;
- int attempts;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_sec_lock_info_response))
- return;
-
- lock_info = (struct ipc_sec_lock_info_response *) info->data;
-
- /*
- * FIXME: solid way of handling lockinfo and sim unlock response together
- * so we can return the number of attempts left in respondSecPinStatus
- */
-
- if (lock_info->type == IPC_SEC_PIN_TYPE_PIN1) {
- attempts = lock_info->attempts;
- RIL_LOGD("%s: PIN1 %d attempts left", __func__, attempts);
- } else {
- RIL_LOGE("%s: unhandled lock type %d", __func__, lock_info->type);
- }
-}
-
-void ril_request_enter_sim_pin(RIL_Token t, void *data, size_t length)
-{
- struct ipc_sec_pin_status_set pin_status;
- char *pin = ((char **) data)[0];
- unsigned char buf[9];
-
- if (data == NULL || length < (int) sizeof(char *))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- // 1. Send PIN
- if (strlen(data) > 16) {
- RIL_LOGE("%s: pin exceeds maximum length", __func__);
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- }
-
- ipc_sec_pin_status_set_setup(&pin_status, IPC_SEC_PIN_TYPE_PIN1, pin, NULL);
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SEC_SIM_STATUS, ipc_sec_sim_status_complete);
-
- ipc_fmt_send_set(IPC_SEC_SIM_STATUS, ril_request_get_id(t), (unsigned char *) &pin_status, sizeof(pin_status));
-
- // 2. Get lock status
- // FIXME: This is not clean at all
- memset(buf, 0, sizeof(buf));
- buf[0] = 1;
- buf[1] = IPC_SEC_PIN_TYPE_PIN1;
-
- ipc_fmt_send(IPC_SEC_LOCK_INFO, IPC_TYPE_GET, buf, sizeof(buf), ril_request_get_id(t));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_change_sim_pin(RIL_Token t, void *data, size_t length)
-{
- char *password_old;
- char *password_new;
- struct ipc_sec_change_locking_pw_set locking_pw;
-
- if (data == NULL || length < (int) (2 * sizeof(char *)))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_SIM_NOT_READY, t))
- return;
-
- password_old = ((char **) data)[0];
- password_new = ((char **) data)[1];
-
- memset(&locking_pw, 0, sizeof(locking_pw));
-
- locking_pw.facility = IPC_SEC_SIM_STATUS_LOCK_SC;
-
- locking_pw.length_new = strlen(password_new) > sizeof(locking_pw.password_new)
- ? sizeof(locking_pw.password_new)
- : strlen(password_new);
-
- memcpy(locking_pw.password_new, password_new, locking_pw.length_new);
-
- locking_pw.length_old = strlen(password_old) > sizeof(locking_pw.password_old)
- ? sizeof(locking_pw.password_old)
- : strlen(password_old);
-
- memcpy(locking_pw.password_old, password_old, locking_pw.length_old);
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SEC_CHANGE_LOCKING_PW,
- ipc_sec_sim_status_complete);
-
- ipc_fmt_send_set(IPC_SEC_CHANGE_LOCKING_PW, ril_request_get_id(t), (unsigned char *) &locking_pw, sizeof(locking_pw));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_enter_sim_puk(RIL_Token t, void *data, size_t length)
-{
- struct ipc_sec_pin_status_set pin_status;
- char *puk;
- char *pin;
-
- if (data == NULL || length < (int) (2 * sizeof(char *)))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- puk = ((char **) data)[0];
- pin = ((char **) data)[1];
-
- ipc_sec_pin_status_set_setup(&pin_status, IPC_SEC_PIN_TYPE_PIN1, pin, puk);
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SEC_SIM_STATUS,
- ipc_sec_sim_status_complete);
-
- ipc_fmt_send_set(IPC_SEC_SIM_STATUS, ril_request_get_id(t), (unsigned char *) &pin_status, sizeof(pin_status));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_sec_phone_lock(struct ipc_message_info *info)
-{
- int status;
- struct ipc_sec_phone_lock_response *lock;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_sec_phone_lock_response))
- goto error;
-
- lock = (struct ipc_sec_phone_lock_response *) info->data;
- status = lock->status;
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &status, sizeof(status));
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_query_facility_lock(RIL_Token t, void *data, size_t length)
-{
- struct ipc_sec_phone_lock_get lock_request;
- char *facility;
-
- if (data == NULL || length < sizeof(char *))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_SIM_NOT_READY, t))
- return;
-
- facility = ((char **) data)[0];
-
- if (!strcmp(facility, "SC")) {
- lock_request.facility = IPC_SEC_FACILITY_TYPE_SC;
- } else if (!strcmp(facility, "FD")) {
- lock_request.facility = IPC_SEC_FACILITY_TYPE_FD;
- } else if (!strcmp(facility, "PN")) {
- lock_request.facility = IPC_SEC_FACILITY_TYPE_PN;
- } else if (!strcmp(facility, "PU")) {
- lock_request.facility = IPC_SEC_FACILITY_TYPE_PU;
- } else if (!strcmp(facility, "PP")) {
- lock_request.facility = IPC_SEC_FACILITY_TYPE_PP;
- } else if (!strcmp(facility, "PC")) {
- lock_request.facility = IPC_SEC_FACILITY_TYPE_PC;
- } else {
- RIL_LOGE("%s: unsupported facility: %s", __func__, facility);
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- }
-
- ipc_fmt_send(IPC_SEC_PHONE_LOCK, IPC_TYPE_GET, (void *) &lock_request, sizeof(lock_request), ril_request_get_id(t));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-// Both functions were the same
-#define ipc_sec_phone_lock_complete \
- ipc_sec_sim_status_complete
-
-void ril_request_set_facility_lock(RIL_Token t, void *data, size_t length)
-{
- struct ipc_sec_phone_lock_set lock_request;
- char *facility;
- char *lock;
- char *password;
- char *class;
-
- if (data == NULL || length < (int) (4 * sizeof(char *)))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_SIM_NOT_READY, t))
- return;
-
- facility = ((char **) data)[0];
- lock = ((char **) data)[1];
- password = ((char **) data)[2];
- class = ((char **) data)[3];
-
- memset(&lock_request, 0, sizeof(lock_request));
-
- if (!strcmp(facility, "SC")) {
- lock_request.type = IPC_SEC_SIM_STATUS_LOCK_SC;
- } else if (!strcmp(facility, "FD")) {
- lock_request.type = IPC_SEC_SIM_STATUS_LOCK_FD;
- } else if (!strcmp(facility, "PN")) {
- lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PN;
- } else if (!strcmp(facility, "PU")) {
- lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PU;
- } else if (!strcmp(facility, "PP")) {
- lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PP;
- } else if (!strcmp(facility, "PC")) {
- lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PC;
- } else {
- RIL_LOGE("%s: unsupported facility: %s", __func__, facility);
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- }
-
- lock_request.lock = lock[0] == '1' ? 1 : 0;
- lock_request.length = strlen(password) > sizeof(lock_request.password)
- ? sizeof(lock_request.password)
- : strlen(password);
-
- memcpy(lock_request.password, password, lock_request.length);
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SEC_PHONE_LOCK,
- ipc_sec_phone_lock_complete);
-
- ipc_fmt_send(IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, (void *) &lock_request, sizeof(lock_request), ril_request_get_id(t));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
diff --git a/sim.c b/sim.c
new file mode 100644
index 0000000..3d940fa
--- /dev/null
+++ b/sim.c
@@ -0,0 +1,1303 @@
+/*
+ * This file is part of Samsung-RIL.
+ *
+ * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Samsung-RIL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
+
+#include <samsung-ril.h>
+#include <utils.h>
+#include <sim.h>
+
+#if RIL_VERSION >= 6
+RIL_RadioState ipc2ril_sec_pin_status_response(struct ipc_sec_pin_status_response_data *data,
+ RIL_CardStatus_v6 *card_status)
+#else
+RIL_RadioState ipc2ril_sec_pin_status_response(struct ipc_sec_pin_status_response_data *data,
+ RIL_CardStatus *card_status)
+#endif
+{
+ RIL_AppStatus app_statuses[] = {
+ // Absent
+ { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN, NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
+ // Not ready
+ { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN, NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
+ // Ready
+ { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY, NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
+ // PIN lock
+ { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN, NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
+ // PUK lock
+ { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN, NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
+ // PUK locked
+ { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN, NULL, NULL, 0, RIL_PINSTATE_ENABLED_PERM_BLOCKED, RIL_PINSTATE_UNKNOWN },
+ // Perso network
+ { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK, NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
+ // Perso network subset
+ { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET, NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
+ // Perso corporate
+ { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_CORPORATE, NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
+ // Perso service provider
+ { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER, NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
+ };
+ RIL_RadioState radio_state;
+ unsigned int index;
+ unsigned int count;
+ unsigned int i;
+
+ if (data == NULL || card_status == NULL)
+ return 0;
+
+ count = sizeof(app_statuses) / sizeof(RIL_AppStatus);
+
+ switch (data->status) {
+ case IPC_SEC_PIN_STATUS_LOCK_SC:
+ switch (data->facility_lock) {
+ case IPC_SEC_FACILITY_LOCK_TYPE_SC_UNLOCKED:
+ index = 2;
+ break;
+ case IPC_SEC_FACILITY_LOCK_TYPE_SC_PIN1_REQ:
+ index = 3;
+ break;
+ case IPC_SEC_FACILITY_LOCK_TYPE_SC_PUK_REQ:
+ index = 4;
+ break;
+ case IPC_SEC_FACILITY_LOCK_TYPE_SC_CARD_BLOCKED:
+ index = 5;
+ break;
+ default:
+ index = 0;
+ break;
+ }
+ break;
+ case IPC_SEC_PIN_STATUS_LOCK_FD:
+ index = 0;
+ break;
+ case IPC_SEC_PIN_STATUS_LOCK_PN:
+ index = 6;
+ break;
+ case IPC_SEC_PIN_STATUS_LOCK_PU:
+ index = 7;
+ break;
+ case IPC_SEC_PIN_STATUS_LOCK_PP:
+ index = 9;
+ break;
+ case IPC_SEC_PIN_STATUS_LOCK_PC:
+ index = 8;
+ break;
+ case IPC_SEC_PIN_STATUS_READY:
+ case IPC_SEC_PIN_STATUS_INIT_COMPLETE:
+ case IPC_SEC_PIN_STATUS_PB_INIT_COMPLETE:
+ index = 2;
+ break;
+ case IPC_SEC_PIN_STATUS_SIM_LOCK_REQUIRED:
+ case IPC_SEC_PIN_STATUS_INSIDE_PF_ERROR:
+ case IPC_SEC_PIN_STATUS_CARD_NOT_PRESENT:
+ case IPC_SEC_PIN_STATUS_CARD_ERROR:
+ default:
+ index = 0;
+ break;
+ }
+
+ switch (index) {
+ case 1:
+ radio_state = RADIO_STATE_SIM_NOT_READY;
+ break;
+ case 2:
+ radio_state = RADIO_STATE_SIM_READY;
+ break;
+ default:
+ radio_state = RADIO_STATE_SIM_LOCKED_OR_ABSENT;
+ }
+
+#if RIL_VERSION >= 6
+ memset(card_status, 0, sizeof(RIL_CardStatus_v6));
+#else
+ memset(card_status, 0, sizeof(RIL_CardStatus));
+#endif
+
+ if (index == 0)
+ card_status->card_state = RIL_CARDSTATE_ABSENT;
+ else
+ card_status->card_state = RIL_CARDSTATE_PRESENT;
+
+ card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
+
+ card_status->cdma_subscription_app_index = -1;
+#if RIL_VERSION >= 7
+ card_status->ims_subscription_app_index = -1;
+#endif
+
+ memcpy((void *) &card_status->applications[0], (void *) &app_statuses[index], sizeof(RIL_AppStatus));
+
+ card_status->gsm_umts_subscription_app_index = 0;
+ card_status->num_applications = 1;
+
+ RIL_LOGD("%s: Selecting status application %d on %d", __func__, index, count);
+
+ return radio_state;
+}
+
+unsigned char ril2ipc_sec_facility_type(char *facility)
+{
+ if (facility == NULL)
+ return 0;
+
+ if (!strcmp(facility, "SC"))
+ return IPC_SEC_FACILITY_TYPE_SC;
+ else if (!strcmp(facility, "FD"))
+ return IPC_SEC_FACILITY_TYPE_FD;
+ else if (!strcmp(facility, "PN"))
+ return IPC_SEC_FACILITY_TYPE_PN;
+ else if (!strcmp(facility, "PU"))
+ return IPC_SEC_FACILITY_TYPE_PU;
+ else if (!strcmp(facility, "PP"))
+ return IPC_SEC_FACILITY_TYPE_PP;
+ else if (!strcmp(facility, "PC"))
+ return IPC_SEC_FACILITY_TYPE_PC;
+ else
+ return 0;
+}
+
+int ipc_sec_pin_status_callback(struct ipc_message *message)
+{
+ struct ipc_gen_phone_res_data *data;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data))
+ return -1;
+
+ data = (struct ipc_gen_phone_res_data *) message->data;
+
+ rc = ipc_gen_phone_res_check(data);
+ if (rc < 0) {
+ // Return the original SIM status
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
+ } else {
+ // Destroy the original SIM status
+ ril_request_data_free(RIL_REQUEST_GET_SIM_STATUS);
+ }
+
+ return 0;
+}
+
+int ipc_sec_pin_status(struct ipc_message *message)
+{
+ struct ipc_sec_pin_status_response_data *data;
+ struct ipc_sec_pin_status_request_data request_data;
+#if RIL_VERSION >= 6
+ RIL_CardStatus_v6 card_status;
+#else
+ RIL_CardStatus card_status;
+#endif
+ RIL_RadioState radio_state;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_pin_status_response_data))
+ return -1;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ data = (struct ipc_sec_pin_status_response_data *) message->data;
+
+ radio_state = ipc2ril_sec_pin_status_response(data, &card_status);
+ if (radio_state == 0)
+ return 0;
+
+ if (card_status.applications[0].app_type == RIL_APPTYPE_SIM && card_status.applications[0].app_state == RIL_APPSTATE_PIN && ril_data->sim_pin != NULL) {
+ ril_request_data_set_uniq(RIL_REQUEST_GET_SIM_STATUS, (void *) &card_status, sizeof(card_status));
+
+ rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, ril_data->sim_pin, NULL);
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_GET_SIM_STATUS);
+ return 0;
+ }
+
+ rc = ipc_gen_phone_res_expect_callback(message->aseq, IPC_SEC_PIN_STATUS, ipc_sec_pin_status_callback);
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_GET_SIM_STATUS);
+ return 0;
+ }
+
+ rc = ipc_fmt_send(message->aseq, IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_GET_SIM_STATUS);
+ return 0;
+ }
+
+ return 0;
+ }
+
+ ril_radio_state_update(radio_state);
+
+ if (message->type == IPC_TYPE_RESP && ipc_seq_valid(message->aseq)) {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &card_status, sizeof(card_status));
+ } else {
+ ril_request_data_set_uniq(RIL_REQUEST_GET_SIM_STATUS, (void *) &card_status, sizeof(card_status));
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
+ }
+
+ return 0;
+}
+
+int ril_request_get_sim_status(void *data, size_t size, RIL_Token token)
+{
+ void *card_status_data;
+ size_t card_status_size;
+#if RIL_VERSION >= 6
+ RIL_CardStatus_v6 *card_status;
+#else
+ RIL_CardStatus *card_status;
+#endif
+ struct ril_request *request;
+ int rc;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_GET_SIM_STATUS, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ card_status_size = ril_request_data_size_get(RIL_REQUEST_GET_SIM_STATUS);
+ card_status_data = ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS);
+
+#if RIL_VERSION >= 6
+ if (card_status_data != NULL && card_status_size >= sizeof(RIL_CardStatus_v6)) {
+ card_status = (RIL_CardStatus_v6 *) ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS);
+#else
+ if (card_status_data != NULL && card_status_size >= sizeof(RIL_CardStatus)) {
+ card_status = (RIL_CardStatus *) ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS);
+#endif
+ ril_request_complete(token, RIL_E_SUCCESS, card_status_data, card_status_size);
+
+ free(card_status_data);
+
+ return RIL_REQUEST_COMPLETED;
+ } else {
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_GET, NULL, 0);
+ if (rc < 0) {
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ return RIL_REQUEST_COMPLETED;
+ }
+
+ return RIL_REQUEST_HANDLED;
+ }
+}
+
+int ipc_sec_phone_lock(struct ipc_message *message)
+{
+ struct ipc_sec_phone_lock_response_data *data;
+ int active;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_phone_lock_response_data))
+ return -1;
+
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
+
+ data = (struct ipc_sec_phone_lock_response_data *) message->data;
+
+ active = !!data->active;
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &active, sizeof(active));
+
+ return 0;
+}
+
+int ril_request_query_facility_lock(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_sec_phone_lock_request_get_data request_data;
+ char **values = NULL;
+ int rc;
+
+ if (data == NULL || size < 4 * sizeof(char *))
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+
+ request_data.facility_type = ril2ipc_sec_facility_type(values[0]);
+ if (request_data.facility_type == 0)
+ goto error;
+
+ strings_array_free(values, size);
+ values = NULL;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ipc_sec_callback(struct ipc_message *message)
+{
+ struct ipc_sec_lock_infomation_request_data request_data;
+ struct ipc_gen_phone_res_data *data;
+ struct ril_request *request = NULL;
+ void *request_complete_data;
+ size_t request_complete_size;
+ unsigned char facility_type;
+ char **values;
+ int retry_count;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data))
+ return -1;
+
+ data = (struct ipc_gen_phone_res_data *) message->data;
+
+ request = ril_request_find_token(ipc_fmt_request_token(message->aseq));
+ if (request == NULL)
+ goto error;
+
+ if (request->request == RIL_REQUEST_ENTER_SIM_PIN || request->request == RIL_REQUEST_CHANGE_SIM_PIN) {
+ // Grab the count of remaining tries before completing the request
+
+ ril_request_data_set_uniq(request->request, (void *) data, sizeof(struct ipc_gen_phone_res_data));
+
+ rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1);
+ if (rc < 0) {
+ ril_request_data_free(request->request);
+ goto error;
+ }
+
+ rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0) {
+ ril_request_data_free(request->request);
+ goto error;
+ }
+ } else if (request->request == RIL_REQUEST_ENTER_SIM_PIN2 || request->request == RIL_REQUEST_CHANGE_SIM_PIN2) {
+ // Grab the count of remaining tries before completing the request
+
+ ril_request_data_set_uniq(request->request, (void *) data, sizeof(struct ipc_gen_phone_res_data));
+
+ rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2);
+ if (rc < 0) {
+ ril_request_data_free(request->request);
+ goto error;
+ }
+
+ rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0) {
+ ril_request_data_free(request->request);
+ goto error;
+ }
+ } else if (request->request == RIL_REQUEST_SET_FACILITY_LOCK) {
+ values = (char **) request->data;
+
+ request_complete_size = ril_request_data_size_get(RIL_REQUEST_SET_FACILITY_LOCK);
+ request_complete_data = ril_request_data_get(RIL_REQUEST_SET_FACILITY_LOCK);
+
+ rc = ipc_gen_phone_res_check(data);
+
+ if (request_complete_data != NULL && request_complete_size > 0 && rc >= 0) {
+ rc = ipc_gen_phone_res_expect_callback(message->aseq, IPC_SEC_PHONE_LOCK, ipc_sec_callback);
+ if (rc < 0) {
+ strings_array_free(values, request->size);
+ goto error;
+ }
+
+ rc = ipc_fmt_send(message->aseq, IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, request_complete_data, request_complete_size);
+ if (rc < 0) {
+ strings_array_free(values, request->size);
+ goto error;
+ }
+ } else {
+ // When FD facility PIN2 unlock failed, ask the count of remaining tries directly
+
+ facility_type = ril2ipc_sec_facility_type(values[0]);
+
+ strings_array_free(values, request->size);
+
+ // Grab the count of remaining tries before completing the request
+
+ ril_request_data_set_uniq(RIL_REQUEST_SET_FACILITY_LOCK, (void *) data, sizeof(struct ipc_gen_phone_res_data));
+
+ if (facility_type == IPC_SEC_FACILITY_TYPE_FD) {
+ rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2);
+ if (rc < 0) {
+ ril_request_data_free(request->request);
+ goto error;
+ }
+ } else {
+ rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1);
+ if (rc < 0) {
+ ril_request_data_free(request->request);
+ goto error;
+ }
+ }
+
+ rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0) {
+ ril_request_data_free(request->request);
+ goto error;
+ }
+ }
+ } else if (request->request == RIL_REQUEST_SIM_IO) {
+ request_complete_size = ril_request_data_size_get(RIL_REQUEST_SIM_IO);
+ request_complete_data = ril_request_data_get(RIL_REQUEST_SIM_IO);
+
+ rc = ipc_gen_phone_res_check(data);
+ if (rc < 0) {
+ ril_request_complete(request->token, RIL_E_SIM_PIN2, NULL, 0);
+ goto complete;
+ }
+
+ if (request_complete_data != NULL && request_complete_size > 0) {
+ rc = ipc_fmt_send(message->aseq, IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, request_complete_data, request_complete_size);
+ if (rc < 0)
+ goto error;
+ } else {
+ goto error;
+ }
+ } else {
+ retry_count = -1;
+
+ rc = ipc_gen_phone_res_check(data);
+ if (rc < 0) {
+ if ((data->code & 0xff) == 0x10) {
+ RIL_LOGE("%s: Wrong password", __func__);
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count));
+ } else if ((data->code & 0xff) == 0x0c) {
+ RIL_LOGE("%s: Wrong password and no attempts left", __func__);
+ retry_count = 0;
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count));
+ } else {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, &retry_count, sizeof(retry_count));
+ }
+ } else {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &retry_count, sizeof(retry_count));
+ }
+ }
+
+ if (request->request == RIL_REQUEST_ENTER_SIM_PUK || request->request == RIL_REQUEST_ENTER_SIM_PUK2)
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
+
+ goto complete;
+
+error:
+ if (request != NULL)
+ ril_request_complete(request->token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+complete:
+ return 0;
+}
+
+int ril_request_set_facility_lock(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_sec_phone_lock_request_set_data request_data;
+ struct ipc_sec_pin_status_request_data pin_request_data;
+ struct ril_request *request;
+ unsigned char facility_type;
+ unsigned char active;
+ char **values = NULL;
+ int rc;
+
+ if (data == NULL || size < 4 * sizeof(char *))
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_SET_FACILITY_LOCK, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+
+ facility_type = ril2ipc_sec_facility_type(values[0]);
+ if (facility_type == 0)
+ goto error;
+
+ active = values[1][0] == '1';
+
+ rc = ipc_sec_phone_lock_request_set_setup(&request_data, facility_type, active, values[2]);
+ if (rc < 0)
+ goto error;
+
+ if (facility_type == IPC_SEC_FACILITY_TYPE_FD) {
+ // FD facility requires PIN2 unlock first
+
+ rc = ipc_sec_pin_status_setup(&pin_request_data, IPC_SEC_PIN_TYPE_PIN2, values[2], NULL);
+ if (rc < 0)
+ goto error;
+
+ ril_request_data_set_uniq(RIL_REQUEST_SET_FACILITY_LOCK, &request_data, sizeof(request_data));
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_SET_FACILITY_LOCK);
+ goto error;
+ }
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &pin_request_data, sizeof(pin_request_data));
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_SET_FACILITY_LOCK);
+ goto error;
+ }
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+ }
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, ipc_sec_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ril_request_enter_sim_pin(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_sec_pin_status_request_data request_data;
+ struct ril_request *request;
+ char **values = NULL;
+ int rc;
+
+ if (data == NULL || size < 2 * sizeof(char *) || ril_data == NULL)
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PIN, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+ if (values[0] == NULL)
+ goto error;
+
+ if (ril_data->sim_pin != NULL)
+ free(ril_data->sim_pin);
+
+ ril_data->sim_pin = strdup(values[0]);
+
+ rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, values[0], NULL);
+ if (rc < 0)
+ goto error;
+
+ strings_array_free(values, size);
+ values = NULL;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ril_request_enter_sim_puk(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_sec_pin_status_request_data request_data;
+ struct ril_request *request;
+ char **values = NULL;
+ int rc;
+
+ if (data == NULL || size < 2 * sizeof(char *))
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PUK, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+
+ rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, values[1], values[0]);
+ if (rc < 0)
+ goto error;
+
+ strings_array_free(values, size);
+ values = NULL;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ril_request_enter_sim_pin2(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_sec_pin_status_request_data request_data;
+ struct ril_request *request;
+ char **values = NULL;
+ int rc;
+
+ if (data == NULL || size < 2 * sizeof(char *))
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PIN2, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+
+ rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2, values[0], NULL);
+ if (rc < 0)
+ goto error;
+
+ strings_array_free(values, size);
+ values = NULL;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ril_request_enter_sim_puk2(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_sec_pin_status_request_data request_data;
+ struct ril_request *request;
+ char **values = NULL;
+ int rc;
+
+ if (data == NULL || size < 2 * sizeof(char *))
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PUK2, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+
+ rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2, values[1], values[0]);
+ if (rc < 0)
+ goto error;
+
+ strings_array_free(values, size);
+ values = NULL;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ril_request_change_sim_pin(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_sec_change_locking_pw_data request_data;
+ struct ril_request *request;
+ char **values = NULL;
+ int rc;
+
+ if (data == NULL || size < 3 * sizeof(char *))
+ goto error;
+
+ request = ril_request_find_request_status(RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+
+ rc = ipc_sec_change_locking_pw_setup(&request_data, IPC_SEC_FACILITY_TYPE_SC, values[0], values[1]);
+ if (rc < 0)
+ goto error;
+
+ strings_array_free(values, size);
+ values = NULL;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, ipc_sec_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ril_request_change_sim_pin2(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_sec_change_locking_pw_data request_data;
+ struct ril_request *request;
+ char **values = NULL;
+ int rc;
+
+ if (data == NULL || size < 3 * sizeof(char *))
+ goto error;
+
+ request = ril_request_find_request_status(RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ values = (char **) data;
+
+ rc = ipc_sec_change_locking_pw_setup(&request_data, IPC_SEC_FACILITY_TYPE_FD, values[0], values[1]);
+ if (rc < 0)
+ goto error;
+
+ strings_array_free(values, size);
+ values = NULL;
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, ipc_sec_callback);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (values != NULL)
+ strings_array_free(values, size);
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int ipc_sec_rsim_access(struct ipc_message *message)
+{
+ struct ipc_sec_rsim_access_response_header *header;
+ struct ipc_sec_rsim_access_usim_response_header *usim_header;
+ struct sim_file_response sim_file_response;
+ struct ril_request *request;
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
+ RIL_SIM_IO_Response response;
+#if RIL_VERSION >= 6
+ RIL_SIM_IO_v6 *sim_io;
+#else
+ RIL_SIM_IO *sim_io;
+#endif
+ unsigned char *p;
+ unsigned int offset;
+ unsigned int i;
+ void *data;
+ size_t size;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_rsim_access_response_header))
+ return -1;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ return 0;
+
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
+
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+
+ header = (struct ipc_sec_rsim_access_response_header *) message->data;
+
+ size = ipc_sec_rsim_access_size_extract(message->data, message->size);
+ data = ipc_sec_rsim_access_extract(message->data, message->size);
+
+ request = ril_request_find_token(ipc_fmt_request_token(message->aseq));
+#if RIL_VERSION >= 6
+ if (request == NULL || request->data == NULL || request->size < sizeof(RIL_SIM_IO_v6))
+#else
+ if (request == NULL || request->data == NULL || request->size < sizeof(RIL_SIM_IO))
+#endif
+ return 0;
+
+#if RIL_VERSION >= 6
+ sim_io = (RIL_SIM_IO_v6 *) request->data;
+#else
+ sim_io = (RIL_SIM_IO *) request->data;
+#endif
+
+ memset(&response, 0, sizeof(response));
+ response.sw1 = header->sw1;
+ response.sw2 = header->sw2;
+
+ switch (sim_io->command) {
+ case SIM_COMMAND_READ_BINARY:
+ case SIM_COMMAND_READ_RECORD:
+ if (header->length == 0)
+ break;
+
+ response.simResponse = data2string(data, header->length);
+ break;
+ case SIM_COMMAND_GET_RESPONSE:
+ if (header->length == 0)
+ break;
+
+ if (ipc_fmt_data->sim_icc_type_data.type == 0x01) {
+ response.simResponse = data2string(data, header->length);
+ break;
+ }
+
+ if (header->length < sizeof(struct ipc_sec_rsim_access_usim_response_header))
+ break;
+
+ usim_header = (struct ipc_sec_rsim_access_usim_response_header *) data;
+
+ memset(&sim_file_response, 0, sizeof(sim_file_response));
+
+ offset = sizeof(struct ipc_sec_rsim_access_usim_response_header) + usim_header->offset;
+ if (offset > header->length)
+ break;
+
+ offset = usim_header->offset - 2;
+ p = (unsigned char *) usim_header + offset;
+
+ sim_file_response.file_id[0] = p[0];
+ sim_file_response.file_id[1] = p[1];
+
+ offset = header->length - 2;
+ p = (unsigned char *) usim_header;
+
+ while (offset > 2) {
+ if (p[offset] == 0x88) {
+ offset -= 2;
+ break;
+ }
+
+ offset--;
+ }
+
+ if (offset <= 2)
+ break;
+
+ p = (unsigned char *) usim_header + offset;
+
+ sim_file_response.file_size[0] = p[0];
+ sim_file_response.file_size[1] = p[1];
+
+ // Fallback to EF
+ sim_file_response.file_type = SIM_FILE_TYPE_EF;
+ for (i = 0; i < sim_file_ids_count; i++) {
+ if (sim_io->fileid == sim_file_ids[i].file_id) {
+ sim_file_response.file_type = sim_file_ids[i].type;
+ break;
+ }
+ }
+
+ sim_file_response.access_condition[0] = 0x00;
+ sim_file_response.access_condition[1] = 0xff;
+ sim_file_response.access_condition[2] = 0xff;
+
+ sim_file_response.file_status = 0x01;
+ sim_file_response.file_length = 0x02;
+
+ switch (usim_header->file_structure) {
+ case IPC_SEC_RSIM_FILE_STRUCTURE_TRANSPARENT:
+ sim_file_response.file_structure = SIM_FILE_STRUCTURE_TRANSPARENT;
+ break;
+ case IPC_SEC_RSIM_FILE_STRUCTURE_LINEAR_FIXED:
+ default:
+ sim_file_response.file_structure = SIM_FILE_STRUCTURE_LINEAR_FIXED;
+ break;
+ }
+
+ sim_file_response.record_length = usim_header->length;
+
+ response.simResponse = data2string((void *) &sim_file_response, sizeof(sim_file_response));
+ break;
+ case SIM_COMMAND_UPDATE_BINARY:
+ case SIM_COMMAND_UPDATE_RECORD:
+ case SIM_COMMAND_SEEK:
+ default:
+ response.simResponse = NULL;
+ break;
+ }
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &response, sizeof(response));
+
+ if (response.simResponse != NULL)
+ free(response.simResponse);
+
+ return 0;
+}
+
+int ril_request_sim_io(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_sec_rsim_access_request_header request_header;
+ struct ipc_sec_pin_status_request_data pin_request_data;
+ struct ril_request *request;
+#if RIL_VERSION >= 6
+ RIL_SIM_IO_v6 *sim_io = NULL;
+#else
+ RIL_SIM_IO *sim_io = NULL;
+#endif
+ void *sim_io_data = NULL;
+ size_t sim_io_size = 0;
+ void *request_data = NULL;
+ size_t request_size = 0;
+ int pin_request = 0;
+ int rc;
+
+#if RIL_VERSION >= 6
+ if (data == NULL || size < sizeof(RIL_SIM_IO_v6))
+#else
+ if (data == NULL || size < sizeof(RIL_SIM_IO))
+#endif
+ goto error;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
+
+ request = ril_request_find_request_status(RIL_REQUEST_SIM_IO, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
+
+#if RIL_VERSION >= 6
+ sim_io = (RIL_SIM_IO_v6 *) data;
+#else
+ sim_io = (RIL_SIM_IO *) data;
+#endif
+
+ if (sim_io->data != NULL) {
+ sim_io_size = string2data_size(sim_io->data);
+ if (sim_io_size == 0)
+ goto error;
+
+ sim_io_data = string2data(sim_io->data);
+ if (sim_io_data == NULL)
+ goto error;
+ }
+
+ if (sim_io->pin2 != NULL) {
+ // PIN2 unlock first
+
+ pin_request = 1;
+
+ rc = ipc_sec_pin_status_setup(&pin_request_data, IPC_SEC_PIN_TYPE_PIN2, sim_io->pin2, NULL);
+ if (rc < 0)
+ goto error;
+ }
+
+ if (sim_io->path != NULL)
+ free(sim_io->path);
+
+ if (sim_io->data != NULL)
+ free(sim_io->data);
+
+ if (sim_io->pin2 != NULL)
+ free(sim_io->pin2);
+
+#if RIL_VERSION >= 6
+ if (sim_io->aidPtr != NULL)
+ free(sim_io->aidPtr);
+#endif
+
+ memset(&request_header, 0, sizeof(request_header));
+ request_header.command = sim_io->command;
+ request_header.file_id = sim_io->fileid;
+ request_header.p1 = sim_io->p1;
+ request_header.p2 = sim_io->p2;
+ request_header.p3 = sim_io->p3;
+
+ sim_io = NULL;
+
+ request_size = ipc_sec_rsim_access_size_setup(&request_header, sim_io_data, sim_io_size);
+ if (request_size == 0)
+ goto error;
+
+ request_data = ipc_sec_rsim_access_setup(&request_header, sim_io_data, sim_io_size);
+ if (request_data == NULL)
+ goto error;
+
+ if (pin_request) {
+ // PIN2 unlock first
+
+ ril_request_data_set_uniq(RIL_REQUEST_SIM_IO, request_data, request_size);
+
+ rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback);
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_SIM_IO);
+ goto error;
+ }
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &pin_request_data, sizeof(pin_request_data));
+ if (rc < 0) {
+ ril_request_data_free(RIL_REQUEST_SIM_IO);
+ goto error;
+ }
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+ }
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, request_data, request_size);
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ if (sim_io != NULL) {
+ if (sim_io->path != NULL)
+ free(sim_io->path);
+
+ if (sim_io->data != NULL)
+ free(sim_io->data);
+
+ if (sim_io->pin2 != NULL)
+ free(sim_io->pin2);
+
+#if RIL_VERSION >= 6
+ if (sim_io->aidPtr != NULL)
+ free(sim_io->aidPtr);
+#endif
+ }
+
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ if (sim_io_data != NULL && sim_io_size > 0)
+ free(sim_io_data);
+
+ if (request_data != NULL && request_size > 0)
+ free(request_data);
+
+ return rc;
+}
+
+int ipc_sec_sim_icc_type(struct ipc_message *message)
+{
+ struct ipc_sec_sim_icc_type_data *data;
+ struct ril_client *client;
+ struct ipc_fmt_data *ipc_fmt_data;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_sim_icc_type_data))
+ return -1;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL || client->data == NULL)
+ return 0;
+
+ ipc_fmt_data = (struct ipc_fmt_data *) client->data;
+
+ data = (struct ipc_sec_sim_icc_type_data *) message->data;
+
+ if (ipc_fmt_data->sim_icc_type_data.type != data->type)
+ ipc_fmt_data->sim_icc_type_data.type = data->type;
+
+ return 0;
+}
+
+int ipc_sec_lock_infomation(struct ipc_message *message)
+{
+ struct ipc_sec_lock_infomation_response_data *data;
+ struct ipc_gen_phone_res_data *gen_phone_res;
+ int requests[] = { RIL_REQUEST_ENTER_SIM_PIN, RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_ENTER_SIM_PIN2, RIL_REQUEST_CHANGE_SIM_PIN2, RIL_REQUEST_SET_FACILITY_LOCK };
+ void *gen_phone_res_data = NULL;
+ size_t gen_phone_res_size = 0;
+ int retry_count;
+ unsigned int count;
+ unsigned int i;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_lock_infomation_response_data))
+ return -1;
+
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return 0;
+
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
+
+ data = (struct ipc_sec_lock_infomation_response_data *) message->data;
+ if (data->type != IPC_SEC_PIN_TYPE_PIN1 && data->type != IPC_SEC_PIN_TYPE_PIN2)
+ return 0;
+
+ count = sizeof(requests) / sizeof(int);
+
+ for (i = 0; i < count; i++) {
+ gen_phone_res_size = ril_request_data_size_get(requests[i]);
+ if (gen_phone_res_size < sizeof(struct ipc_gen_phone_res_data))
+ continue;
+
+ gen_phone_res_data = ril_request_data_get(requests[i]);
+ if (gen_phone_res_data == NULL)
+ continue;
+
+ break;
+ }
+
+ if (gen_phone_res_data == NULL || gen_phone_res_size < sizeof(struct ipc_gen_phone_res_data))
+ return 0;
+
+ gen_phone_res = (struct ipc_gen_phone_res_data *) gen_phone_res_data;
+
+ retry_count = data->retry_count;
+
+ rc = ipc_gen_phone_res_check(gen_phone_res);
+ if (rc < 0) {
+ if ((gen_phone_res->code & 0xff) == 0x10) {
+ RIL_LOGE("%s: Wrong password and %d attempts left", __func__, retry_count);
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count));
+ } else if ((gen_phone_res->code & 0xff) == 0x0c) {
+ RIL_LOGE("%s: Wrong password and no attempts left", __func__);
+ retry_count = 0;
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count));
+ } else {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, &retry_count, sizeof(retry_count));
+ }
+ } else {
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &retry_count, sizeof(retry_count));
+ }
+
+ free(gen_phone_res_data);
+
+ return 0;
+}
diff --git a/sms.c b/sms.c
index 2b990e3..6f8a8f8 100644
--- a/sms.c
+++ b/sms.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,18 +18,20 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
-#define LOG_TAG "RIL-SMS"
+#include <stdlib.h>
+
+#define LOG_TAG "RIL"
#include <utils/Log.h>
-#include "samsung-ril.h"
-#include "util.h"
+#include <samsung-ril.h>
+#include <utils.h>
-unsigned short ril2ipc_sms_ack_error(int success, int failcause)
+unsigned short ril2ipc_sms_ack(int success, int fail_cause)
{
if (success) {
return IPC_SMS_ACK_NO_ERROR;
} else {
- switch (failcause) {
+ switch (fail_cause) {
case 0xD3:
return IPC_SMS_ACK_PDA_FULL_ERROR;
default:
@@ -38,25 +40,29 @@ unsigned short ril2ipc_sms_ack_error(int success, int failcause)
}
}
-RIL_Errno ipc2ril_sms_ack_error(unsigned short error, int *error_code)
+RIL_Errno ipc2ril_sms_ack_error(unsigned short ack)
{
- // error_code is defined in See 3GPP 27.005, 3.2.5 for GSM/UMTS
-
- if (error_code == NULL)
- return RIL_E_GENERIC_FAILURE;
-
- switch (error) {
+ switch (ack) {
case IPC_SMS_ACK_NO_ERROR:
- *error_code = -1;
return RIL_E_SUCCESS;
default:
- // unknown error
- *error_code = 500;
return RIL_E_GENERIC_FAILURE;
}
}
-unsigned char ril2ipc_sms_save_msg_status(int status)
+int ipc2ril_sms_ack_error_code(unsigned short ack)
+{
+ // Error code is defined in 3GPP 27.005, 3.2.5 for GSM/UMTS
+
+ switch (ack) {
+ case IPC_SMS_ACK_NO_ERROR:
+ return -1;
+ default:
+ return 500;
+ }
+}
+
+unsigned char ril2ipc_sms_status(int status)
{
switch (status) {
case 0:
@@ -68,851 +74,550 @@ unsigned char ril2ipc_sms_save_msg_status(int status)
case 3:
return IPC_SMS_STATUS_STO_SENT;
default:
- return IPC_SMS_STATUS_REC_READ;
+ return 0;
}
}
-/*
- * Outgoing SMS functions
- */
-
-int ril_request_send_sms_register(char *pdu, int pdu_length, unsigned char *smsc, int smsc_length, RIL_Token t)
+int ipc_sms_send_msg(struct ipc_message *message)
{
- struct ril_request_send_sms_info *send_sms;
- struct list_head *list_end;
- struct list_head *list;
+ struct ipc_sms_send_msg_response_data *data;
+ RIL_SMS_Response response;
- send_sms = calloc(1, sizeof(struct ril_request_send_sms_info));
- if (send_sms == NULL)
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_send_msg_response_data))
return -1;
- send_sms->pdu = pdu;
- send_sms->pdu_length = pdu_length;
- send_sms->smsc = smsc;
- send_sms->smsc_length = smsc_length;
- send_sms->token = t;
+ if (!ipc_seq_valid(message->aseq))
+ return 0;
- list_end = ril_data.outgoing_sms;
- while (list_end != NULL && list_end->next != NULL)
- list_end = list_end->next;
+ data = (struct ipc_sms_send_msg_response_data *) message->data;
- list = list_head_alloc((void *) send_sms, list_end, NULL);
+ memset(&response, 0, sizeof(response));
+ response.messageRef = data->id;
+ response.ackPDU = NULL;
- if (ril_data.outgoing_sms == NULL)
- ril_data.outgoing_sms = list;
+ ril_request_complete(ipc_fmt_request_token(message->aseq), ipc2ril_sms_ack_error(data->ack), &response, sizeof(response));
return 0;
}
-void ril_request_send_sms_unregister(struct ril_request_send_sms_info *send_sms)
-{
- struct list_head *list;
-
- if (send_sms == NULL)
- return;
-
- list = ril_data.outgoing_sms;
- while (list != NULL) {
- if (list->data == (void *) send_sms) {
- memset(send_sms, 0, sizeof(struct ril_request_send_sms_info));
- free(send_sms);
-
- if (list == ril_data.outgoing_sms)
- ril_data.outgoing_sms = list->next;
-
- list_head_free(list);
-
- break;
- }
-list_continue:
- list = list->next;
- }
-}
-
-struct ril_request_send_sms_info *ril_request_send_sms_info_find(void)
-{
- struct ril_request_send_sms_info *send_sms;
- struct list_head *list;
-
- list = ril_data.outgoing_sms;
- while (list != NULL) {
- send_sms = (struct ril_request_send_sms_info *) list->data;
- if (send_sms == NULL)
- goto list_continue;
-
- return send_sms;
-
-list_continue:
- list = list->next;
- }
-
- return NULL;
-}
-
-struct ril_request_send_sms_info *ril_request_send_sms_info_find_token(RIL_Token t)
-{
- struct ril_request_send_sms_info *send_sms;
- struct list_head *list;
-
- list = ril_data.outgoing_sms;
- while (list != NULL) {
- send_sms = (struct ril_request_send_sms_info *) list->data;
- if (send_sms == NULL)
- goto list_continue;
-
- if (send_sms->token == t)
- return send_sms;
-
-list_continue:
- list = list->next;
- }
-
- return NULL;
-}
-
-void ril_request_send_sms_info_clear(struct ril_request_send_sms_info *send_sms)
-{
- if (send_sms == NULL)
- return;
-
- if (send_sms->pdu != NULL)
- free(send_sms->pdu);
-
- if (send_sms->smsc != NULL)
- free(send_sms->smsc);
-}
-
-void ril_request_send_sms_next(void)
-{
- struct ril_request_send_sms_info *send_sms;
- RIL_Token t;
- char *pdu;
- int pdu_length;
- unsigned char *smsc;
- int smsc_length;
- int rc;
-
- ril_data.tokens.outgoing_sms = RIL_TOKEN_NULL;
-
- send_sms = ril_request_send_sms_info_find();
- if (send_sms == NULL)
- return;
-
- t = send_sms->token;
- pdu = send_sms->pdu;
- pdu_length = send_sms->pdu_length;
- smsc = send_sms->smsc;
- smsc_length = send_sms->smsc_length;
-
- ril_request_send_sms_unregister(send_sms);
-
- if (pdu == NULL) {
- RIL_LOGE("SMS send request has no valid PDU");
- if (smsc != NULL)
- free(smsc);
- return;
- }
-
- ril_data.tokens.outgoing_sms = t;
- if (smsc == NULL) {
- // We first need to get SMS SVC before sending the message
- RIL_LOGD("We have no SMSC, let's ask one");
-
- rc = ril_request_send_sms_register(pdu, pdu_length, NULL, 0, t);
- if (rc < 0) {
- RIL_LOGE("Unable to add the request to the list");
-
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- if (pdu != NULL)
- free(pdu);
- // Send the next SMS in the list
- ril_request_send_sms_next();
- }
-
- ipc_fmt_send_get(IPC_SMS_SVC_CENTER_ADDR, ril_request_get_id(t));
- } else {
- ril_request_send_sms_complete(t, pdu, pdu_length, smsc, smsc_length);
- if (pdu != NULL)
- free(pdu);
- if (smsc != NULL)
- free(smsc);
- }
-}
-
-void ril_request_send_sms_complete(RIL_Token t, char *pdu, int pdu_length, unsigned char *smsc, int smsc_length)
+int ril_request_send_sms_complete(unsigned char seq, const void *smsc,
+ size_t smsc_size, const void *pdu, size_t pdu_size)
{
- struct ipc_sms_send_msg_request send_msg;
- unsigned char send_msg_type;
-
- unsigned char *pdu_hex;
- int pdu_hex_length;
-
- void *data;
- int length;
-
+ struct ipc_sms_send_msg_request_header request_header;
+ unsigned int count;
+ unsigned int index;
+ void *data = NULL;
+ size_t size = 0;
unsigned char *p;
+ int rc;
- if (pdu == NULL || pdu_length <= 0 || smsc == NULL || smsc_length <= 0)
- goto error;
-
- if ((pdu_length / 2 + smsc_length) > 0xfe) {
- RIL_LOGE("PDU or SMSC too large, aborting");
- goto error;
- }
-
- pdu_hex_length = pdu_length % 2 == 0 ? pdu_length / 2 :
- (pdu_length ^ 1) / 2;
+ if (smsc == NULL || smsc_size == 0 || pdu == NULL || pdu_size == 0)
+ return -1;
- // Length of the final message
- length = sizeof(send_msg) + pdu_hex_length + smsc_length;
+ if (!ipc_seq_valid(seq))
+ return -1;
- RIL_LOGD("Sending SMS message (length: 0x%x)!", length);
+ memset(&request_header, 0, sizeof(request_header));
+ request_header.type = IPC_SMS_TYPE_OUTGOING;
+ request_header.msg_type = IPC_SMS_MSG_TYPE_SINGLE;
- pdu_hex = calloc(1, pdu_hex_length);
- hex2bin(pdu, pdu_length, pdu_hex);
- send_msg_type = IPC_SMS_MSG_SINGLE;
+ p = (unsigned char *) pdu;
- /* PDU operations */
- int pdu_tp_da_index = 2;
- unsigned char pdu_tp_da_len = pdu_hex[pdu_tp_da_index];
+ // PDU TP-DA length
+ p += 2;
- if (pdu_tp_da_len > 0xff / 2) {
- RIL_LOGE("PDU TP-DA Len failed (0x%x)\n", pdu_tp_da_len);
- goto pdu_end;
+ if (*p > (255 / 2)) {
+ RIL_LOGE("PDU TP-DA length failed (0x%x)", *p);
+ goto setup;
}
- RIL_LOGD("PDU TP-DA Len is 0x%x\n", pdu_tp_da_len);
+ // PDU TP-UDH length
+ p += *p;
- int pdu_tp_udh_index = pdu_tp_da_index + pdu_tp_da_len;
- unsigned char pdu_tp_udh_len = pdu_hex[pdu_tp_udh_index];
-
- if (pdu_tp_udh_len > 0xff / 2 || pdu_tp_udh_len < 5) {
- RIL_LOGE("PDU TP-UDH Len failed (0x%x)\n", pdu_tp_udh_len);
- goto pdu_end;
+ if (*p > (255 / 2) || *p < 5) {
+ RIL_LOGE("PDU TP-UDH length failed (0x%x)", *p);
+ goto setup;
}
- RIL_LOGD("PDU TP-UDH Len is 0x%x\n", pdu_tp_udh_len);
-
- int pdu_tp_udh_num_index = pdu_tp_udh_index + 4;
- unsigned char pdu_tp_udh_num = pdu_hex[pdu_tp_udh_num_index];
+ // PDU TO-UDH count
+ p += 4;
+ count = (unsigned int) *p;
- if (pdu_tp_udh_num > 0xf) {
- RIL_LOGE("PDU TP-UDH Num failed (0x%x)\n", pdu_tp_udh_num);
- goto pdu_end;
+ if (count > 0x0f) {
+ RIL_LOGE("PDU TP-UDH count failed (%d)", count);
+ goto setup;
}
- int pdu_tp_udh_seq_index = pdu_tp_udh_index + 5;
- unsigned char pdu_tp_udh_seq = pdu_hex[pdu_tp_udh_seq_index];
+ // PDU TO-UDH index
+ p += 1;
+ index = (unsigned int) *p;
- if (pdu_tp_udh_seq > 0xf || pdu_tp_udh_seq > pdu_tp_udh_num) {
- RIL_LOGE("PDU TP-UDH Seq failed (0x%x)\n", pdu_tp_udh_seq);
- goto pdu_end;
+ if (index > count) {
+ RIL_LOGE("PDU TP-UDH index failed (%d)", index);
+ goto setup;
}
- RIL_LOGD("We are sending message %d on %d\n", pdu_tp_udh_seq, pdu_tp_udh_num);
-
- if (pdu_tp_udh_num > 1) {
- RIL_LOGD("We are sending a multi-part message!");
- send_msg_type = IPC_SMS_MSG_MULTIPLE;
+ if (count > 1) {
+ request_header.msg_type = IPC_SMS_MSG_TYPE_MULTIPLE;
+ RIL_LOGD("Sending multi-part message %d/%d\n", index, count);
}
-pdu_end:
- // Alloc memory for the final message
- data = calloc(1, length);
+setup:
+ size = ipc_sms_send_msg_size_setup(&request_header, smsc, smsc_size, pdu, pdu_size);
+ if (size == 0)
+ goto error;
- // Clear and fill the IPC structure part of the message
- memset(&send_msg, 0, sizeof(struct ipc_sms_send_msg_request));
- send_msg.type = IPC_SMS_TYPE_OUTGOING;
- send_msg.msg_type = send_msg_type;
- send_msg.length = (unsigned char) (pdu_hex_length + smsc_length + 1);
- send_msg.smsc_len = smsc_length;
+ data = ipc_sms_send_msg_setup(&request_header, smsc, smsc_size, pdu, pdu_size);
+ if (data == NULL)
+ goto error;
- // Copy the parts of the message
- p = data;
- memcpy(p, &send_msg, sizeof(send_msg));
- p += sizeof(send_msg);
- memcpy(p, smsc, smsc_length);
- p += smsc_length;
- memcpy(p, pdu_hex, pdu_hex_length);
+ rc = ipc_gen_phone_res_expect_abort(seq, IPC_SMS_SEND_MSG);
+ if (rc < 0)
+ goto error;
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SMS_SEND_MSG, ipc_sms_send_msg_complete);
+ rc = ipc_fmt_send(seq, IPC_SMS_SEND_MSG, IPC_TYPE_EXEC, data, size);
+ if (rc < 0)
+ goto error;
- ipc_fmt_send(IPC_SMS_SEND_MSG, IPC_TYPE_EXEC, data, length, ril_request_get_id(t));
+ rc = 0;
+ goto complete;
- free(pdu_hex);
- free(data);
+error:
+ rc = -1;
- return;
+complete:
+ if (data != NULL && size > 0)
+ free(data);
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- // Send the next SMS in the list
- ril_request_send_sms_next();
+ return rc;
}
-void ril_request_send_sms(RIL_Token t, void *data, size_t length)
+int ril_request_send_sms(void *data, size_t size, RIL_Token token)
{
- char *pdu = NULL;
- int pdu_length;
- unsigned char *smsc = NULL;
- int smsc_length;
+ struct ril_request *request;
+ char **values = NULL;
+ void *smsc = NULL;
+ size_t smsc_size = 0;
+ void *pdu = NULL;
+ size_t pdu_size = 0;
+ unsigned int i;
int rc;
- if (data == NULL || length < (int) (2 * sizeof(char *)))
+ if (data == NULL || size < 2 * sizeof(char *))
goto error;
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
+ rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- pdu = ((char **) data)[1];
- smsc = ((unsigned char **) data)[0];
- pdu_length = 0;
- smsc_length = 0;
+ request = ril_request_find_request_status(RIL_REQUEST_SEND_SMS, RIL_REQUEST_HANDLED);
+ if (request != NULL)
+ return RIL_REQUEST_UNHANDLED;
- if (pdu != NULL) {
- pdu_length = strlen(pdu) + 1;
- pdu = strdup(pdu);
- }
- if (smsc != NULL) {
- smsc_length = strlen((char *) smsc);
- smsc = (unsigned char *) strdup((char *) smsc);
- }
+ values = (char **) data;
+ if (values[1] == NULL)
+ goto error;
- if (ril_data.tokens.outgoing_sms != RIL_TOKEN_NULL) {
- RIL_LOGD("Another outgoing SMS is being processed, adding to the list");
+ pdu_size = string2data_size(values[1]);
+ if (pdu_size == 0)
+ goto error;
- rc = ril_request_send_sms_register(pdu, pdu_length, smsc, smsc_length, t);
- if (rc < 0) {
- RIL_LOGE("Unable to add the request to the list");
+ pdu = string2data(values[1]);
+ if (pdu == NULL)
+ goto error;
+
+ if (values[0] != NULL) {
+ smsc_size = string2data_size(values[0]);
+ if (smsc_size == 0)
goto error;
- }
- return;
+ smsc = string2data(values[0]);
+ if (smsc == NULL)
+ goto error;
}
- ril_data.tokens.outgoing_sms = t;
- if (smsc == NULL) {
- // We first need to get SMS SVC before sending the message
- RIL_LOGD("We have no SMSC, let's ask one");
+ strings_array_free(values, size);
+ values = NULL;
- rc = ril_request_send_sms_register(pdu, pdu_length, NULL, 0, t);
+ if (smsc != NULL && smsc_size > 0) {
+ rc = ril_request_send_sms_complete(ipc_fmt_request_seq(token), pdu, pdu_size, (void *) ((unsigned char *) smsc + sizeof(unsigned char)), ((unsigned char *) smsc)[0]);
+ if (rc < 0)
+ goto error;
+ } else {
+ ril_request_data_set_uniq(RIL_REQUEST_SEND_SMS, pdu, pdu_size);
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SMS_SVC_CENTER_ADDR, IPC_TYPE_GET, NULL, 0);
if (rc < 0) {
- RIL_LOGE("Unable to add the request to the list");
+ ril_request_data_free(RIL_REQUEST_SEND_SMS);
goto error;
}
-
- ipc_fmt_send_get(IPC_SMS_SVC_CENTER_ADDR, ril_request_get_id(t));
- } else {
- ril_request_send_sms_complete(t, pdu, pdu_length, smsc, smsc_length);
- if (pdu != NULL)
- free(pdu);
- if (smsc != NULL)
- free(smsc);
}
- return;
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-
- if (pdu != NULL)
- free(pdu);
- if (smsc != NULL)
- free(smsc);
- // Send the next SMS in the list
- ril_request_send_sms_next();
-}
-
-void ril_request_send_sms_expect_more(RIL_Token t, void *data, size_t length)
-{
- // No particular treatment here, we already have a queue
- ril_request_send_sms(t, data, length);
-}
+ if (values != NULL)
+ strings_array_free(values, size);
-void ipc_sms_svc_center_addr(struct ipc_message_info *info)
-{
- struct ril_request_send_sms_info *send_sms;
- RIL_Token t;
- char *pdu;
- int pdu_length;
- unsigned char *smsc;
- int smsc_length;
- int rc;
-
- if (info->data == NULL || info->length < sizeof(unsigned char))
- goto error;
+ ril_request_complete(token, RIL_E_SMS_SEND_FAIL_RETRY, NULL, 0);
- send_sms = ril_request_send_sms_info_find_token(ril_request_get_token(info->aseq));
- if (send_sms == NULL || send_sms->pdu == NULL || send_sms->pdu_length <= 0) {
- RIL_LOGE("The request wasn't queued, reporting generic error!");
+ rc = RIL_REQUEST_COMPLETED;
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- ril_request_send_sms_info_clear(send_sms);
- ril_request_send_sms_unregister(send_sms);
- // Send the next SMS in the list
- ril_request_send_sms_next();
-
- return;
- }
-
- t = send_sms->token;
- pdu = send_sms->pdu;
- pdu_length = send_sms->pdu_length;
- smsc = (unsigned char *) info->data + sizeof(unsigned char);
- smsc_length = (int) ((unsigned char *) info->data)[0];
+complete:
+ if (smsc != NULL && smsc_size > 0)
+ free(smsc);
- RIL_LOGD("Got SMSC, completing the request");
- ril_request_send_sms_unregister(send_sms);
- ril_request_send_sms_complete(t, pdu, pdu_length, smsc, smsc_length);
- if (pdu != NULL)
+ if (pdu != NULL && pdu_size > 0)
free(pdu);
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_sms_send_msg_complete(struct ipc_message_info *info)
-{
- struct ril_request_send_sms_info *send_sms;
- struct ipc_gen_phone_res *phone_res;
-
- phone_res = (struct ipc_gen_phone_res *) info->data;
- if (ipc_gen_phone_res_check(phone_res) < 0) {
- RIL_LOGE("IPC_GEN_PHONE_RES indicates error, abort request to RILJ");
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- // Send the next SMS in the list
- ril_request_send_sms_next();
- }
+ return rc;
}
-void ipc_sms_send_msg(struct ipc_message_info *info)
+int ipc_sms_incoming_msg(struct ipc_message *message)
{
- struct ipc_sms_send_msg_response *report_msg;
- RIL_SMS_Response response;
- RIL_Errno e;
+ struct ipc_sms_incoming_msg_header *header;
+ void *pdu;
+ size_t pdu_size;
+ char *pdu_string;
- if (info->data == NULL || info->length < sizeof(struct ipc_sms_send_msg_response))
- goto error;
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_incoming_msg_header))
+ return -1;
- report_msg = (struct ipc_sms_send_msg_response *) info->data;
+ header = (struct ipc_sms_incoming_msg_header *) message->data;
- RIL_LOGD("Got ACK for msg_tpid #%d\n", report_msg->msg_tpid);
+ pdu_size = ipc_sms_incoming_msg_pdu_size_extract(message->data, message->size);
+ if (pdu_size == 0)
+ return 0;
- memset(&response, 0, sizeof(response));
- response.messageRef = report_msg->msg_tpid;
- response.ackPDU = NULL;
+ pdu = ipc_sms_incoming_msg_pdu_extract(message->data, message->size);
+ if (pdu == NULL)
+ return 0;
- e = ipc2ril_sms_ack_error(report_msg->error, &response.errorCode);
+ pdu_string = data2string(pdu, pdu_size);
+ if (pdu_string == NULL)
+ return 0;
- ril_request_complete(ril_request_get_token(info->aseq), e, (void *) &response, sizeof(response));
+ ril_request_data_set_uniq(RIL_REQUEST_SMS_ACKNOWLEDGE, &header->id, sizeof(header->id));
- // Send the next SMS in the list
- ril_request_send_sms_next();
+ if (header->type == IPC_SMS_TYPE_STATUS_REPORT)
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, (void *) pdu_string, sizeof(pdu_string));
+ else
+ ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS, (void *) pdu_string, sizeof(pdu_string));
- return;
+ free(pdu_string);
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ return 0;
}
-/*
- * Incoming SMS functions
- */
-
-int ipc_sms_incoming_msg_register(char *pdu, int length, unsigned char type, unsigned char tpid)
+int ipc_sms_save_msg(struct ipc_message *message)
{
- struct ipc_sms_incoming_msg_info *incoming_msg;
- struct list_head *list_end;
- struct list_head *list;
+ struct ipc_sms_save_msg_response_data *data;
- incoming_msg = calloc(1, sizeof(struct ipc_sms_incoming_msg_info));
- if (incoming_msg == NULL)
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_save_msg_response_data))
return -1;
- incoming_msg->pdu = pdu;
- incoming_msg->length = length;
- incoming_msg->type = type;
- incoming_msg->tpid = tpid;
-
- list_end = ril_data.incoming_sms;
- while (list_end != NULL && list_end->next != NULL)
- list_end = list_end->next;
+ if (!ipc_seq_valid(message->aseq))
+ return 0;
- list = list_head_alloc((void *) incoming_msg, list_end, NULL);
+ data = (struct ipc_sms_save_msg_response_data *) message->data;
- if (ril_data.incoming_sms == NULL)
- ril_data.incoming_sms = list;
+ if (data->error)
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ else
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0);
return 0;
}
-void ipc_sms_incoming_msg_unregister(struct ipc_sms_incoming_msg_info *incoming_msg)
+int ril_request_write_sms_to_sim(void *data, size_t size, RIL_Token token)
{
- struct list_head *list;
-
- if (incoming_msg == NULL)
- return;
+ struct ipc_sms_save_msg_request_header request_header;
+ RIL_SMS_WriteArgs *args = NULL;
+ void *smsc = NULL;
+ size_t smsc_size = 0;
+ void *pdu = NULL;
+ size_t pdu_size = 0;
+ void *request_data = NULL;
+ size_t request_size = 0;
+ int rc;
- list = ril_data.incoming_sms;
- while (list != NULL) {
- if (list->data == (void *) incoming_msg) {
- memset(incoming_msg, 0, sizeof(struct ipc_sms_incoming_msg_info));
- free(incoming_msg);
+ if (data == NULL || size < sizeof(RIL_SMS_WriteArgs))
+ goto error;
- if (list == ril_data.incoming_sms)
- ril_data.incoming_sms = list->next;
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- list_head_free(list);
+ args = (RIL_SMS_WriteArgs *) data;
+ if (args->pdu == NULL) {
+ if (args->smsc != NULL)
+ free(args->smsc);
- break;
- }
-list_continue:
- list = list->next;
+ goto error;
}
-}
-struct ipc_sms_incoming_msg_info *ipc_sms_incoming_msg_info_find(void)
-{
- struct ipc_sms_incoming_msg_info *incoming_msg;
- struct list_head *list;
+ memset(&request_header, 0, sizeof(request_header));
+ request_header.status = ril2ipc_sms_status(args->status);
- list = ril_data.incoming_sms;
- while (list != NULL) {
- incoming_msg = (struct ipc_sms_incoming_msg_info *) list->data;
- if (incoming_msg == NULL)
- goto list_continue;
+ pdu_size = string2data_size(args->pdu);
+ if (pdu_size == 0) {
+ free(args->pdu);
- return incoming_msg;
+ if (args->smsc != NULL)
+ free(args->smsc);
-list_continue:
- list = list->next;
+ goto error;
}
- return NULL;
-}
-
-void ipc_sms_incoming_msg_next(void)
-{
- struct ipc_sms_incoming_msg_info *incoming_msg;
+ pdu = string2data(args->pdu);
+ if (pdu == NULL) {
+ free(args->pdu);
- ril_data.state.sms_incoming_msg_tpid = 0;
+ if (args->smsc != NULL)
+ free(args->smsc);
- incoming_msg = ipc_sms_incoming_msg_info_find();
- if (incoming_msg == NULL)
- return;
+ goto error;
+ }
- ipc_sms_incoming_msg_complete(incoming_msg->pdu, incoming_msg->length, incoming_msg->type, incoming_msg->tpid);
- ipc_sms_incoming_msg_unregister(incoming_msg);
-}
+ free(args->pdu);
-void ipc_sms_incoming_msg_complete(char *pdu, int length, unsigned char type, unsigned char tpid)
-{
- if (pdu == NULL || length <= 0)
- return;
+ if (args->smsc == NULL)
+ goto setup;
- ril_data.state.sms_incoming_msg_tpid = tpid;
+ smsc_size = string2data_size(args->smsc);
+ if (smsc_size == 0) {
+ free(args->smsc);
- if (type == IPC_SMS_TYPE_POINT_TO_POINT) {
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS, pdu, length);
- } else if (type == IPC_SMS_TYPE_STATUS_REPORT) {
- ril_request_unsolicited(RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, pdu, length);
- } else {
- RIL_LOGE("Unhandled message type: %x", type);
+ goto error;
}
- free(pdu);
-}
-
-void ipc_sms_incoming_msg(struct ipc_message_info *info)
-{
- struct ipc_sms_incoming_msg *msg;
- unsigned char *pdu_hex;
- char *pdu;
- int length;
- int rc;
+ smsc = string2data(args->smsc);
+ if (smsc == NULL) {
+ free(args->smsc);
- if (info->data == NULL || info->length < sizeof(struct ipc_sms_incoming_msg))
goto error;
-
- msg = (struct ipc_sms_incoming_msg *) info->data;
- pdu_hex = ((unsigned char *) info->data + sizeof(struct ipc_sms_incoming_msg));
-
- length = msg->length * 2 + 1;
- pdu = (char *) calloc(1, length);
-
- bin2hex(pdu_hex, msg->length, pdu);
-
- if (ril_data.state.sms_incoming_msg_tpid != 0) {
- RIL_LOGD("Another message is waiting ACK, queuing");
- rc = ipc_sms_incoming_msg_register(pdu, length, msg->type, msg->msg_tpid);
- if (rc < 0)
- RIL_LOGE("Unable to register incoming msg");
-
- return;
}
- ipc_sms_incoming_msg_complete(pdu, length, msg->type, msg->msg_tpid);
-
- return;
-
-error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_sms_acknowledge(RIL_Token t, void *data, size_t length)
-{
- struct ipc_sms_deliver_report_request report_msg;
- int success, fail_cause;
+ free(args->smsc);
- if (data == NULL || length < 2 * sizeof(int))
+setup:
+ request_size = ipc_sms_save_msg_size_setup(&request_header, smsc, smsc_size, pdu, pdu_size);
+ if (request_size == 0)
goto error;
- if (ril_data.state.sms_incoming_msg_tpid == ril_data.state.ril_sms_tpid) {
- ril_data.state.ril_sms_tpid = 0;
-
- ril_request_complete(t, RIL_E_SUCCESS, NULL, 0);
-
- ipc_sms_incoming_msg_next();
-
- return;
- }
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
+ request_data = ipc_sms_save_msg_setup(&request_header, smsc, smsc_size, pdu, pdu_size);
+ if (request_data == NULL)
+ goto error;
- success = ((int *) data)[0];
- fail_cause = ((int *) data)[1];
+ rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_SMS_SAVE_MSG);
+ if (rc < 0)
+ goto error;
- if (ril_data.state.sms_incoming_msg_tpid == 0) {
- RIL_LOGE("There is no SMS message to ACK!");
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SMS_SAVE_MSG, IPC_TYPE_EXEC, request_data, request_size);
+ if (rc < 0)
goto error;
- }
- report_msg.type = IPC_SMS_TYPE_STATUS_REPORT;
- report_msg.error = ril2ipc_sms_ack_error(success, fail_cause);
- report_msg.msg_tpid = ril_data.state.sms_incoming_msg_tpid;
- report_msg.unk = 0;
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
- ipc_gen_phone_res_expect_to_abort(ril_request_get_id(t), IPC_SMS_DELIVER_REPORT);
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
- ipc_fmt_send(IPC_SMS_DELIVER_REPORT, IPC_TYPE_EXEC, (void *) &report_msg, sizeof(report_msg), ril_request_get_id(t));
+ rc = RIL_REQUEST_COMPLETED;
- ipc_sms_incoming_msg_next();
+complete:
+ if (smsc != NULL && smsc_size > 0)
+ free(smsc);
- return;
+ if (pdu != NULL && pdu_size > 0)
+ free(pdu);
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
+ if (request_data != NULL && request_size > 0)
+ free(request_data);
- ipc_sms_incoming_msg_next();
+ return rc;
}
-void ipc_sms_deliver_report(struct ipc_message_info *info)
+int ipc_sms_del_msg(struct ipc_message *message)
{
- struct ipc_sms_deliver_report_response *report_msg;
- RIL_Errno e;
- int error_code;
+ struct ipc_sms_del_msg_response_data *data;
- if (info->data == NULL || info->length < sizeof(struct ipc_sms_deliver_report_response))
- goto error;
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_del_msg_response_data))
+ return -1;
- report_msg = (struct ipc_sms_deliver_report_response *) info->data;
- e = ipc2ril_sms_ack_error(report_msg->error, &error_code);
+ if (!ipc_seq_valid(message->aseq))
+ return 0;
- ril_request_complete(ril_request_get_token(info->aseq), e, NULL, 0);
+ data = (struct ipc_sms_del_msg_response_data *) message->data;
- return;
+ if (data->error)
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ else
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, NULL, 0);
-error:
- if (info != NULL)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
+ return 0;
}
-void ril_request_write_sms_to_sim(RIL_Token token, void *data, size_t size)
+int ril_request_delete_sms_on_sim(void *data, size_t size, RIL_Token token)
{
- struct ipc_sms_save_msg_request_data *sms_save_msg_request_data;
- RIL_SMS_WriteArgs *args;
- void *buffer = NULL;
- size_t length;
- size_t data_length;
- size_t pdu_length = 0;
- size_t pdu_hex_length = 0;
- size_t smsc_length = 0;
- size_t smsc_hex_length = 0;
- unsigned char *p;
+ struct ipc_sms_del_msg_request_data request_data;
+ int index;
+ int rc;
- if (data == NULL || size < sizeof(RIL_SMS_WriteArgs))
+ if (data == NULL || size < sizeof(int))
goto error;
- if (ril_radio_state_complete(RADIO_STATE_OFF, token))
- return;
-
- args = (RIL_SMS_WriteArgs *) data;
-
- if (args->pdu != NULL) {
- pdu_length = strlen(args->pdu);
- pdu_hex_length = pdu_length % 2 == 0 ? pdu_length / 2 : (pdu_length ^ 1) / 2;
- }
-
- if (args->smsc != NULL) {
- smsc_length = strlen(args->smsc);
- smsc_hex_length = smsc_length % 2 == 0 ? smsc_length / 2 : (smsc_length ^ 1) / 2;
- }
-
- data_length = pdu_hex_length + smsc_hex_length;
- if (data_length == 0 || data_length > 0xff)
+ index = *((int *) data);
+ if (index == 0)
goto error;
- length = sizeof(struct ipc_sms_save_msg_request_data) + data_length;
- buffer = malloc(length);
-
- sms_save_msg_request_data = (struct ipc_sms_save_msg_request_data *) buffer;
-
- memset(sms_save_msg_request_data, 0, sizeof(struct ipc_sms_save_msg_request_data));
- sms_save_msg_request_data->unknown = 0x02;
- sms_save_msg_request_data->index = 12 - 1;
- sms_save_msg_request_data->status = ril2ipc_sms_save_msg_status(args->status);
- sms_save_msg_request_data->length = (unsigned char) (data_length & 0xff);
-
- p = (unsigned char *) buffer + sizeof(struct ipc_sms_save_msg_request_data);
-
- if (args->smsc != NULL && smsc_length > 0) {
- hex2bin(args->smsc, smsc_length, p);
- p += smsc_hex_length;
- }
-
- if (args->pdu != NULL && pdu_length > 0) {
- hex2bin(args->pdu, pdu_length, p);
- p += pdu_hex_length;
- }
+ rc = ipc_sms_del_msg_setup(&request_data, (unsigned short) (index - 1));
+ if (rc < 0)
+ goto error;
- ipc_gen_phone_res_expect_to_abort(ril_request_get_id(token), IPC_SMS_SAVE_MSG);
+ rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_SMS_DEL_MSG);
+ if (rc < 0)
+ goto error;
- ipc_fmt_send(IPC_SMS_SAVE_MSG, IPC_TYPE_EXEC, buffer, length, ril_request_get_id(token));
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SMS_DEL_MSG, IPC_TYPE_EXEC, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+ rc = RIL_REQUEST_HANDLED;
goto complete;
error:
ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+ rc = RIL_REQUEST_COMPLETED;
+
complete:
- if (buffer != NULL)
- free(buffer);
+ return rc;
}
-void ipc_sms_save_msg(struct ipc_message_info *info)
+int ipc_sms_deliver_report(struct ipc_message *message)
{
- struct ipc_sms_save_msg_response_data *sms_save_msg_response_data;
+ struct ipc_sms_deliver_report_response_data *data;
+ RIL_Errno error;
- if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_sms_save_msg_response_data))
- return;
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_deliver_report_response_data))
+ return -1;
- sms_save_msg_response_data = (struct ipc_sms_save_msg_response_data *) info->data;
+ if (!ipc_seq_valid(message->aseq))
+ return 0;
- if (sms_save_msg_response_data->error)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- else
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0);
+ data = (struct ipc_sms_deliver_report_response_data *) message->data;
+
+ error = ipc2ril_sms_ack_error(data->ack);
+
+ ril_request_complete(ipc_fmt_request_token(message->aseq), error, NULL, 0);
+
+ return 0;
}
-void ril_request_delete_sms_on_sim(RIL_Token token, void *data, size_t size)
+int ril_request_sms_acknowledge(void *data, size_t size, RIL_Token token)
{
- struct ipc_sms_del_msg_request_data sms_del_msg_request_data;
- int index = 0;
+ struct ipc_sms_deliver_report_request_data report_data;
+ void *id_data;
+ size_t id_size;
+ unsigned char id;
+ int *values;
+ int rc;
- if (data == NULL || size < sizeof(index))
+ if (data == NULL || size < 2 * sizeof(int))
goto error;
- if (ril_radio_state_complete(RADIO_STATE_OFF, token))
- return;
+ rc = ril_radio_state_check(RADIO_STATE_SIM_READY);
+ if (rc < 0)
+ return RIL_REQUEST_UNHANDLED;
- index = *((int *) data);
+ values = (int *) data;
- if (index <= 0 || index > 0xffff)
+ id_size = ril_request_data_size_get(RIL_REQUEST_SMS_ACKNOWLEDGE);
+ id_data = ril_request_data_get(RIL_REQUEST_SMS_ACKNOWLEDGE);
+
+ if (id_data == NULL || id_size == 0) {
+ RIL_LOGE("%s: No SMS left to acknowledge", __func__);
goto error;
+ }
- memset(&sms_del_msg_request_data, 0, sizeof(sms_del_msg_request_data));
- sms_del_msg_request_data.unknown = 0x02;
- sms_del_msg_request_data.index = (short) index - 1;
+ id = *((unsigned char *) id_data);
- ipc_gen_phone_res_expect_to_abort(ril_request_get_id(token), IPC_SMS_DEL_MSG);
+ free(id_data);
- ipc_fmt_send(IPC_SMS_DEL_MSG, IPC_TYPE_EXEC, (unsigned char *) &sms_del_msg_request_data, sizeof(sms_del_msg_request_data), ril_request_get_id(token));
+ memset(&report_data, 0, sizeof(report_data));
+ report_data.type = IPC_SMS_TYPE_STATUS_REPORT;
+ report_data.ack = ril2ipc_sms_ack(values[0], values[1]);
+ report_data.id = id;
- return;
+ rc = ipc_gen_phone_res_expect_abort(ipc_fmt_request_seq(token), IPC_SMS_DELIVER_REPORT);
+ if (rc < 0)
+ goto error;
-error:
- ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SMS_DELIVER_REPORT, IPC_TYPE_EXEC, (void *) &report_data, sizeof(report_data));
+ if (rc < 0)
+ goto error;
-void ipc_sms_del_msg(struct ipc_message_info *info)
-{
- struct ipc_sms_del_msg_response_data *sms_del_msg_response_data;
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
- if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_sms_del_msg_response_data))
- return;
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
- sms_del_msg_response_data = (struct ipc_sms_del_msg_response_data *) info->data;
+ rc = RIL_REQUEST_COMPLETED;
- if (sms_del_msg_response_data->error)
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- else
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0);
+complete:
+ return rc;
}
-/*
- * RIL SMS
- */
-
-int ril_sms_send(char *number, char *message)
+int ipc_sms_svc_center_addr(struct ipc_message *message)
{
- char *pdu;
- size_t length;
+ struct ipc_sms_svc_center_addr_header *header;
+ void *smsc = NULL;
+ size_t smsc_size = 0;
+ void *pdu = NULL;
+ size_t pdu_size = 0;
int rc;
- pdu = pdu_create(number, message);
- if (pdu == NULL)
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sms_svc_center_addr_header))
return -1;
- length = strlen(pdu);
- if (length == 0)
- return -1;
+ if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq))
+ return 0;
- ril_data.state.ril_sms_tpid = RIL_SMS_TPID;
+ header = (struct ipc_sms_svc_center_addr_header *) message->data;
+ if (header->length == 0 || header->length > (message->size - sizeof(struct ipc_sms_svc_center_addr_header)))
+ goto error;
- if (ril_data.state.sms_incoming_msg_tpid != 0) {
- RIL_LOGD("Another message is waiting ACK, queuing");
- rc = ipc_sms_incoming_msg_register(pdu, length, IPC_SMS_TYPE_POINT_TO_POINT, ril_data.state.ril_sms_tpid);
- if (rc < 0) {
- RIL_LOGE("Unable to register incoming msg");
- return -1;
- }
+ pdu_size = ril_request_data_size_get(RIL_REQUEST_SEND_SMS);
+ if (pdu_size == 0)
+ goto error;
- return 0;
- }
+ pdu = ril_request_data_get(RIL_REQUEST_SEND_SMS);
+ if (pdu == NULL)
+ goto error;
- ipc_sms_incoming_msg_complete(pdu, length, IPC_SMS_TYPE_POINT_TO_POINT, ril_data.state.ril_sms_tpid);
+ smsc_size = ipc_sms_svc_center_addr_smsc_size_extract(message->data, message->size);
+ if (smsc_size == 0)
+ goto error;
- return 0;
-}
+ smsc = ipc_sms_svc_center_addr_smsc_extract(message->data, message->size);
+ if (smsc == NULL)
+ goto error;
-/*
- * Apparently non-SMS-messages-related function
- */
+ rc = ril_request_send_sms_complete(message->aseq, smsc, smsc_size, pdu, pdu_size);
+ if (rc < 0)
+ goto error;
-void ipc_sms_device_ready(struct ipc_message_info *info)
-{
-#if RIL_VERSION >= 7
- if (ril_data.state.radio_state == RADIO_STATE_ON) {
-#else
- if (ril_data.state.radio_state == RADIO_STATE_SIM_READY) {
-#endif
- ipc_fmt_send(IPC_SMS_DEVICE_READY, IPC_TYPE_SET, NULL, 0, info->aseq);
- }
+ goto complete;
- ril_tokens_check();
+error:
+ ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SMS_SEND_FAIL_RETRY, NULL, 0);
+
+complete:
+ if (pdu != NULL)
+ free(pdu);
+
+ return 0;
}
diff --git a/snd.c b/snd.c
deleted file mode 100644
index f71da7f..0000000
--- a/snd.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * This file is part of Samsung-RIL.
- *
- * Copyright (C) 2011-2013 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define LOG_TAG "RIL-SND"
-#include <utils/Log.h>
-
-#include "samsung-ril.h"
-#include "util.h"
-
-unsigned char srs2ipc_call_type(int type)
-{
- switch (type) {
- case SRS_SND_TYPE_VOICE:
- return IPC_SND_VOLUME_TYPE_VOICE;
- case SRS_SND_TYPE_SPEAKER:
- return IPC_SND_VOLUME_TYPE_SPEAKER;
- case SRS_SND_TYPE_HEADSET:
- return IPC_SND_VOLUME_TYPE_HEADSET;
- case SRS_SND_TYPE_BTVOICE:
- return IPC_SND_VOLUME_TYPE_BTVOICE;
- default:
- RIL_LOGE("Unknown call type: 0x%x", type);
- return 0;
- }
-}
-
-unsigned char srs2ipc_audio_path(int path)
-{
- switch (path) {
- case SRS_SND_PATH_HANDSET:
- return IPC_SND_AUDIO_PATH_HANDSET;
- case SRS_SND_PATH_HEADSET:
- return IPC_SND_AUDIO_PATH_HEADSET;
- case SRS_SND_PATH_SPEAKER:
- return IPC_SND_AUDIO_PATH_SPEAKER;
- case SRS_SND_PATH_BLUETOOTH:
- return IPC_SND_AUDIO_PATH_BLUETOOTH;
- case SRS_SND_PATH_BLUETOOTH_NO_NR:
- return IPC_SND_AUDIO_PATH_BLUETOOTH_NO_NR;
- case SRS_SND_PATH_HEADPHONE:
- return IPC_SND_AUDIO_PATH_HEADPHONE;
- default:
- RIL_LOGE("Unknown audio path: 0x%x", path);
- return 0;
- }
-}
-
-void ril_request_set_mute(RIL_Token t, void *data, int length)
-{
- int *value;
- unsigned char mute;
-
- if (data == NULL || length < (int) sizeof(int))
- return;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- value = (int *) data;
- mute = *value ? 1 : 0;
-
- RIL_LOGD("Mute is %d\n", mute);
-
- ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_SND_MIC_MUTE_CTRL);
-
- ipc_fmt_send(IPC_SND_MIC_MUTE_CTRL, IPC_TYPE_SET, (void *) &mute, sizeof(mute), ril_request_get_id(t));
-}
-
-void srs_snd_set_call_clock_sync(struct srs_message *message)
-{
- unsigned char *sync;
-
- if (message == NULL || message->data == NULL || message->length < (int) sizeof(unsigned char))
- return;
-
- sync = (unsigned char *) message->data;
-
- RIL_LOGD("Clock sync is 0x%x\n", *sync);
-
- ipc_fmt_send(IPC_SND_CLOCK_CTRL, IPC_TYPE_EXEC, sync, sizeof(unsigned char), ril_request_id_get());
-}
-
-void srs_snd_set_call_volume(struct srs_message *message)
-{
- struct srs_snd_call_volume *call_volume;
- struct ipc_snd_spkr_volume_ctrl volume_ctrl;
-
- if (message == NULL || message->data == NULL || message->length < (int) sizeof(struct srs_snd_call_volume))
- return;
-
- call_volume = (struct srs_snd_call_volume *) message->data;
-
- RIL_LOGD("Call volume for: 0x%x vol = 0x%x\n", call_volume->type, call_volume->volume);
-
- memset(&volume_ctrl, 0, sizeof(volume_ctrl));
- volume_ctrl.type = srs2ipc_call_type(call_volume->type);
- volume_ctrl.volume = call_volume->volume;
-
- ipc_fmt_send(IPC_SND_SPKR_VOLUME_CTRL, IPC_TYPE_SET, (void *) &volume_ctrl, sizeof(volume_ctrl), ril_request_id_get());
-}
-
-void srs_snd_set_call_audio_path(struct srs_message *message)
-{
- int *audio_path;
- unsigned char path;
-
- if (message == NULL || message->data == NULL || message->length < (int) sizeof(int))
- return;
-
- audio_path = (int *) message->data;
- path = srs2ipc_audio_path(*audio_path);
-
- RIL_LOGD("Audio path to: 0x%x\n", path);
-
- ipc_fmt_send(IPC_SND_AUDIO_PATH_CTRL, IPC_TYPE_SET, (void *) &path, sizeof(path), ril_request_id_get());
-}
diff --git a/sound.c b/sound.c
new file mode 100644
index 0000000..22601b3
--- /dev/null
+++ b/sound.c
@@ -0,0 +1,159 @@
+/*
+ * This file is part of Samsung-RIL.
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Samsung-RIL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
+
+#include <samsung-ril.h>
+
+unsigned char srs2ipc_call_type(int type)
+{
+ switch (type) {
+ case SRS_SND_TYPE_VOICE:
+ return IPC_SND_VOLUME_TYPE_VOICE;
+ case SRS_SND_TYPE_SPEAKER:
+ return IPC_SND_VOLUME_TYPE_SPEAKER;
+ case SRS_SND_TYPE_HEADSET:
+ return IPC_SND_VOLUME_TYPE_HEADSET;
+ case SRS_SND_TYPE_BTVOICE:
+ return IPC_SND_VOLUME_TYPE_BTVOICE;
+ default:
+ return IPC_SND_VOLUME_TYPE_VOICE;
+ }
+}
+
+unsigned char srs2ipc_audio_path(int path)
+{
+ switch (path) {
+ case SRS_SND_PATH_HANDSET:
+ return IPC_SND_AUDIO_PATH_HANDSET;
+ case SRS_SND_PATH_HEADSET:
+ return IPC_SND_AUDIO_PATH_HEADSET;
+ case SRS_SND_PATH_SPEAKER:
+ return IPC_SND_AUDIO_PATH_SPEAKER;
+ case SRS_SND_PATH_BLUETOOTH:
+ return IPC_SND_AUDIO_PATH_BLUETOOTH;
+ case SRS_SND_PATH_BLUETOOTH_NO_NR:
+ return IPC_SND_AUDIO_PATH_BLUETOOTH_NO_NR;
+ case SRS_SND_PATH_HEADPHONE:
+ return IPC_SND_AUDIO_PATH_HEADPHONE;
+ default:
+ return IPC_SND_AUDIO_PATH_HANDSET;
+ }
+}
+
+int srs_snd_set_call_volume(struct srs_message *message)
+{
+ struct ipc_snd_spkr_volume_ctrl_data request_data;
+ struct srs_snd_call_volume_data *data;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct srs_snd_call_volume_data))
+ return -1;
+
+ data = (struct srs_snd_call_volume_data *) message->data;
+
+ memset(&request_data, 0, sizeof(request_data));
+ request_data.type = srs2ipc_call_type(data->type);
+ request_data.volume = data->volume;
+
+ rc = ipc_fmt_send(ipc_fmt_seq(), IPC_SND_SPKR_VOLUME_CTRL, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ return 0;
+
+ return 0;
+}
+
+int ril_request_set_mute(void *data, size_t size, RIL_Token token)
+{
+ struct ipc_snd_mic_mute_ctrl_data request_data;
+ int mute;
+ int rc;
+
+ if (data == NULL || size < sizeof(int))
+ goto error;
+
+ mute = *((int *) data);
+
+ memset(&request_data, 0, sizeof(request_data));
+ request_data.mute = !!mute;
+
+ rc = ipc_gen_phone_res_expect_complete(ipc_fmt_request_seq(token), IPC_SND_MIC_MUTE_CTRL);
+ if (rc < 0)
+ goto error;
+
+ rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SND_MIC_MUTE_CTRL, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ goto error;
+
+ rc = RIL_REQUEST_HANDLED;
+ goto complete;
+
+error:
+ ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
+
+ rc = RIL_REQUEST_COMPLETED;
+
+complete:
+ return rc;
+}
+
+int srs_snd_set_call_audio_path(struct srs_message *message)
+{
+ struct ipc_snd_audio_path_ctrl_data request_data;
+ struct srs_snd_call_audio_path_data *data;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct srs_snd_call_audio_path_data))
+ return -1;
+
+ data = (struct srs_snd_call_audio_path_data *) message->data;
+
+ memset(&request_data, 0, sizeof(request_data));
+ request_data.path = srs2ipc_audio_path(data->path);
+
+ rc = ipc_fmt_send(ipc_fmt_seq(), IPC_SND_AUDIO_PATH_CTRL, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ return 0;
+
+ return 0;
+}
+
+int srs_snd_set_call_clock_sync(struct srs_message *message)
+{
+ struct ipc_snd_clock_ctrl_data request_data;
+ struct srs_snd_call_clock_sync_data *data;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct srs_snd_call_clock_sync_data))
+ return -1;
+
+ data = (struct srs_snd_call_clock_sync_data *) message->data;
+
+ memset(&request_data, 0, sizeof(request_data));
+ request_data.sync = data->sync;
+
+ rc = ipc_fmt_send(ipc_fmt_seq(), IPC_SND_CLOCK_CTRL, IPC_TYPE_EXEC, (void *) &request_data, sizeof(request_data));
+ if (rc < 0)
+ return 0;
+
+ return 0;
+}
diff --git a/srs-client/include/srs-client.h b/srs-client/include/srs-client.h
index 632e882..16eee49 100644
--- a/srs-client/include/srs-client.h
+++ b/srs-client/include/srs-client.h
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * Copyright (C) 2013 Paul Kocialkowski <contact@oaulk.fr>
+ * Copyright (C) 2013-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
@@ -17,43 +17,46 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <pthread.h>
-
-#include <samsung-ril-socket.h>
-
#ifndef _SRS_CLIENT_H_
#define _SRS_CLIENT_H_
-#define SRS_CLIENT_TIMEOUT 500000
+#include <stdlib.h>
+#include <pthread.h>
-#define SRS_CLIENT_LOCK(client) pthread_mutex_lock(&(client->mutex))
-#define SRS_CLIENT_UNLOCK(client) pthread_mutex_unlock(&(client->mutex))
+#include <samsung-ril-socket.h>
-typedef void (*srs_client_thread_cb)(struct srs_message *message);
+#define SRS_CLIENT_LOCK(client) pthread_mutex_lock(&client->mutex)
+#define SRS_CLIENT_UNLOCK(client) pthread_mutex_unlock(&client->mutex)
struct srs_client {
int fd;
+ int event_fd;
pthread_mutex_t mutex;
pthread_t thread;
- int thread_run;
- srs_client_thread_cb thread_cb;
+ void (*callback)(struct srs_client *client, struct srs_message *message);
};
-int srs_client_recv_message(struct srs_client *client, struct srs_message *message);
-int srs_client_send_message(struct srs_client *client, struct srs_message *message);
-int srs_client_send(struct srs_client *client, unsigned short command, void *data, int length);
+const char *srs_command_string(unsigned short command);
+int srs_header_setup(struct srs_header *header,
+ const struct srs_message *message);
+int srs_message_setup(const struct srs_header *header,
+ struct srs_message *message);
+int srs_ping(struct srs_client *client);
+
+struct srs_client *srs_client_create(void);
+int srs_client_destroy(struct srs_client *client);
int srs_client_open(struct srs_client *client);
int srs_client_close(struct srs_client *client);
-int srs_client_create(struct srs_client **client_p);
-int srs_client_destroy(struct srs_client *client);
-
-int srs_client_thread_start(struct srs_client *client,
- srs_client_thread_cb cb);
-int srs_client_thread_stop(struct srs_client *client);
-
-int srs_client_ping(struct srs_client *client);
+int srs_client_poll(struct srs_client *client);
+int srs_client_send(struct srs_client *client, unsigned short command,
+ void *data, size_t size);
+int srs_client_recv(struct srs_client *client, struct srs_message *message);
+int srs_client_loop(struct srs_client *client);
+int srs_client_loop_start(struct srs_client *client,
+ void (*callback)(struct srs_client *client, struct srs_message *message));
+int srs_client_loop_stop(struct srs_client *client);
#endif
diff --git a/srs-client/srs-client.c b/srs-client/srs-client.c
index 109b607..2e1c75d 100644
--- a/srs-client/srs-client.c
+++ b/srs-client/srs-client.c
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * Copyright (C) 2013 Paul Kocialkowski <contact@oaulk.fr>
+ * Copyright (C) 2013-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
@@ -27,6 +27,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
+#include <sys/eventfd.h>
#include <signal.h>
#include <arpa/inet.h>
@@ -39,120 +40,254 @@
#include <srs-client.h>
/*
- * SRS Client fops
+ * Utils
*/
-int srs_client_recv_message(struct srs_client *client, struct srs_message *message)
+const char *srs_command_string(unsigned short command)
{
- struct srs_header *header_p;
- struct srs_header header;
- void *data = NULL;
- int length = 0;
+ static char command_string[7] = { 0 };
+
+ switch (command) {
+ case SRS_CONTROL_PING:
+ return "SRS_CONTROL_PING";
+ case SRS_SND_SET_CALL_VOLUME:
+ return "SRS_SND_SET_CALL_VOLUME";
+ case SRS_SND_SET_CALL_AUDIO_PATH:
+ return "SRS_SND_SET_CALL_AUDIO_PATH";
+ case SRS_SND_SET_CALL_CLOCK_SYNC:
+ return "SRS_SND_SET_CALL_CLOCK_SYNC";
+ default:
+ snprintf((char *) &command_string, sizeof(command_string), "0x%04x", command);
+ return command_string;
+ }
+}
- struct timeval timeout;
- fd_set fds;
- int rc;
+int srs_header_setup(struct srs_header *header,
+ const struct srs_message *message)
+{
+ if (header == NULL || message == NULL)
+ return -1;
- if (client == NULL || message == NULL || client->fd < 0)
- return -EINVAL;
+ memset(header, 0, sizeof(struct srs_header));
+ header->length = message->size + sizeof(struct srs_header);
+ header->group = SRS_GROUP(message->command);
+ header->index = SRS_INDEX(message->command);
+
+ return 0;
+}
+
+int srs_message_setup(const struct srs_header *header,
+ struct srs_message *message)
+{
+ if (header == NULL || message == NULL)
+ return -1;
memset(message, 0, sizeof(struct srs_message));
- memset(&header, 0, sizeof(header));
+ message->command = SRS_COMMAND(header->group, header->index);
+ message->data = NULL;
+ message->size = 0;
- timeout.tv_sec = (SRS_CLIENT_TIMEOUT - SRS_CLIENT_TIMEOUT % 1000000) / 1000000;
- timeout.tv_usec = SRS_CLIENT_TIMEOUT % 1000000;
+ return 0;
+}
- FD_ZERO(&fds);
- FD_SET(client->fd, &fds);
+/*
+ * SRS
+ */
- rc = select(client->fd + 1, &fds, NULL, NULL, &timeout);
- if (rc == 0) {
- rc = 0;
- goto done;
- } else if (rc < 0 || !FD_ISSET(client->fd, &fds))
+int srs_ping(struct srs_client *client)
+{
+ struct srs_message message;
+ struct srs_control_ping_data ping;
+ struct srs_control_ping_data *pong;
+ int rc;
+
+ if (client == NULL)
+ return -1;
+
+ memset(&message, 0, sizeof(message));
+
+ memset(&ping, 0, sizeof(ping));
+ ping.caffe = SRS_CONTROL_CAFFE;
+
+ rc = srs_client_send(client, SRS_CONTROL_PING, &ping, sizeof(ping));
+ if (rc < 0)
goto error;
- SRS_CLIENT_LOCK(client);
- rc = read(client->fd, &header, sizeof(header));
- SRS_CLIENT_UNLOCK(client);
+ rc = srs_client_poll(client);
+ if (rc <= 0)
+ goto error;
- if (rc != sizeof(header))
+ rc = srs_client_recv(client, &message);
+ if (rc < 0 || message.data == NULL || message.size < sizeof(struct srs_control_ping_data))
goto error;
- header_p = &header;
- message->command = SRS_COMMAND(header_p);
+ pong = (struct srs_control_ping_data *) message.data;
+ if (pong->caffe != SRS_CONTROL_CAFFE)
+ goto error;
- length = header.length - sizeof(header);
- if (length > 0) {
- data = calloc(1, length);
- if (data == NULL)
- goto error;
+ rc = 0;
+ goto complete;
- FD_ZERO(&fds);
- FD_SET(client->fd, &fds);
+error:
+ rc = -1;
+
+complete:
+ if (message.data != NULL && message.size > 0)
+ free(message.data);
+
+ return rc;
+}
- rc = select(client->fd + 1, &fds, NULL, NULL, &timeout);
- if (rc <= 0 || !FD_ISSET(client->fd, &fds))
- goto error;
+/*
+ * SRS client
+ */
+
+struct srs_client *srs_client_create(void)
+{
+ struct srs_client *client;
+
+ signal(SIGPIPE, SIG_IGN);
- SRS_CLIENT_LOCK(client);
- rc = read(client->fd, data, length);
- SRS_CLIENT_UNLOCK(client);
+ client = (struct srs_client *) calloc(1, sizeof(struct srs_client));
+ client->fd = -1;
+ client->event_fd = -1;
- if (rc != length)
- goto error;
+ pthread_mutex_init(&client->mutex, NULL);
- message->data = data;
- message->length = length;
- }
+ return client;
+}
+
+int srs_client_destroy(struct srs_client *client)
+{
+ if (client == NULL)
+ return -1;
- rc = header.length;
- goto done;
+ pthread_mutex_destroy(&client->mutex);
+
+ memset(client, 0, sizeof(struct srs_client));
+ free(client);
+
+ return 0;
+}
+
+int srs_client_open(struct srs_client *client)
+{
+ int flags;
+ int fd = 0;
+ int i = 0;
+ int rc;
+
+ if (client == NULL)
+ return -1;
+
+ SRS_CLIENT_LOCK(client);
+
+ do {
+ if (fd < 0)
+ usleep(50000);
+
+#if RIL_VERSION >= 6
+ fd = socket_local_client(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+#else
+ fd = socket_local_client(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+#endif
+
+ flags = fcntl(fd, F_GETFL);
+ flags |= O_NONBLOCK;
+ fcntl(fd, F_SETFL, flags);
+
+ i++;
+ } while (fd < 0 && i < 5);
+
+ if (fd < 0)
+ goto error;
+
+ client->fd = fd;
+
+ rc = 0;
+ goto complete;
error:
rc = -1;
- if (data != NULL)
- free(data);
+complete:
+ SRS_CLIENT_UNLOCK(client);
-done:
return rc;
}
-int srs_client_send_message(struct srs_client *client, struct srs_message *message)
+int srs_client_close(struct srs_client *client)
{
- struct srs_header header;
- unsigned char *p = NULL;
- void *data = NULL;
- int length = 0;
+ if (client == NULL )
+ return -1;
+
+ SRS_CLIENT_LOCK(client);
+
+ if (client->fd >= 0) {
+ close(client->fd);
+ client->fd = -1;
+ }
+
+ SRS_CLIENT_UNLOCK(client);
+
+ return 0;
+}
+
+int srs_client_poll(struct srs_client *client)
+{
+ struct timeval timeout;
+ fd_set fds;
+ int rc;
+
+ if (client == NULL || client->fd < 0)
+ return -1;
+
+ memset(&timeout, 0, sizeof(timeout));
+ timeout.tv_usec = 50000;
+ FD_ZERO(&fds);
+ FD_SET(client->fd, &fds);
+
+ rc = select(client->fd + 1, &fds, NULL, NULL, &timeout);
+
+ return rc;
+}
+
+int srs_client_send(struct srs_client *client, unsigned short command,
+ void *data, size_t size)
+{
+ struct srs_message message;
+ struct srs_header header;
+ void *buffer = NULL;
+ size_t length;
struct timeval timeout;
fd_set fds;
+ unsigned char *p;
int rc;
- if (client == NULL || message == NULL || client->fd < 0)
- return -EINVAL;
+ if (client == NULL || client->fd < 0)
+ return -1;
+
+ SRS_CLIENT_LOCK(client);
+
+ memset(&message, 0, sizeof(message));
+ message.command = command;
+ message.data = data;
+ message.size = size;
- memset(&header, 0, sizeof(header));
- header.length = message->length + sizeof(header);
- header.group = SRS_GROUP(message->command);
- header.index = SRS_INDEX(message->command);
+ srs_header_setup(&header, &message);
length = header.length;
- data = calloc(1, length);
- if (data == NULL)
- goto error;
+ buffer = calloc(1, length);
- p = (unsigned char *) data;
- memcpy(p, &header, sizeof(header));
- p += sizeof(header);
- if (message->data != NULL && message->length > 0) {
- memcpy(p, message->data, message->length);
- p += message->length;
+ memcpy(buffer, &header, sizeof(header));
+ if (message.data != NULL && message.size > 0) {
+ p = (unsigned char *) buffer + sizeof(header);
+ memcpy(p, message.data, message.size);
}
- timeout.tv_sec = (SRS_CLIENT_TIMEOUT - SRS_CLIENT_TIMEOUT % 1000000) / 1000000;
- timeout.tv_usec = SRS_CLIENT_TIMEOUT % 1000000;
+ memset(&timeout, 0, sizeof(timeout));
+ timeout.tv_usec = 300;
FD_ZERO(&fds);
FD_SET(client->fd, &fds);
@@ -161,204 +296,224 @@ int srs_client_send_message(struct srs_client *client, struct srs_message *messa
if (rc <= 0 || !FD_ISSET(client->fd, &fds))
goto error;
- SRS_CLIENT_LOCK(client);
- rc = write(client->fd, data, length);
- SRS_CLIENT_UNLOCK(client);
-
- if (rc != length)
+ rc = write(client->fd, buffer, length);
+ if (rc < (int) length)
goto error;
- rc = length;
- goto done;
+ rc = 0;
+ goto complete;
error:
rc = -1;
-done:
- if (data != NULL)
- free(data);
+complete:
+ if (buffer != NULL)
+ free(buffer);
+
+ SRS_CLIENT_UNLOCK(client);
return rc;
}
-int srs_client_send(struct srs_client *client, unsigned short command, void *data, int length)
+int srs_client_recv(struct srs_client *client, struct srs_message *message)
{
- struct srs_message message;
+ struct srs_header *header;
+ void *buffer = NULL;
+ size_t length;
+ struct timeval timeout;
+ fd_set fds;
+ unsigned char *p;
+ int rc;
- memset(&message, 0, sizeof(message));
- message.command = command;
- message.data = data;
- message.length = length;
+ if (client == NULL || client->fd < 0 || message == NULL)
+ return -1;
- return srs_client_send_message(client, &message);
-}
+ SRS_CLIENT_LOCK(client);
-int srs_client_open(struct srs_client *client)
-{
- int fd;
+ length = SRS_BUFFER_LENGTH;
+ buffer= calloc(1, length);
- if (client == NULL)
- return -EINVAL;
-#if RIL_VERSION >= 6
- fd = socket_local_client(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
-#else
- fd = socket_local_client(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
-#endif
- if (fd < 0) {
- client->fd = -1;
- return -1;
- }
+ memset(&timeout, 0, sizeof(timeout));
+ timeout.tv_usec = 300;
- client->fd = fd;
- return 0;
-}
+ FD_ZERO(&fds);
+ FD_SET(client->fd, &fds);
-int srs_client_close(struct srs_client *client)
-{
- if (client == NULL || client->fd < 0)
- return -EINVAL;
+ rc = select(client->fd + 1, &fds, NULL, NULL, &timeout);
+ if (rc <= 0 || !FD_ISSET(client->fd, &fds))
+ goto error;
- close(client->fd);
- client->fd = -1;
+ rc = read(client->fd, buffer, length);
+ if (rc < (int) sizeof(struct srs_header))
+ goto error;
- return 0;
-}
+ header = (struct srs_header *) buffer;
-int srs_client_create(struct srs_client **client_p)
-{
- struct srs_client *client;
+ srs_message_setup(header, message);
- if (client_p == NULL)
- return -EINVAL;
+ length = header->length - sizeof(struct srs_header);
+ if (length > 0) {
+ message->size = length;
+ message->data = calloc(1, length);
- client = calloc(1, sizeof(struct srs_client));
- if (client == NULL) {
- *client_p = NULL;
- return -1;
+ p = (unsigned char *) buffer + sizeof(struct srs_header);
+ memcpy(message->data, p, length);
}
- client->fd = -1;
- pthread_mutex_init(&(client->mutex), NULL);
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
- *client_p = client;
+complete:
+ if (buffer != NULL)
+ free(buffer);
- return 0;
+ SRS_CLIENT_UNLOCK(client);
+
+ return rc;
}
-int srs_client_destroy(struct srs_client *client)
+int srs_client_loop(struct srs_client *client)
{
- if (client == NULL)
- return -EINVAL;
+ struct srs_message message;
+ unsigned long int event;
+ fd_set fds;
+ int fd_max;
+ int rc;
- pthread_mutex_destroy(&(client->mutex));
+ if (client == NULL || client->callback == NULL)
+ return -1;
- free(client);
+ while (1) {
+ if (client->fd < 0 || client->event_fd < 0)
+ return -1;
+
+ FD_ZERO(&fds);
+ FD_SET(client->fd, &fds);
+ FD_SET(client->event_fd, &fds);
+
+ fd_max = client->fd > client->event_fd ? client->fd : client->event_fd;
+
+ rc = select(fd_max + 1, &fds, NULL, NULL, NULL);
+ if (rc < 0)
+ return -1;
+
+ if (FD_ISSET(client->event_fd, &fds)) {
+ read(client->event_fd, &event, sizeof(event));
+ break;
+ }
+
+ if (!FD_ISSET(client->fd, &fds))
+ continue;
+
+ memset(&message, 0, sizeof(struct srs_message));
+
+ rc = srs_client_recv(client, &message);
+ if (rc < 0)
+ return -1;
+
+ client->callback(client, &message);
+
+ if (message.data != NULL && message.size > 0)
+ free(message.data);
+ }
return 0;
}
-/*
- * SRS Client thread
- */
-
void *srs_client_thread(void *data)
{
- struct srs_message message;
struct srs_client *client;
- int rc;
+ int rc = 0;
+ int i = 0;
if (data == NULL)
return NULL;
client = (struct srs_client *) data;
- if (client->thread_cb == NULL)
- goto done;
+ do {
+ if (rc < 0) {
+ rc = srs_client_close(client);
+ if (rc < 0)
+ break;
- while (client->thread_run) {
- rc = srs_client_recv_message(client, &message);
- if (rc < 0)
- goto done;
+ rc = srs_client_open(client);
+ if (rc < 0)
+ break;
+ }
- client->thread_cb(&message);
- }
+ rc = srs_client_loop(client);
-done:
- client->thread_run = 0;
+ i++;
+ } while (rc < 0 && i < 5);
- return NULL;
+ return 0;
}
-int srs_client_thread_start(struct srs_client *client,
- srs_client_thread_cb cb)
+int srs_client_loop_start(struct srs_client *client,
+ void (*callback)(struct srs_client *client, struct srs_message *message))
{
pthread_attr_t attr;
+ int event_fd = -1;
int rc;
- if (client == NULL || cb == NULL)
- return -EINVAL;
+ if (client == NULL || callback == NULL)
+ return -1;
+
+ SRS_CLIENT_LOCK(client);
+
+ event_fd = eventfd(0, EFD_NONBLOCK);
+ if (event_fd < 0)
+ goto error;
- client->thread_cb = cb;
- client->thread_run = 1;
+ client->event_fd = event_fd;
+ client->callback = callback;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- rc = pthread_create(&(client->thread), &attr, srs_client_thread, (void *) client);
+ rc = pthread_create(&client->thread, &attr, srs_client_thread, (void *) client);
if (rc != 0)
- return -1;
+ goto error;
- return 0;
-}
+ rc = 0;
+ goto complete;
-int srs_client_thread_stop(struct srs_client *client)
-{
- if (client == NULL)
- return -EINVAL;
+error:
+ if (event_fd >= 0) {
+ close(event_fd);
+ client->event_fd = -1;
+ }
- client->thread_run = 0;
+ rc = -1;
- return 0;
-}
+complete:
+ SRS_CLIENT_UNLOCK(client);
-/*
- * SRS Client inline
- */
+ return rc;
+}
-int srs_client_ping(struct srs_client *client)
+int srs_client_loop_stop(struct srs_client *client)
{
- struct srs_message message;
- struct srs_control_ping ping;
- struct srs_control_ping *ping_p;
- int rc;
+ unsigned long int event;
- if (client == NULL)
+ if (client == NULL || client->event_fd < 0)
return -1;
- memset(&message, 0, sizeof(message));
-
- ping.caffe = SRS_CONTROL_CAFFE;
- rc = srs_client_send(client, SRS_CONTROL_PING, &ping, sizeof(ping));
- if (rc < 0)
- goto error;
-
- rc = srs_client_recv_message(client, &message);
- if (rc < 0 || message.length <= 0 || message.data == NULL)
- goto error;
+ SRS_CLIENT_LOCK(client);
- ping_p = (struct srs_control_ping *) message.data;
- if (ping_p->caffe != SRS_CONTROL_CAFFE)
- goto error;
+ event = 1;
+ write(client->event_fd, &event, sizeof(event));
- rc = 0;
- goto done;
+ SRS_CLIENT_UNLOCK(client);
-error:
- rc = -1;
+ pthread_join(client->thread, NULL);
-done:
- if (message.data != NULL)
- free(message.data);
+ close(client->event_fd);
+ client->event_fd = -1;
- return rc;
+ return 0;
}
diff --git a/srs.c b/srs.c
index b05beb3..890a33e 100644
--- a/srs.c
+++ b/srs.c
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * 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
@@ -17,12 +17,15 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
+#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
+#include <sys/eventfd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
@@ -30,52 +33,213 @@
#define LOG_TAG "RIL-SRS"
#include <utils/Log.h>
+#include <hardware_legacy/power.h>
-#include "samsung-ril.h"
-#include "util.h"
+#include <samsung-ril.h>
+#include <utils.h>
-int srs_client_register(struct srs_client_data *srs_client_data, int fd)
+/*
+ * Utils
+ */
+
+const char *srs_command_string(unsigned short command)
+{
+ static char command_string[7] = { 0 };
+
+ switch (command) {
+ case SRS_CONTROL_PING:
+ return "SRS_CONTROL_PING";
+ case SRS_SND_SET_CALL_VOLUME:
+ return "SRS_SND_SET_CALL_VOLUME";
+ case SRS_SND_SET_CALL_AUDIO_PATH:
+ return "SRS_SND_SET_CALL_AUDIO_PATH";
+ case SRS_SND_SET_CALL_CLOCK_SYNC:
+ return "SRS_SND_SET_CALL_CLOCK_SYNC";
+ default:
+ snprintf((char *) &command_string, sizeof(command_string), "0x%04x", command);
+ return command_string;
+ }
+}
+
+void srs_log_send(struct ril_client *client, struct srs_message *message)
{
- struct srs_client_info *client;
+ if (client == NULL || message == NULL)
+ return;
+
+ RIL_LOGD("\n");
+ RIL_LOGD("%s: Sent %s message", __func__, client->name);
+ RIL_LOGD("%s: Message: command=%s, size=%d", __func__, srs_command_string(message->command), message->size);
+ if (message->size > 0) {
+ RIL_LOGD("=================================== %s data ===================================", client->name);
+ data_dump(message->data, message->size);
+ RIL_LOGD("================================================================================");
+ }
+}
+
+void srs_log_recv(struct ril_client *client, struct srs_message *message)
+{
+ if (client == NULL || message == NULL)
+ return;
+
+ RIL_LOGD("\n");
+ RIL_LOGD("%s: Received %s message", __func__, client->name);
+ RIL_LOGD("%s: Message: command=%s, size=%d", __func__, srs_command_string(message->command), message->size);
+ if (message->size > 0) {
+ RIL_LOGD("=================================== %s data ===================================", client->name);
+ data_dump(message->data, message->size);
+ RIL_LOGD("================================================================================");
+ }
+}
+
+int srs_header_setup(struct srs_header *header,
+ const struct srs_message *message)
+{
+ if (header == NULL || message == NULL)
+ return -1;
+
+ memset(header, 0, sizeof(struct srs_header));
+ header->length = message->size + sizeof(struct srs_header);
+ header->group = SRS_GROUP(message->command);
+ header->index = SRS_INDEX(message->command);
+
+ return 0;
+}
+
+int srs_message_setup(const struct srs_header *header,
+ struct srs_message *message)
+{
+ if (header == NULL || message == NULL)
+ return -1;
+
+ memset(message, 0, sizeof(struct srs_message));
+ message->command = SRS_COMMAND(header->group, header->index);
+ message->data = NULL;
+ message->size = 0;
+
+ return 0;
+}
+
+/*
+ * SRS
+ */
+
+int srs_send(unsigned short command, const void *data, size_t size)
+{
+ struct ril_client *ril_client;
+ struct srs_data *srs_data;
+ struct srs_client *client;
+ struct srs_message message;
+ int rc;
+
+ ril_client = ril_client_find_id(RIL_CLIENT_SRS);
+ if (ril_client == NULL || ril_client->data == NULL)
+ return -1;
+
+ srs_data = (struct srs_data *) ril_client->data;
+ if (srs_data->event_fd < 0)
+ return -1;
+
+ if (!ril_client->available) {
+ RIL_LOGE("%s client is not available", ril_client->name);
+ return -1;
+ }
+
+ memset(&message, 0, sizeof(message));
+ message.command = command;
+ message.data = (void *) data;
+ message.size = size;
+
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_VERSION_STRING);
+
+ rc = srs_client_send(ril_client, &message);
+ if (rc < 0) {
+ RIL_LOGE("Sending to %s client failed", ril_client->name);
+
+ release_wake_lock(RIL_VERSION_STRING);
+
+ eventfd_send(srs_data->event_fd, SRS_CLIENT_IO_ERROR);
+ return -1;
+ }
+
+ return 0;
+}
+
+int srs_control_ping(struct srs_message *message)
+{
+ struct srs_control_ping_data *data;
+ int rc;
+
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct srs_control_ping_data))
+ return -1;
+
+ data = (struct srs_control_ping_data *) message->data;
+ if (data->caffe == SRS_CONTROL_CAFFE) {
+ rc = srs_send(SRS_CONTROL_PING, data, sizeof(struct srs_control_ping_data));
+ if (rc < 0) {
+ RIL_LOGE("Sending SRS control ping failed");
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * SRS client
+ */
+
+int srs_client_register(struct ril_client *ril_client, int fd)
+{
+ struct srs_data *data;
+ struct srs_client *client;
struct list_head *list_end;
struct list_head *list;
- if (srs_client_data == NULL)
+ if (ril_client == NULL || ril_client->data == NULL)
return -1;
- client = calloc(1, sizeof(struct srs_client_info));
- if (client == NULL)
- return -1;
+ data = (struct srs_data *) ril_client->data;
+
+ RIL_CLIENT_LOCK(ril_client);
+ client = calloc(1, sizeof(struct srs_client));
client->fd = fd;
- list_end = srs_client_data->clients;
+ list_end = data->clients;
while (list_end != NULL && list_end->next != NULL)
list_end = list_end->next;
- list = list_head_alloc((void *) client, list_end, NULL);
+ list = list_head_alloc(list_end, NULL, (void *) client);
- if (srs_client_data->clients == NULL)
- srs_client_data->clients = list;
+ if (data->clients == NULL)
+ data->clients = list;
+
+ RIL_CLIENT_UNLOCK(ril_client);
return 0;
}
-void srs_client_unregister(struct srs_client_data *srs_client_data, struct srs_client_info *client)
+int srs_client_unregister(struct ril_client *ril_client,
+ struct srs_client *client)
{
+ struct srs_data *data;
struct list_head *list;
- if (srs_client_data == NULL || client == NULL)
- return;
+ if (ril_client == NULL || ril_client->data == NULL)
+ return -1;
+
+ data = (struct srs_data *) ril_client->data;
+
+ RIL_CLIENT_LOCK(ril_client);
- list = srs_client_data->clients;
+ list = data->clients;
while (list != NULL) {
if (list->data == (void *) client) {
- memset(client, 0, sizeof(struct srs_client_info));
+ memset(client, 0, sizeof(struct srs_client));
free(client);
- if (list == srs_client_data->clients)
- srs_client_data->clients = list->next;
+ if (list == data->clients)
+ data->clients = list->next;
list_head_free(list);
@@ -84,497 +248,914 @@ void srs_client_unregister(struct srs_client_data *srs_client_data, struct srs_c
list_continue:
list = list->next;
}
+
+ RIL_CLIENT_UNLOCK(ril_client);
+
+ return 0;
}
-struct srs_client_info *srs_client_info_find(struct srs_client_data *srs_client_data)
+int srs_client_flush(struct ril_client *ril_client)
{
- struct srs_client_info *client;
+ struct srs_data *data;
+ struct srs_client *client;
struct list_head *list;
+ struct list_head *list_next;
+
+ if (ril_client == NULL || ril_client->data == NULL)
+ return -1;
+
+ data = (struct srs_data *) ril_client->data;
+
+ RIL_CLIENT_LOCK(ril_client);
- list = srs_client_data->clients;
+ list = data->clients;
while (list != NULL) {
- client = (struct srs_client_info *) list->data;
- if (client == NULL)
+ if (list->data != NULL) {
+ client = (struct srs_client *) list->data;
+ memset(client, 0, sizeof(struct srs_client));
+ free(client);
+ }
+
+ if (list == data->clients)
+ data->clients = list->next;
+
+ list_next = list->next;
+
+ list_head_free(list);
+
+list_continue:
+ list = list_next;
+ }
+
+ RIL_CLIENT_UNLOCK(ril_client);
+
+ return 0;
+}
+
+struct srs_client *srs_client_find(struct ril_client *ril_client)
+{
+ struct srs_data *data;
+ struct srs_client *client;
+ struct list_head *list;
+
+ if (ril_client == NULL || ril_client->data == NULL)
+ return NULL;
+
+ data = (struct srs_data *) ril_client->data;
+
+ RIL_CLIENT_LOCK(ril_client);
+
+ list = data->clients;
+ while (list != NULL) {
+ if (list->data == NULL)
goto list_continue;
+ client = (struct srs_client *) list->data;
+
+ RIL_CLIENT_UNLOCK(ril_client);
return client;
list_continue:
list = list->next;
}
+ RIL_CLIENT_UNLOCK(ril_client);
+
return NULL;
}
-struct srs_client_info *srs_client_info_find_fd(struct srs_client_data *srs_client_data, int fd)
+struct srs_client *srs_client_find_fd(struct ril_client *ril_client, int fd)
{
- struct srs_client_info *client;
+ struct srs_data *data;
+ struct srs_client *client;
struct list_head *list;
- list = srs_client_data->clients;
+ if (ril_client == NULL || ril_client->data == NULL)
+ return NULL;
+
+ data = (struct srs_data *) ril_client->data;
+
+ RIL_CLIENT_LOCK(ril_client);
+
+ list = data->clients;
while (list != NULL) {
- client = (struct srs_client_info *) list->data;
- if (client == NULL)
+ if (list->data == NULL)
goto list_continue;
- if (client->fd == fd)
+ client = (struct srs_client *) list->data;
+
+ if (client->fd == fd) {
+ RIL_CLIENT_UNLOCK(ril_client);
return client;
+ }
list_continue:
list = list->next;
}
+ RIL_CLIENT_UNLOCK(ril_client);
+
return NULL;
}
-int srs_client_info_fill_fd_set(struct srs_client_data *srs_client_data, fd_set *fds)
+struct srs_client *srs_client_find_fd_set(struct ril_client *ril_client,
+ fd_set *fds)
{
- struct srs_client_info *client;
+ struct srs_data *data;
+ struct srs_client *client;
struct list_head *list;
- int fd_max;
- if (srs_client_data == NULL || fds == NULL)
- return -1;
+ if (ril_client == NULL || ril_client->data == NULL || fds == NULL )
+ return NULL;
+
+ data = (struct srs_data *) ril_client->data;
- fd_max = -1;
- list = srs_client_data->clients;
+ RIL_CLIENT_LOCK(ril_client);
+
+ list = data->clients;
while (list != NULL) {
- client = (struct srs_client_info *) list->data;
- if (client == NULL)
+ if (list->data == NULL)
goto list_continue;
- FD_SET(client->fd, fds);
- if (client->fd > fd_max)
- fd_max = client->fd;
+ client = (struct srs_client *) list->data;
+
+ if (FD_ISSET(client->fd, fds)) {
+ FD_CLR(client->fd, fds);
+
+ RIL_CLIENT_UNLOCK(ril_client);
+ return client;
+ }
list_continue:
list = list->next;
}
- return fd_max;
+ RIL_CLIENT_UNLOCK(ril_client);
+
+ return NULL;
}
-int srs_client_info_get_fd_set(struct srs_client_data *srs_client_data, fd_set *fds)
+int srs_client_fd_set_setup(struct ril_client *ril_client, fd_set *fds)
{
- struct srs_client_info *client;
+ struct srs_data *data;
+ struct srs_client *client;
struct list_head *list;
- int fd;
+ int fd_max = -1;
- if (srs_client_data == NULL || fds == NULL)
+ if (ril_client == NULL || ril_client->data == NULL || fds == NULL)
return -1;
- list = srs_client_data->clients;
+ data = (struct srs_data *) ril_client->data;
+
+ RIL_CLIENT_LOCK(ril_client);
+
+ FD_ZERO(fds);
+
+ list = data->clients;
while (list != NULL) {
- client = (struct srs_client_info *) list->data;
- if (client == NULL)
+ if (list->data == NULL)
goto list_continue;
- if (FD_ISSET(client->fd, fds)) {
- FD_CLR(client->fd, fds);
- return client->fd;
- }
+ client = (struct srs_client *) list->data;
+
+ FD_SET(client->fd, fds);
+ if (client->fd > fd_max)
+ fd_max = client->fd;
list_continue:
list = list->next;
}
- return -1;
+ RIL_CLIENT_UNLOCK(ril_client);
+
+ return fd_max;
}
-int srs_client_send_message(struct srs_client_data *srs_client_data, struct srs_message *message)
+int srs_client_send(struct ril_client *client, struct srs_message *message)
{
+ struct srs_data *data;
struct srs_header header;
- void *data;
-
+ void *buffer = NULL;
+ size_t length;
struct timeval timeout;
fd_set fds;
+ unsigned char *p;
int rc;
- if (srs_client_data == NULL || message == NULL)
- return -EINVAL;
+ if (client == NULL || client->data == NULL || message == NULL)
+ return -1;
- memset(&header, 0, sizeof(header));
- header.group = SRS_GROUP(message->command);
- header.index = SRS_INDEX(message->command);
- header.length = message->length + sizeof(header);
+ data = (struct srs_data *) client->data;
+ if (data->client_fd < 0)
+ return -1;
- data = calloc(1, header.length);
- memcpy(data, &header, sizeof(header));
- memcpy((void *) ((char *) data + sizeof(header)), message->data, message->length);
+ RIL_CLIENT_LOCK(client);
- memset(&timeout, 0, sizeof(timeout));
- timeout.tv_usec = 300;
+ srs_header_setup(&header, message);
+
+ length = header.length;
+ buffer = calloc(1, length);
- if (srs_client_data->client_fd < 0) {
- rc = -1;
- goto complete;
+ memcpy(buffer, &header, sizeof(header));
+ if (message->data != NULL && message->size > 0) {
+ p = (unsigned char *) buffer + sizeof(header);
+ memcpy(p, message->data, message->size);
}
- FD_ZERO(&fds);
- FD_SET(srs_client_data->client_fd, &fds);
+ srs_log_send(client, message);
- rc = select(srs_client_data->client_fd + 1, NULL, &fds, NULL, &timeout);
+ memset(&timeout, 0, sizeof(timeout));
+ timeout.tv_usec = 300;
+
+ FD_ZERO(&fds);
+ FD_SET(data->client_fd, &fds);
- if (!FD_ISSET(srs_client_data->client_fd, &fds)) {
- RIL_LOGE("SRS write select failed on fd %d", srs_client_data->client_fd);
- rc = -1;
- goto complete;
+ rc = select(data->client_fd + 1, NULL, &fds, NULL, &timeout);
+ if (rc <= 0 || !FD_ISSET(data->client_fd, &fds)) {
+ RIL_LOGE("Polling %s client failed", client->name);
+ goto error;
}
- rc = write(srs_client_data->client_fd, data, header.length);
- if (rc < (int) sizeof(struct srs_header)) {
- RIL_LOGE("SRS write failed on fd %d with %d bytes", srs_client_data->client_fd, rc);
- rc = -1;
- goto complete;
+ rc = write(data->client_fd, buffer, length);
+ if (rc < (int) length) {
+ RIL_LOGE("Writing to %s client failed", client->name);
+ goto error;
}
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
complete:
- free(data);
+ if (buffer != NULL)
+ free(buffer);
+
+ RIL_CLIENT_UNLOCK(client);
return rc;
}
-int srs_client_send(struct srs_client_data *srs_client_data, unsigned short command, void *data, int length)
+int srs_client_recv(struct ril_client *client, struct srs_message *message)
{
- struct srs_client_info *client;
- struct srs_message message;
+ struct srs_data *data;
+ struct srs_header *header;
+ void *buffer = NULL;
+ size_t length;
+ struct timeval timeout;
+ fd_set fds;
+ unsigned char *p;
int rc;
- if (srs_client_data == NULL)
+ if (client == NULL || client->data == NULL || message == NULL)
return -1;
- memset(&message, 0, sizeof(message));
- message.command = command;
- message.length = length;
- message.data = data;
+ data = (struct srs_data *) client->data;
+ if (data->client_fd < 0)
+ return -1;
+
+ RIL_CLIENT_LOCK(client);
+
+ length = SRS_BUFFER_LENGTH;
+ buffer= calloc(1, length);
+
+ memset(&timeout, 0, sizeof(timeout));
+ timeout.tv_usec = 300;
+
+ FD_ZERO(&fds);
+ FD_SET(data->client_fd, &fds);
+
+ rc = select(data->client_fd + 1, &fds, NULL, NULL, &timeout);
+ if (rc <= 0 || !FD_ISSET(data->client_fd, &fds)) {
+ RIL_LOGE("Polling %s client failed", client->name);
+ goto error;
+ }
+
+ rc = read(data->client_fd, buffer, length);
+ if (rc < (int) sizeof(struct srs_header)) {
+ RIL_LOGE("Reading from %s client failed", client->name);
+ goto error;
+ }
+
+ header = (struct srs_header *) buffer;
- RIL_CLIENT_LOCK(srs_client_data->client);
- rc = srs_client_send_message(srs_client_data, &message);
- RIL_CLIENT_UNLOCK(srs_client_data->client);
+ srs_message_setup(header, message);
- if (rc <= 0) {
- RIL_LOGD("SRS client with fd %d terminated", srs_client_data->client_fd);
+ length = header->length - sizeof(struct srs_header);
+ if (length > 0) {
+ message->size = length;
+ message->data = calloc(1, length);
- client = srs_client_info_find_fd(srs_client_data, srs_client_data->client_fd);
- if (client != NULL)
- srs_client_unregister(srs_client_data, client);
- close(srs_client_data->client_fd);
- srs_client_data->client_fd = -1;
+ p = (unsigned char *) buffer + sizeof(struct srs_header);
+ memcpy(message->data, p, length);
}
+ srs_log_recv(client, message);
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ if (buffer != NULL)
+ free(buffer);
+
+ RIL_CLIENT_UNLOCK(client);
+
return rc;
}
-int srs_send(unsigned short command, void *data, int length)
+/*
+ * SRS server
+ */
+
+int srs_server_open(struct ril_client *client)
{
- struct srs_client_data *srs_client_data;
+ struct srs_data *data;
+ int server_fd;
+ int flags;
int rc;
- if (ril_data.srs_client == NULL || ril_data.srs_client->data == NULL)
- return -EINVAL;
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct srs_data *) client->data;
+ if (data->server_event_fd < 0)
+ return -1;
- srs_client_data = (struct srs_client_data *) ril_data.srs_client->data;
+ RIL_CLIENT_LOCK(client);
- RIL_LOGD("SEND SRS: fd=%d command=%d length=%d", srs_client_data->client_fd, command, length);
- if (data != NULL && length > 0) {
- RIL_LOGD("==== SRS DATA DUMP ====");
- hex_dump(data, length);
- RIL_LOGD("=======================");
+ unlink(SRS_SOCKET_NAME);
+
+#if RIL_VERSION >= 6
+ server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+#else
+ server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+#endif
+ if (server_fd < 0) {
+ RIL_LOGE("Opening %s server failed", client->name);
+ goto error;
}
- return srs_client_send(srs_client_data, command, data, length);
+ flags = fcntl(server_fd, F_GETFL);
+ flags |= O_NONBLOCK;
+ fcntl(server_fd, F_SETFL, flags);
+
+ data->server_fd = server_fd;
+
+ eventfd_flush(data->server_event_fd);
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
+
+complete:
+ RIL_CLIENT_UNLOCK(client);
+
+ return rc;
}
-int srs_client_recv(struct srs_client_data *srs_client_data, struct srs_message *message)
+int srs_server_close(struct ril_client *ril_client)
{
- struct srs_header *header;
- void *data;
-
- struct timeval timeout;
- fd_set fds;
+ struct srs_data *data;
+ struct srs_client *client;
+ eventfd_t event;
int rc;
- if (srs_client_data == NULL || message == NULL)
+ if (ril_client == NULL || ril_client->data == NULL)
return -1;
- data = calloc(1, SRS_DATA_MAX_SIZE);
+ data = (struct srs_data *) ril_client->data;
+ if (data->server_event_fd < 0)
+ return -1;
- memset(&timeout, 0, sizeof(timeout));
- timeout.tv_usec = 300;
+ do {
+ client = srs_client_find(ril_client);
+ if (client == NULL)
+ break;
- if (srs_client_data->client_fd < 0) {
- rc = -1;
- goto complete;
- }
+ if (client->fd >= 0)
+ close(client->fd);
- FD_ZERO(&fds);
- FD_SET(srs_client_data->client_fd, &fds);
+ rc = srs_client_unregister(ril_client, client);
+ if (rc < 0) {
+ RIL_LOGE("Unregistering %s client failed", ril_client->name);
+ return -1;
+ }
+ } while (client != NULL);
- rc = select(srs_client_data->client_fd + 1, &fds, NULL, NULL, &timeout);
+ RIL_CLIENT_LOCK(ril_client);
- if (!FD_ISSET(srs_client_data->client_fd, &fds)) {
- RIL_LOGE("SRS read select failed on fd %d", srs_client_data->client_fd);
- rc = -1;
- goto complete;
+ rc = eventfd_send(data->server_event_fd, SRS_SERVER_CLOSE);
+ if (rc < 0) {
+ RIL_LOGE("Sending %s server close event failed", ril_client->name);
+ goto error;
}
- rc = read(srs_client_data->client_fd, data, SRS_DATA_MAX_SIZE);
- if (rc < (int) sizeof(struct srs_header)) {
- RIL_LOGE("SRS read failed on fd %d with %d bytes", srs_client_data->client_fd, rc);
- rc = -1;
- goto complete;
+ if (data->server_fd >= 0) {
+ close(data->server_fd);
+ data->server_fd = -1;
}
- header = (struct srs_header *) data;
+ rc = 0;
+ goto complete;
- memset(message, 0, sizeof(struct srs_message));
- message->command = SRS_COMMAND(header);
- message->length = header->length - sizeof(struct srs_header);
- message->data = NULL;
-
- if (message->length > 0) {
- message->data = calloc(1, message->length);
- memcpy(message->data, (void *) ((char *) data + sizeof(struct srs_header)), message->length);
- }
+error:
+ rc = -1;
complete:
- free(data);
+ RIL_CLIENT_UNLOCK(ril_client);
return rc;
}
-void srs_control_ping(struct srs_message *message)
+int srs_server_loop(struct ril_client *client)
{
- int caffe;
+ struct srs_data *data;
+ struct sockaddr_un client_addr;
+ socklen_t client_addr_len;
+ eventfd_t event;
+ int client_fd;
+ fd_set fds;
+ int fd_max;
+ int flags;
+ int rc;
- if (message == NULL || message->data == NULL || message->length < (int) sizeof(int))
- return;
+ if (client == NULL || client->data == NULL)
+ return -1;
- caffe = *((int *) message->data);
+ data = (struct srs_data *) client->data;
+ if (data->server_fd < 0 || data->server_event_fd < 0 || data->event_fd < 0)
+ return -1;
- if (caffe == SRS_CONTROL_CAFFE)
- srs_send(SRS_CONTROL_PING, &caffe, sizeof(caffe));
-}
+ while (1) {
+ if (!client->available) {
+ RIL_LOGE("%s client is not available", client->name);
+ return -1;
+ }
-static int srs_server_open(void)
-{
- int server_fd;
- int t;
+ FD_ZERO(&fds);
+ FD_SET(data->server_fd, &fds);
+ FD_SET(data->server_event_fd, &fds);
- for (t = 0 ; t < 5 ; t++) {
- unlink(SRS_SOCKET_NAME);
-#if RIL_VERSION >= 6
- server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
-#else
- server_fd = socket_local_server(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
-#endif
- if (server_fd >= 0)
- return server_fd;
+ fd_max = data->server_fd > data->server_event_fd ? data->server_fd : data->server_event_fd;
+
+ rc = select(fd_max + 1, &fds, NULL, NULL, NULL);
+ if (rc < 0) {
+ RIL_LOGE("Polling %s server failed", client->name);
+ return -1;
+ }
+
+ if (FD_ISSET(data->server_event_fd, &fds)) {
+ rc = eventfd_recv(data->server_event_fd, &event);
+ if (rc < 0)
+ return -1;
+
+ switch (event) {
+ case SRS_SERVER_CLOSE:
+ return 0;
+ }
+ }
+
+ if (!FD_ISSET(data->server_fd, &fds))
+ continue;
+
+ client_fd = accept(data->server_fd, (struct sockaddr *) &client_addr, &client_addr_len);
+ if (client_fd < 0) {
+ RIL_LOGE("Accepting new %s client failed", client->name);
+ return -1;
+ }
+
+ flags = fcntl(client_fd, F_GETFL);
+ flags |= O_NONBLOCK;
+ fcntl(client_fd, F_SETFL, flags);
+
+ rc = srs_client_register(client, client_fd);
+ if (rc < 0) {
+ RIL_LOGE("Registering new %s client failed", client->name);
+ return -1;
+ }
+
+ RIL_LOGD("Registered new %s client", client->name);
+
+ rc = eventfd_send(data->event_fd, SRS_CLIENT_CHANGE);
+ if (rc < 0) {
+ RIL_LOGE("Sending %s change event failed", client->name);
+ return -1;
+ }
}
- return -1;
+ return 0;
}
-void *srs_client_read_loop(void *data)
+void *srs_server_thread(void *data)
{
- struct srs_client_info *client;
- struct srs_client_data *srs_client_data;
- struct srs_message message;
- struct timeval timeout;
- fd_set fds;
- int fd_max;
- int fd;
+ struct ril_client *client;
+ int failures = 0;
int rc;
if (data == NULL)
- pthread_exit(NULL);
+ return NULL;
- srs_client_data = (struct srs_client_data *) data;
+ client = (struct ril_client *) data;
- while (srs_client_data->running) {
- FD_ZERO(&fds);
+ do {
+ if (failures) {
+ rc = srs_server_close(client);
+ if (rc < 0)
+ goto failure;
- SRS_CLIENT_LOCK();
- fd_max = srs_client_info_fill_fd_set(srs_client_data, &fds);
- SRS_CLIENT_UNLOCK();
+ rc = srs_server_open(client);
+ if (rc < 0)
+ goto failure;
+ }
- if (fd_max < 0) {
- usleep(3000);
- continue;
+ rc = srs_server_loop(client);
+ if (rc < 0) {
+ RIL_LOGE("%s server loop failed", client->name);
+ goto failure;
+ } else {
+ RIL_LOGE("%s server loop terminated", client->name);
+ break;
}
- timeout.tv_sec = 0;
- timeout.tv_usec = 3000;
+failure:
+ failures++;
+ } while (failures < RIL_CLIENT_RETRY_COUNT);
- select(fd_max + 1, &fds, NULL, NULL, &timeout);
+ srs_server_close(client);
- SRS_CLIENT_LOCK();
- while ((fd = srs_client_info_get_fd_set(srs_client_data, &fds)) >= 0) {
- srs_client_data->client_fd = fd;
+ RIL_LOGD("Stopped %s server loop", client->name);
- RIL_CLIENT_LOCK(srs_client_data->client);
- rc = srs_client_recv(srs_client_data, &message);
- if (rc <= 0) {
- RIL_LOGD("SRS client with fd %d terminated", fd);
+ return NULL;
+}
- client = srs_client_info_find_fd(srs_client_data, fd);
- if (client != NULL)
- srs_client_unregister(srs_client_data, client);
- close(fd);
+/*
+ * SRS client
+ */
- RIL_CLIENT_UNLOCK(srs_client_data->client);
- continue;
- }
- RIL_CLIENT_UNLOCK(srs_client_data->client);
+int srs_create(struct ril_client *client)
+{
+ struct srs_data *data;
+ int server_event_fd = -1;
+ int event_fd = -1;
+ int rc;
- RIL_LOGD("RECV SRS: fd=%d command=%d length=%d", fd, message.command, message.length);
- if (message.data != NULL && message.length > 0) {
- RIL_LOGD("==== SRS DATA DUMP ====");
- hex_dump(message.data, message.length);
- RIL_LOGD("=======================");
- }
+ if (client == NULL)
+ return -1;
- srs_dispatch(&message);
+ signal(SIGPIPE, SIG_IGN);
- if (message.data != NULL && message.length > 0)
- free(message.data);
+ RIL_CLIENT_LOCK(client);
- srs_client_data->client_fd = -1;
- }
- SRS_CLIENT_UNLOCK();
+ client->available = 0;
+
+ data = (struct srs_data *) calloc(1, sizeof(struct srs_data));
+ data->server_fd = -1;
+ data->client_fd = -1;
+
+ server_event_fd = eventfd(0, EFD_NONBLOCK);
+ if (server_event_fd < 0) {
+ RIL_LOGE("Creating %s server event failed", client->name);
+ goto error;
}
- pthread_exit(NULL);
- return NULL;
+ event_fd = eventfd(0, EFD_NONBLOCK);
+ if (event_fd < 0) {
+ RIL_LOGE("Creating %s event failed", client->name);
+ goto error;
+ }
+
+ data->server_event_fd = server_event_fd;
+ data->event_fd = event_fd;
+
+ client->data = data;
+
+ rc = 0;
+ goto complete;
+
+error:
+ if (server_event_fd >= 0)
+ close(server_event_fd);
+
+ if (event_fd >= 0)
+ close(event_fd);
+
+ rc = -1;
+
+complete:
+ RIL_CLIENT_UNLOCK(client);
+
+ return rc;
}
-int srs_read_loop(struct ril_client *client)
+int srs_destroy(struct ril_client *client)
{
- struct srs_client_data *srs_client_data;
+ struct srs_data *data;
- struct sockaddr_un client_addr;
- int client_addr_len;
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct srs_data *) client->data;
+
+ if (client->available)
+ srs_close(client);
+
+ RIL_CLIENT_LOCK(client);
+
+ client->available = 0;
+
+ if (data->server_event_fd >= 0)
+ close(data->server_event_fd);
+
+ if (data->event_fd >= 0)
+ close(data->event_fd);
+
+ memset(data, 0, sizeof(struct srs_data));
+ free(data);
+
+ client->data = NULL;
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
+}
+
+int srs_open(struct ril_client *client)
+{
+ struct srs_data *data;
pthread_attr_t attr;
- int flags;
- int fd;
int rc;
if (client == NULL || client->data == NULL)
- return -EINVAL;
+ return -1;
- srs_client_data = (struct srs_client_data *) client->data;
+ data = (struct srs_data *) client->data;
+ if (data->event_fd < 0)
+ return -1;
+
+ rc = srs_server_open(client);
+ if (rc < 0) {
+ RIL_LOGE("Opening %s server failed", client->name);
+ return -1;
+ }
+
+ RIL_CLIENT_LOCK(client);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- srs_client_data->running = 1;
+ rc = pthread_create(&data->server_thread, &attr, srs_server_thread, (void *) client);
+ if (rc != 0) {
+ RIL_LOGE("Starting %s server loop failed", client->name);
+ goto error;
+ }
- rc = pthread_create(&srs_client_data->thread, &attr, srs_client_read_loop, (void *) srs_client_data);
- if (rc < 0) {
- RIL_LOGE("Unable to create SRS client read loop thread");
+ RIL_LOGD("Started %s server loop", client->name);
+
+ eventfd_flush(data->event_fd);
+
+ client->available = 1;
+
+ rc = 0;
+ goto complete;
+
+error:
+ srs_server_close(client);
+
+ rc = -1;
+
+complete:
+ RIL_CLIENT_UNLOCK(client);
+
+ return rc;
+}
+
+int srs_close(struct ril_client *ril_client)
+{
+ struct srs_data *data;
+ struct srs_client *client;
+ eventfd_t event;
+ int rc;
+
+ if (ril_client == NULL || ril_client->data == NULL)
return -1;
- }
- while (srs_client_data->server_fd >= 0) {
- fd = accept(srs_client_data->server_fd, (struct sockaddr *) &client_addr,
- &client_addr_len);
- if (fd < 0) {
- RIL_LOGE("Unable to accept new SRS client");
- break;
- }
+ data = (struct srs_data *) ril_client->data;
+ if (data->event_fd < 0)
+ return -1;
- flags = fcntl(fd, F_GETFL);
- flags |= O_NONBLOCK;
- fcntl(fd, F_SETFL, flags);
+ RIL_CLIENT_LOCK(ril_client);
- RIL_LOGD("Accepted new SRS client from fd %d", fd);
+ rc = eventfd_send(data->event_fd, SRS_CLIENT_CLOSE);
+ if (rc < 0) {
+ RIL_LOGE("Sending %s close event failed", ril_client->name);
+ RIL_CLIENT_UNLOCK(ril_client);
- SRS_CLIENT_LOCK();
- rc = srs_client_register(srs_client_data, fd);
- SRS_CLIENT_UNLOCK();
- if (rc < 0) {
- RIL_LOGE("Unable to register SRS client");
- break;
- }
+ return -1;
}
- RIL_LOGE("SRS server failure");
+ data->client_fd = -1;
+
+ RIL_CLIENT_UNLOCK(ril_client);
+
+ rc = srs_server_close(ril_client);
+ if (rc < 0) {
+ RIL_LOGE("Closing %s server failed", ril_client->name);
+ return -1;
+ }
- srs_client_data->running = 0;
+ rc = srs_client_flush(ril_client);
+ if (rc < 0) {
+ RIL_LOGE("Flushing %s client failed", ril_client->name);
+ return -1;
+ }
- // Wait for the thread to finish
- pthread_join(srs_client_data->thread, NULL);
+ pthread_join(data->server_thread, NULL);
return 0;
}
-int srs_create(struct ril_client *client)
+int srs_dispatch(struct ril_client *client, struct srs_message *message)
{
- struct srs_client_data *srs_client_data;
+ unsigned int i;
+ int rc;
- if (client == NULL)
- return -EINVAL;
+ if (client == NULL || message == NULL || ril_data == NULL)
+ return -1;
- RIL_LOGD("Creating new SRS client");
+ RIL_LOCK();
- signal(SIGPIPE, SIG_IGN);
+ for (i = 0; i < srs_dispatch_handlers_count; i++) {
+ if (srs_dispatch_handlers[i].handler == NULL)
+ continue;
- srs_client_data = (struct srs_client_data *) calloc(1, sizeof(struct srs_client_data));
+ if (srs_dispatch_handlers[i].command == message->command) {
+ rc = srs_dispatch_handlers[i].handler(message);
+ if (rc < 0) {
+ RIL_LOGE("Handling %s message failed", client->name);
+ goto error;
+ }
- srs_client_data->server_fd = srs_server_open();
- if (srs_client_data->server_fd < 0) {
- RIL_LOGE("SRS server creation failed");
- goto error;
+ rc = 0;
+ goto complete;
+ }
}
- pthread_mutex_init(&srs_client_data->mutex, NULL);
-
- srs_client_data->client = client;
- client->data = (void *) srs_client_data;
+ RIL_LOGD("Unhandled %s message: %s", client->name, srs_command_string(message->command));
- return 0;
+ rc = 0;
+ goto complete;
error:
- free(srs_client_data);
+ rc = -1;
- return -1;
+complete:
+ RIL_UNLOCK();
+
+ return rc;
}
-int srs_destroy(struct ril_client *client)
+int srs_loop(struct ril_client *ril_client)
{
- struct srs_client_data *srs_client_data = NULL;
- struct srs_client_info *client_info;
+ struct srs_data *data;
+ struct srs_client *client;
+ struct srs_message message;
+ eventfd_t event;
+ fd_set fds;
+ int fd_max;
+ int rc;
- if (client == NULL || client->data == NULL) {
- RIL_LOGE("Client was already destroyed");
- return 0;
- }
+ if (ril_client == NULL || ril_client->data == NULL)
+ return -1;
+
+ data = (struct srs_data *) ril_client->data;
+ if (data->event_fd < 0)
+ return -1;
- srs_client_data = (struct srs_client_data *) client->data;
+ while (1) {
+ if (!ril_client->available) {
+ RIL_LOGE("%s client is not available", ril_client->name);
+ return -1;
+ }
- pthread_mutex_destroy(&srs_client_data->mutex);
+ fd_max = srs_client_fd_set_setup(ril_client, &fds);
- while ((client_info = srs_client_info_find(srs_client_data)) != NULL) {
- close(client_info->fd);
- srs_client_unregister(srs_client_data, client_info);
- }
+ FD_SET(data->event_fd, &fds);
- if (srs_client_data->server_fd > 0)
- close(srs_client_data->server_fd);
+ fd_max = fd_max > data->event_fd ? fd_max : data->event_fd;
- srs_client_data->server_fd = -1;
- srs_client_data->client_fd = -1;
- srs_client_data->clients = NULL;
- srs_client_data->running = 0;
+ rc = select(fd_max + 1, &fds, NULL, NULL, NULL);
+ if (rc < 0) {
+ RIL_LOGE("Polling %s client failed", ril_client->name);
+ return -1;
+ }
- free(srs_client_data);
- client->data = NULL;
+ if (FD_ISSET(data->event_fd, &fds)) {
+ rc = eventfd_read(data->event_fd, &event);
+ if (rc < 0)
+ return -1;
+
+ switch (event) {
+ case SRS_CLIENT_CLOSE:
+ return 0;
+ case SRS_CLIENT_CHANGE:
+ break;
+ case SRS_CLIENT_IO_ERROR:
+ if (client->fd >= 0)
+ close(client->fd);
+
+ data->client_fd = -1;
+
+ srs_client_unregister(ril_client, client);
+ break;
+ }
+ }
+
+ do {
+ client = srs_client_find_fd_set(ril_client, &fds);
+ if (client == NULL)
+ break;
+
+ data->client_fd = client->fd;
+
+ memset(&message, 0, sizeof(message));
+
+ RIL_LOCK();
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_VERSION_STRING);
+
+ rc = srs_client_recv(ril_client, &message);
+ if (rc < 0) {
+ RIL_LOGE("Receiving from %s client failed", ril_client->name);
+
+ release_wake_lock(RIL_VERSION_STRING);
+ RIL_UNLOCK();
+
+ if (client->fd >= 0)
+ close(client->fd);
+
+ data->client_fd = -1;
+
+ srs_client_unregister(ril_client, client);
+ continue;
+ }
+
+ RIL_UNLOCK();
+
+ rc = srs_dispatch(ril_client, &message);
+ if (rc < 0) {
+ RIL_LOGE("Dispatching %s message failed", ril_client->name);
+
+ if (message.data != NULL && message.size > 0)
+ free(message.data);
+
+ if (client->fd >= 0)
+ close(client->fd);
+
+ data->client_fd = -1;
+
+ srs_client_unregister(ril_client, client);
+ continue;
+ }
+
+ if (message.data != NULL && message.size > 0)
+ free(message.data);
+
+ data->client_fd = -1;
+ } while (client != NULL);
+ }
return 0;
}
-struct ril_client_funcs srs_client_funcs = {
+/*
+ * RIL client
+ */
+
+struct ril_client_handlers srs_handlers = {
.create = srs_create,
.destroy = srs_destroy,
- .read_loop = srs_read_loop,
+ .open = srs_open,
+ .close = srs_close,
+ .loop = srs_loop,
+};
+
+
+struct ril_client_callbacks srs_callbacks = {
+ .request_register = NULL,
+ .request_unregister = NULL,
+ .flush = NULL,
+};
+
+struct ril_client srs_client = {
+ .id = RIL_CLIENT_SRS,
+ .name = "SRS",
+ .critical = 0,
+ .handlers = &srs_handlers,
+ .callbacks = &srs_callbacks,
};
diff --git a/srs.h b/srs.h
index 873d764..5dfb4f3 100644
--- a/srs.h
+++ b/srs.h
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * 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
@@ -20,39 +20,94 @@
#ifndef _SRS_H_
#define _SRS_H_
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/un.h>
+#include <stdlib.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
+#include <samsung-ril.h>
-#include <samsung-ril-socket.h>
+/*
+ * Values
+ */
+
+#define SRS_CLIENT_CLOSE 0x00
+#define SRS_SERVER_CLOSE 0x01
+#define SRS_CLIENT_CHANGE 0x02
+#define SRS_CLIENT_IO_ERROR 0x03
-#define SRS_CLIENT_LOCK() pthread_mutex_lock(&srs_client_data->mutex)
-#define SRS_CLIENT_UNLOCK() pthread_mutex_unlock(&srs_client_data->mutex)
+/*
+ * Structures
+ */
-struct srs_client_info {
+struct srs_client {
int fd;
};
-struct srs_client_data {
- struct ril_client *client;
-
+struct srs_data {
int server_fd;
int client_fd;
+ int server_event_fd;
+ int event_fd;
+
+ pthread_t server_thread;
+
struct list_head *clients;
+};
- pthread_t thread;
- pthread_mutex_t mutex;
- int running;
+struct srs_dispatch_handler {
+ unsigned short command;
+ int (*handler)(struct srs_message *message);
};
-extern struct ril_client_funcs srs_client_funcs;
+/*
+ * Helpers
+ */
+
+/* Utils */
+const char *srs_command_string(unsigned short command);
+void srs_log_send(struct ril_client *client, struct srs_message *message);
+void srs_log_recv(struct ril_client *client, struct srs_message *message);
+int srs_header_setup(struct srs_header *header,
+ const struct srs_message *message);
+int srs_message_setup(const struct srs_header *header,
+ struct srs_message *message);
+
+/* SRS */
+int srs_send(unsigned short command, const void *data, size_t size);
+int srs_control_ping(struct srs_message *message);
+
+/* SRS client */
+int srs_client_register(struct ril_client *ril_client, int fd);
+int srs_client_unregister(struct ril_client *ril_client,
+ struct srs_client *client);
+int srs_client_flush(struct ril_client *ril_client);
+struct srs_client *srs_client_find(struct ril_client *ril_client);
+struct srs_client *srs_client_find_fd(struct ril_client *ril_client, int fd);
+struct srs_client *srs_client_find_fd_set(struct ril_client *ril_client,
+ fd_set *fds);
+int srs_client_fd_set_setup(struct ril_client *ril_client, fd_set *fds);
+int srs_client_send(struct ril_client *client, struct srs_message *message);
+int srs_client_recv(struct ril_client *client, struct srs_message *message);
+
+/* SRS server */
+int srs_server_open(struct ril_client *client);
+int srs_server_close(struct ril_client *client);
+int srs_server_loop(struct ril_client *client);
+void *srs_server_thread(void *data);
+
+/* SRS client */
+int srs_create(struct ril_client *client);
+int srs_destroy(struct ril_client *client);
+int srs_open(struct ril_client *client);
+int srs_close(struct ril_client *ril_client);
+int srs_dispatch(struct ril_client *client, struct srs_message *message);
+int srs_loop(struct ril_client *ril_client);
+
+/*
+ * RIL client
+ */
-int srs_send(unsigned short command, void *data, int length);
-void srs_control_ping(struct srs_message *message);
+extern struct ril_client_handlers srs_handlers;
+extern struct ril_client_callbacks srs_callbacks;
+extern struct ril_client srs_client;
#endif
diff --git a/ss.c b/ss.c
deleted file mode 100644
index bad8958..0000000
--- a/ss.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * This file is part of Samsung-RIL.
- *
- * Copyright (C) 2013 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define LOG_TAG "RIL-SS"
-#include <utils/Log.h>
-
-#include "samsung-ril.h"
-#include "util.h"
-
-void ipc_ss_ussd_complete(struct ipc_message_info *info)
-{
- struct ipc_gen_phone_res *phone_res;
- int rc;
-
- phone_res = (struct ipc_gen_phone_res *) info->data;
-
- rc = ipc_gen_phone_res_check(phone_res);
- if (rc < 0) {
- RIL_LOGE("There was an error, aborting USSD request");
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- ril_data.state.ussd_state = 0;
-
- return;
- }
-
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, NULL, 0);
-}
-
-void ril_request_send_ussd(RIL_Token t, void *data, size_t length)
-{
- char *data_enc = NULL;
- int data_enc_len = 0;
-
- char *message =NULL;
- struct ipc_ss_ussd *ussd = NULL;
-
- int message_size = 0xc0;
-
- if (data == NULL || length < (int) sizeof(char *))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- switch (ril_data.state.ussd_state) {
- case 0:
- case IPC_SS_USSD_NO_ACTION_REQUIRE:
- case IPC_SS_USSD_TERMINATED_BY_NET:
- case IPC_SS_USSD_OTHER_CLIENT:
- case IPC_SS_USSD_NOT_SUPPORT:
- case IPC_SS_USSD_TIME_OUT:
- RIL_LOGD("USSD Tx encoding is GSM7");
-
- data_enc_len = ascii2gsm7_ussd(data, (unsigned char**)&data_enc, length);
- if (data_enc_len > message_size) {
- RIL_LOGE("USSD message size is too long, aborting");
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-
- free(data_enc);
-
- return;
- }
-
- message = malloc(message_size);
- memset(message, 0, message_size);
-
- ussd = (struct ipc_ss_ussd *) message;
- ussd->state = IPC_SS_USSD_NO_ACTION_REQUIRE;
- ussd->dcs = 0x0f; // GSM7 in that case
- ussd->length = data_enc_len;
-
- memcpy((void *) (message + sizeof(struct ipc_ss_ussd)), data_enc, data_enc_len);
-
- free(data_enc);
-
- break;
- case IPC_SS_USSD_ACTION_REQUIRE:
- default:
- RIL_LOGD("USSD Tx encoding is ASCII");
-
- data_enc_len = asprintf(&data_enc, "%s", (char*)data);
-
- if (data_enc_len > message_size) {
- RIL_LOGE("USSD message size is too long, aborting");
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-
- free(data_enc);
-
- return;
- }
-
- message = malloc(message_size);
- memset(message, 0, message_size);
-
- ussd = (struct ipc_ss_ussd *) message;
- ussd->state = IPC_SS_USSD_ACTION_REQUIRE;
- ussd->dcs = 0x0f; // ASCII in that case
- ussd->length = data_enc_len;
-
- memcpy((void *) (message + sizeof(struct ipc_ss_ussd)), data_enc, data_enc_len);
-
- free(data_enc);
-
- break;
- }
-
- if (message == NULL) {
- RIL_LOGE("USSD message is empty, aborting");
-
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
- return;
- }
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SS_USSD,
- ipc_ss_ussd_complete);
-
- ipc_fmt_send(IPC_SS_USSD, IPC_TYPE_EXEC, (void *) message, message_size, ril_request_get_id(t));
-
- return;
-
-error:
- ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_cancel_ussd(RIL_Token t, void *data, size_t length)
-{
- struct ipc_ss_ussd ussd;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, t))
- return;
-
- memset(&ussd, 0, sizeof(ussd));
-
- ussd.state = IPC_SS_USSD_TERMINATED_BY_NET;
- ril_data.state.ussd_state = IPC_SS_USSD_TERMINATED_BY_NET;
-
- ipc_gen_phone_res_expect_to_complete(ril_request_get_id(t), IPC_SS_USSD);
-
- ipc_fmt_send(IPC_SS_USSD, IPC_TYPE_EXEC, (void *) &ussd, sizeof(ussd), ril_request_get_id(t));
-}
-
-void ipc2ril_ussd_state(struct ipc_ss_ussd *ussd, char *message[2])
-{
- if (ussd == NULL || message == NULL)
- return;
-
- switch (ussd->state) {
- case IPC_SS_USSD_NO_ACTION_REQUIRE:
- asprintf(&message[0], "%d", 0);
- break;
- case IPC_SS_USSD_ACTION_REQUIRE:
- asprintf(&message[0], "%d", 1);
- break;
- case IPC_SS_USSD_TERMINATED_BY_NET:
- asprintf(&message[0], "%d", 2);
- break;
- case IPC_SS_USSD_OTHER_CLIENT:
- asprintf(&message[0], "%d", 3);
- break;
- case IPC_SS_USSD_NOT_SUPPORT:
- asprintf(&message[0], "%d", 4);
- break;
- case IPC_SS_USSD_TIME_OUT:
- asprintf(&message[0], "%d", 5);
- break;
- }
-}
-
-void ipc_ss_ussd(struct ipc_message_info *info)
-{
- char *data_dec = NULL;
- int data_dec_len = 0;
- SmsCodingScheme codingScheme;
-
- char *message[2];
-
- struct ipc_ss_ussd *ussd = NULL;
- unsigned char state;
-
- if (info->data == NULL || info->length < sizeof(struct ipc_ss_ussd))
- goto error;
-
- memset(message, 0, sizeof(message));
-
- ussd = (struct ipc_ss_ussd *) info->data;
-
- ipc2ril_ussd_state(ussd, message);
-
- ril_data.state.ussd_state = ussd->state;
-
- if (ussd->length > 0 && info->length > 0 && info->data != NULL) {
- codingScheme = sms_get_coding_scheme(ussd->dcs);
- switch (codingScheme) {
- case SMS_CODING_SCHEME_GSM7:
- RIL_LOGD("USSD Rx encoding is GSM7");
-
- data_dec_len = gsm72ascii(info->data
- + sizeof(struct ipc_ss_ussd), &data_dec, info->length - sizeof(struct ipc_ss_ussd));
- asprintf(&message[1], "%s", data_dec);
- message[1][data_dec_len] = '\0';
-
- break;
- case SMS_CODING_SCHEME_UCS2:
- RIL_LOGD("USSD Rx encoding %x is UCS2", ussd->dcs);
-
- data_dec_len = info->length - sizeof(struct ipc_ss_ussd);
- message[1] = malloc(data_dec_len * 4 + 1);
-
- int i, result = 0;
- char *ucs2 = (char*)info->data + sizeof(struct ipc_ss_ussd);
- for (i = 0; i < data_dec_len; i += 2) {
- int c = (ucs2[i] << 8) | ucs2[1 + i];
- result += utf8_write(message[1], result, c);
- }
- message[1][result] = '\0';
- break;
- default:
- RIL_LOGD("USSD Rx encoding %x is unknown, assuming ASCII",
- ussd->dcs);
-
- data_dec_len = info->length - sizeof(struct ipc_ss_ussd);
- asprintf(&message[1], "%s", info->data + sizeof(struct ipc_ss_ussd));
- message[1][data_dec_len] = '\0';
- break;
- }
- }
-
- ril_request_unsolicited(RIL_UNSOL_ON_USSD, message, sizeof(message));
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
diff --git a/svc.c b/svc.c
deleted file mode 100644
index ed90232..0000000
--- a/svc.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * This file is part of Samsung-RIL.
- *
- * Copyright (C) 2013 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define LOG_TAG "RIL-SVC"
-#include <utils/Log.h>
-
-#include "samsung-ril.h"
-#include "util.h"
-
-int ril_oem_hook_svc_session_start(void)
-{
- if (ril_data.oem_hook_svc_session != NULL) {
- RIL_LOGE("OEM hook SVC session was already started");
- return -1;
- }
-
- ril_data.oem_hook_svc_session = calloc(1, sizeof(struct ril_oem_hook_svc_session));
-
- return 0;
-}
-
-void ril_oem_hook_svc_session_stop(void)
-{
- if (ril_data.oem_hook_svc_session == NULL) {
- RIL_LOGE("OEM hook SVC session was already stopped");
- return;
- }
-
- if (ril_data.oem_hook_svc_session->display_screen != NULL)
- free(ril_data.oem_hook_svc_session->display_screen);
-
- free(ril_data.oem_hook_svc_session);
- ril_data.oem_hook_svc_session = NULL;
-}
-
-void ipc_svc_display_screen(struct ipc_message_info *info)
-{
- char svc_end_message[] = "Samsung-RIL is asking you to End service mode";
- struct ipc_svc_display_screen_header *header;
- struct ipc_svc_display_screen_data *data;
-
- if (info == NULL || info->data == NULL || info->length < sizeof(header->count))
- return;
-
- if (ril_data.oem_hook_svc_session == NULL)
- goto error;
-
- header = (struct ipc_svc_display_screen_header *) info->data;
-
- if (header->count == 0) {
- if (ril_data.oem_hook_svc_session->token != RIL_TOKEN_NULL) {
- ril_request_complete(ril_data.oem_hook_svc_session->token, RIL_E_SUCCESS, &svc_end_message, sizeof(svc_end_message));
- ril_data.oem_hook_svc_session->token = RIL_TOKEN_NULL;
- }
-
- ril_oem_hook_svc_session_stop();
-
- return;
- }
-
- data = (struct ipc_svc_display_screen_data *) ((unsigned char *) info->data + sizeof(struct ipc_svc_display_screen_header));
-
- // Invalid responses don't start at index 0
- if (data->index != 0)
- return;
-
- if (ril_data.oem_hook_svc_session->display_screen != NULL) {
- free(ril_data.oem_hook_svc_session->display_screen);
- ril_data.oem_hook_svc_session->display_screen = NULL;
- ril_data.oem_hook_svc_session->display_screen_length = 0;
- }
-
- ril_data.oem_hook_svc_session->display_screen_length = header->count * sizeof(struct ipc_svc_display_screen_data);
- ril_data.oem_hook_svc_session->display_screen = malloc(ril_data.oem_hook_svc_session->display_screen_length);
- memcpy(ril_data.oem_hook_svc_session->display_screen, data, ril_data.oem_hook_svc_session->display_screen_length);
-
- if (ril_data.oem_hook_svc_session->token != RIL_TOKEN_NULL) {
- ril_request_complete(ril_data.oem_hook_svc_session->token, RIL_E_SUCCESS, ril_data.oem_hook_svc_session->display_screen, ril_data.oem_hook_svc_session->display_screen_length);
-
- ril_data.oem_hook_svc_session->token = RIL_TOKEN_NULL;
- }
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ipc_svc_callback(struct ipc_message_info *info)
-{
- struct ipc_gen_phone_res *phone_res;
- int rc;
-
- if (info == NULL || info->data == NULL || info->length < (int) sizeof(struct ipc_gen_phone_res))
- return;
-
- if (ril_data.oem_hook_svc_session == NULL)
- goto error;
-
- phone_res = (struct ipc_gen_phone_res *) info->data;
-
- rc = ipc_gen_phone_res_check(phone_res);
- if (rc < 0)
- goto error;
-
- if (ril_data.oem_hook_svc_session->token != RIL_TOKEN_NULL) {
- RIL_LOGE("%s: Another token is waiting", __func__);
- goto error;
- }
-
- ril_data.oem_hook_svc_session->token = ril_request_get_token(info->aseq);
-
- return;
-
-error:
- ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
-}
-
-void ril_request_oem_hook_raw(RIL_Token token, void *data, int length)
-{
- RIL_OEMHookHeader *header;
- RIL_OEMHookSvcEnterMode *svc_enter_mode;
- RIL_OEMHookSvcEndMode *svc_end_mode;
- RIL_OEMHookSvcKey *svc_key;
- struct ipc_svc_enter_data svc_enter_data;
- struct ipc_svc_end_data svc_end_data;
- struct ipc_svc_pro_keycode_data svc_pro_keycode_data;
- int svc_length;
- int rc;
-
- if (data == NULL || length < (int) sizeof(RIL_OEMHookHeader))
- goto error;
-
- if (ril_radio_state_complete(RADIO_STATE_OFF, token))
- return;
-
- header = (RIL_OEMHookHeader *) data;
-
- // Only SVC is supported
- if (header->tag != RIL_OEM_HOOK_TAG_SVC)
- goto error;
-
- svc_length = (header->length & 0xff) << 8 | (header->length & 0xff00) >> 8;
-
- switch (header->command) {
- case RIL_OEM_COMMAND_SVC_ENTER_MODE:
- if (svc_length < (int) (sizeof(RIL_OEMHookHeader) + sizeof(RIL_OEMHookSvcEnterMode)))
- goto error;
-
- svc_enter_mode = (RIL_OEMHookSvcEnterMode *) ((unsigned char *) data + sizeof(RIL_OEMHookHeader));
-
- if (svc_enter_mode->query) {
- if (ril_data.oem_hook_svc_session == NULL)
- goto error;
-
- if (ril_data.oem_hook_svc_session->display_screen != NULL && ril_data.oem_hook_svc_session->display_screen_length > 0)
- ril_request_complete(token, RIL_E_SUCCESS, ril_data.oem_hook_svc_session->display_screen, ril_data.oem_hook_svc_session->display_screen_length);
- else
- goto error;
- } else {
- rc = ril_oem_hook_svc_session_start();
- if (rc < 0) {
- RIL_LOGE("%s: Unable to start OEM hook SVC session", __func__);
- goto error;
- }
-
- memset(&svc_enter_data, 0, sizeof(svc_enter_data));
- svc_enter_data.mode = svc_enter_mode->mode;
- svc_enter_data.type = svc_enter_mode->type;
-
- if (svc_enter_data.mode == IPC_SVC_MODE_MONITOR)
- svc_enter_data.unknown = 0x00;
- else
- svc_enter_data.unknown = 0x10;
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(token), IPC_SVC_ENTER, ipc_svc_callback);
-
- ipc_fmt_send(IPC_SVC_ENTER, IPC_TYPE_SET, (unsigned char *) &svc_enter_data, sizeof(svc_enter_data), ril_request_get_id(token));
- }
- break;
- case RIL_OEM_COMMAND_SVC_END_MODE:
- if (svc_length < (int) (sizeof(RIL_OEMHookHeader) + sizeof(RIL_OEMHookSvcEndMode)))
- goto error;
-
- svc_end_mode = (RIL_OEMHookSvcEndMode *) ((unsigned char *) data + sizeof(RIL_OEMHookHeader));
-
- ril_oem_hook_svc_session_stop();
-
- memset(&svc_end_data, 0, sizeof(svc_end_data));
- svc_end_data.mode = svc_end_mode->mode;
-
- ipc_gen_phone_res_expect_to_complete(ril_request_get_id(token), IPC_SVC_END);
-
- ipc_fmt_send(IPC_SVC_END, IPC_TYPE_SET, (unsigned char *) &svc_end_data, sizeof(svc_end_data), ril_request_get_id(token));
- break;
- case RIL_OEM_COMMAND_SVC_KEY:
- if (svc_length < (int) (sizeof(RIL_OEMHookHeader) + sizeof(RIL_OEMHookSvcKey)))
- goto error;
-
- svc_key = (RIL_OEMHookSvcKey *) ((unsigned char *) data + sizeof(RIL_OEMHookHeader));
-
- if (svc_key->query) {
- if (ril_data.oem_hook_svc_session == NULL)
- goto error;
-
- if (ril_data.oem_hook_svc_session->display_screen != NULL && ril_data.oem_hook_svc_session->display_screen_length > 0)
- ril_request_complete(token, RIL_E_SUCCESS, ril_data.oem_hook_svc_session->display_screen, ril_data.oem_hook_svc_session->display_screen_length);
- else
- goto error;
- } else {
- if (ril_data.oem_hook_svc_session == NULL)
- goto error;
-
- memset(&svc_pro_keycode_data, 0, sizeof(svc_pro_keycode_data));
- svc_pro_keycode_data.key = svc_key->key;
-
- ipc_gen_phone_res_expect_to_func(ril_request_get_id(token), IPC_SVC_PRO_KEYCODE, ipc_svc_callback);
-
- ipc_fmt_send(IPC_SVC_PRO_KEYCODE, IPC_TYPE_SET, (unsigned char *) &svc_pro_keycode_data, sizeof(svc_pro_keycode_data), ril_request_get_id(token));
- }
- break;
- }
-
- return;
-
-error:
- ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0);
-}
diff --git a/util.c b/util.c
deleted file mode 100644
index 5d73d2c..0000000
--- a/util.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * 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>
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Samsung-RIL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-
-#define LOG_TAG "RIL-UTIL"
-#include <utils/Log.h>
-#include "util.h"
-
-#include "samsung-ril.h"
-
-/*
- * List
- */
-
-struct list_head *list_head_alloc(void *data, struct list_head *prev, struct list_head *next)
-{
- struct list_head *list;
-
- list = calloc(1, sizeof(struct list_head));
- if (list == NULL)
- return NULL;
-
- list->data = data;
- list->prev = prev;
- list->next = next;
-
- if (prev != NULL)
- prev->next = list;
- if (next != NULL)
- next->prev = list;
-
- return list;
-}
-
-void list_head_free(struct list_head *list)
-{
- if (list == NULL)
- return;
-
- if (list->next != NULL)
- list->next->prev = list->prev;
- if (list->prev != NULL)
- list->prev->next = list->next;
-
- memset(list, 0, sizeof(struct list_head));
- free(list);
-}
-
-/*
- * Converts a hexidecimal string to binary
- */
-void hex2bin(const char *data, int length, unsigned char *buf)
-{
- int i = 0;
- char b = 0;
- unsigned char *p = buf;
-
- length ^= 0x01;
-
- while (i < length) {
- b = 0;
-
- if (data[i] - '0' < 10)
- b = data[i] - '0';
- else if (data[i] - 'a' < 7)
- b = data[i] - 'a' + 10;
- else if (data[i] - 'A' < 7)
- b = data[i] - 'A' + 10;
- i++;
-
- b = (b << 4);
-
- if (data[i] - '0' < 10)
- b |= data[i] - '0';
- else if (data[i] - 'a' < 7)
- b |= data[i] - 'a' + 10;
- else if (data[i] - 'A' < 7)
- b |= data[i] - 'A' + 10;
- i++;
-
- *p++ = b;
- }
-}
-
-/*
- * Converts binary data to a hexidecimal string
- */
-void bin2hex(const unsigned char *data, int length, char *buf)
-{
- int i;
- char b;
- char *p = buf;
-
- for (i = 0; i < length; i++) {
- b = 0;
-
- b = (data[i] >> 4 & 0x0f);
- b += (b < 10) ? '0' : ('a' - 10);
- *p++ = b;
-
- b = (data[i] & 0x0f);
- b += (b < 10) ? '0' : ('a' - 10);
- *p++ = b;
- }
-
- *p = '\0';
-}
-
-/*
- * Converts GSM7 (8 bits) data to ASCII (7 bits)
- */
-int gsm72ascii(unsigned char *data, char **data_dec, int length)
-{
- int t, u, d, o = 0;
- int i;
-
- int dec_length;
- char *dec;
-
- dec_length = ((length * 8) - ((length * 8) % 7) ) / 7;
- dec = malloc(dec_length);
-
- memset(dec, 0, dec_length);
-
- for (i = 0 ; i < length ; i++)
- {
- d = 7 - i % 7;
- if (d == 7 && i != 0)
- o++;
-
- t = (data[i] - (((data[i] >> d) & 0xff) << d));
- u = (data[i] >> d) & 0xff;
-
- dec[i+o]+=t << (i + o) % 8;
-
- if (u)
- dec[i+1+o]+=u;
- }
-
- *data_dec = dec;
-
- return dec_length;
-}
-
-/*
- * Converts ASCII (7 bits) data to GSM7 (8 bits)
- */
-int ascii2gsm7_ussd(char *data, unsigned char **data_enc, int length)
-{
- int d_off, d_pos, a_off, a_pos = 0;
- int i;
-
- int enc_length;
- unsigned char *enc;
-
- enc_length = ((length * 7) - (length * 7) % 8) / 8;
- enc_length += (length * 7) % 8 > 0 ? 1 : 0;
-
- //FIXME: why does samsung does that?
- enc_length++;
-
- enc = malloc(enc_length);
- memset(enc, 0, enc_length);
-
- for (i = 0 ; i < length ; i++)
- {
- // offset from the right of data to keep
- d_off = i % 8;
-
- // position of the data we keep
- d_pos = ((i * 7) - (i * 7) % 8) / 8;
- d_pos += (i * 7) % 8 > 0 ? 1 : 0;
-
- // adding the data with correct offset
- enc[d_pos] |= data[i] >> d_off;
-
- // numbers of bits to omit to get data to add another place
- a_off = 8 - d_off;
- // position (on the encoded feed) of the data to add
- a_pos = d_pos - 1;
-
- // adding the data to add at the correct position
- enc[a_pos] |= data[i] << a_off;
- }
-
- *data_enc = enc;
-
- //FIXME: what is going on here?
- enc[enc_length - 2] |= 0x30;
- enc[enc_length - 1] = 0x02;
-
- return enc_length;
-}
-
-size_t ascii2gsm7(char *ascii, unsigned char *gsm7)
-{
- int ascii_length;
- int gsm7_length;
- int offset;
-
- unsigned char *p;
- int i;
-
- if (ascii == NULL)
- return -1;
-
- ascii_length = strlen(ascii);
-
- gsm7_length = ((ascii_length * 7) - (ascii_length * 7) % 8) / 8;
- gsm7_length = (ascii_length * 7) % 8 > 0 ? gsm7_length + 1 : gsm7_length;
-
- if (gsm7 == NULL)
- return gsm7_length;
-
- memset(gsm7, 0, gsm7_length);
-
- offset = 0;
- p = gsm7;
-
- for (i = 0; i < ascii_length; i++) {
- *p |= ((ascii[i] & 0x7f) >> offset) & 0xff;
-
- if (offset) {
- p--;
- *p |= ((ascii[i] & ((1 << (offset + 1)) - 1)) << (8 - offset)) & 0xff;
- p++;
- }
-
- if (offset < 7)
- p++;
-
- offset++;
- offset %= 8;
- }
-
- return gsm7_length;
-}
-
-void hex_dump(void *data, int size)
-{
- /* dumps size bytes of *data to stdout. Looks like:
- * [0000] 75 6E 6B 6E 6F 77 6E 20
- * 30 FF 00 00 00 00 39 00 unknown 0.....9.
- * (in a single line of course)
- */
-
- unsigned char *p = data;
- unsigned char c;
- int n;
- char bytestr[4] = {0};
- char addrstr[10] = {0};
- char hexstr[ 16*3 + 5] = {0};
- char charstr[16*1 + 5] = {0};
- for (n=1;n<=size;n++) {
- if (n%16 == 1) {
- /* store address for this line */
- snprintf(addrstr, sizeof(addrstr), "%.4x",
- ((unsigned int)p-(unsigned int)data) );
- }
-
- c = *p;
- if (isalnum(c) == 0) {
- c = '.';
- }
-
- /* store hex str (for left side) */
- snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
- strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
-
- /* store char str (for right side) */
- snprintf(bytestr, sizeof(bytestr), "%c", c);
- strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
-
- if (n%16 == 0) {
- /* line completed */
- RIL_LOGD("[%4.4s] %-50.50s %s", addrstr, hexstr, charstr);
- hexstr[0] = 0;
- charstr[0] = 0;
- } else if (n%8 == 0) {
- /* half line: add whitespaces */
- strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1);
- strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
- }
- p++; /* next byte */
- }
-
- if (strlen(hexstr) > 0) {
- /* print rest of buffer if not empty */
- RIL_LOGD("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
- }
-}
-
-/* writes the utf8 character encoded in v
- * to the buffer utf8 at the specified offset
- */
-int utf8_write(char *utf8, int offset, int v)
-{
-
- int result;
-
- if (v < 0x80) {
- result = 1;
- if (utf8)
- utf8[offset] = (char)v;
- } else if (v < 0x800) {
- result = 2;
- if (utf8) {
- utf8[offset + 0] = (char)(0xc0 | (v >> 6));
- utf8[offset + 1] = (char)(0x80 | (v & 0x3f));
- }
- } else if (v < 0x10000) {
- result = 3;
- if (utf8) {
- utf8[offset + 0] = (char)(0xe0 | (v >> 12));
- utf8[offset + 1] = (char)(0x80 | ((v >> 6) & 0x3f));
- utf8[offset + 2] = (char)(0x80 | (v & 0x3f));
- }
- } else {
- result = 4;
- if (utf8) {
- utf8[offset + 0] = (char)(0xf0 | ((v >> 18) & 0x7));
- utf8[offset + 1] = (char)(0x80 | ((v >> 12) & 0x3f));
- utf8[offset + 2] = (char)(0x80 | ((v >> 6) & 0x3f));
- utf8[offset + 3] = (char)(0x80 | (v & 0x3f));
- }
- }
- return result;
-}
-
-SmsCodingScheme sms_get_coding_scheme(int dataCoding)
-{
- switch (dataCoding >> 4) {
- case 0x00:
- case 0x02:
- case 0x03:
- return SMS_CODING_SCHEME_GSM7;
- case 0x01:
- if (dataCoding == 0x10)
- return SMS_CODING_SCHEME_GSM7;
- if (dataCoding == 0x11)
- return SMS_CODING_SCHEME_UCS2;
- break;
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- if (dataCoding & 0x20)
- return SMS_CODING_SCHEME_UNKNOWN;
- if (((dataCoding >> 2) & 3) == 0)
- return SMS_CODING_SCHEME_GSM7;
- if (((dataCoding >> 2) & 3) == 2)
- return SMS_CODING_SCHEME_UCS2;
- break;
- case 0xF:
- if (!(dataCoding & 4))
- return SMS_CODING_SCHEME_GSM7;
- break;
- }
- return SMS_CODING_SCHEME_UNKNOWN;
-}
-
-char *pdu_create(char *number, char *message)
-{
- unsigned char pdu_first[] = { 0x00, 0x04 };
- unsigned char pdu_toa[] = { 0x91 };
- unsigned char pdu_tp[] = { 0x00, 0x00 };
- unsigned char timestamp[7] = { 0 };
- time_t t;
- struct tm *tm;
-
- unsigned char number_length;
- unsigned char message_length;
-
- unsigned char *buffer = NULL;
- char *pdu = NULL;
- size_t length = 0;
-
- unsigned char *p;
- unsigned char a;
- char c;
- int i;
-
- if (number == NULL || message == NULL || strlen(message) > 0xff)
- return NULL;
-
- number_length = strlen(number) & 0xff;
- if (number_length % 2 != 0)
- number_length++;
- number_length /= 2;
-
- message_length = ascii2gsm7(message, NULL) & 0xff;
-
- length = sizeof(pdu_first) + sizeof(number_length) + sizeof(pdu_toa) + number_length + sizeof(pdu_tp) + sizeof(timestamp) + sizeof(message_length) + message_length;
- buffer = calloc(1, length);
-
- p = (unsigned char *) buffer;
-
- memcpy(p, &pdu_first, sizeof(pdu_first));
- p += sizeof(pdu_first);
-
- number_length = strlen(number) & 0xff;
-
- memcpy(p, &number_length, sizeof(number_length));
- p += sizeof(number_length);
- memcpy(p, &pdu_toa, sizeof(pdu_toa));
- p += sizeof(pdu_toa);
-
- i = 0;
- while (i < number_length) {
- c = number[i++];
-
- if (isdigit(c))
- *p = (c - '0') & 0x0f;
-
- if (i < number_length) {
- c = number[i++];
- if (isdigit(c))
- *p |= ((c - '0') & 0x0f) << 4;
- } else {
- *p |= 0xf << 4;
- }
-
- p++;
- }
-
- memcpy(p, &pdu_tp, sizeof(pdu_tp));
- p += sizeof(pdu_tp);
-
- t = time(NULL);
- tm = localtime(&t);
-
- a = (tm->tm_year - 100);
- timestamp[0] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
- a = (tm->tm_mon + 1);
- timestamp[1] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
- a = tm->tm_mday;
- timestamp[2] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
- a = tm->tm_hour;
- timestamp[3] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
- a = tm->tm_min;
- timestamp[4] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
- a = tm->tm_sec;
- timestamp[5] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
- a = (unsigned char) (-timezone / 900);
- timestamp[6] = ((a - (a % 10)) / 10) | ((a % 10) * 0x10);
-
- memcpy(p, &timestamp, sizeof(timestamp));
- p += sizeof(timestamp);
-
- message_length = strlen(message) & 0xff;
-
- memcpy(p, &message_length, sizeof(message_length));
- p += sizeof(message_length);
-
- ascii2gsm7(message, p);
- p += message_length;
-
- pdu = (char *) calloc(1, length * 2 + 1);
-
- bin2hex(buffer, length, pdu);
-
- free(buffer);
-
- return pdu;
-}
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..164812e
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,247 @@
+/*
+ * This file is part of Samsung-RIL.
+ *
+ * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Samsung-RIL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/eventfd.h>
+
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
+
+#include <samsung-ril.h>
+#include <utils.h>
+
+struct list_head *list_head_alloc(struct list_head *prev, struct list_head *next,
+ const void *data)
+{
+ struct list_head *list;
+
+ list = calloc(1, sizeof(struct list_head));
+ list->data = data;
+ list->prev = prev;
+ list->next = next;
+
+ if (prev != NULL)
+ prev->next = list;
+ if (next != NULL)
+ next->prev = list;
+
+ return list;
+}
+
+void list_head_free(struct list_head *list)
+{
+ if (list == NULL)
+ return;
+
+ if (list->next != NULL)
+ list->next->prev = list->prev;
+ if (list->prev != NULL)
+ list->prev->next = list->next;
+
+ memset(list, 0, sizeof(struct list_head));
+ free(list);
+}
+
+int data_dump(const void *data, size_t size)
+{
+ unsigned int cols = 8;
+ unsigned int cols_count = 2;
+ int spacer;
+ char string[81];
+ size_t length;
+ char *print;
+ unsigned char *p;
+ unsigned int offset;
+ unsigned int rollback;
+ unsigned int i, j, k;
+ int rc;
+
+ if (data == NULL || size == 0)
+ return -1;
+
+ // spacer = string length - offset print length - data print length - ascii print length
+ spacer = (sizeof(string) - 1) - 6 - (3 * cols * cols_count - 1 + (cols_count - 1)) - (cols * cols_count + cols_count - 1);
+
+ // Need 3 spacers
+ spacer /= 3;
+
+ if (spacer <= 0)
+ return -1;
+
+ p = (unsigned char *) data;
+ offset = 0;
+
+ while (offset < size) {
+ rollback = 0;
+
+ print = (char *) &string;
+ length = sizeof(string);
+
+ // Offset print
+
+ rc = snprintf(print, length, "[%04x]", offset);
+ print += rc;
+ length -= rc;
+
+ // Spacer print
+
+ for (i = 0; i < (unsigned int) spacer; i++) {
+ *print++ = ' ';
+ length--;
+ }
+
+ // Data print
+
+ for (i = 0; i < cols_count; i++) {
+ for (j = 0; j < cols; j++) {
+ if (offset < size) {
+ rc = snprintf(print, length, "%02X", *p);
+ print += rc;
+ length -= rc;
+
+ p++;
+ offset++;
+ rollback++;
+ } else {
+ for (k = 0; k < 2; k++) {
+ *print++ = ' ';
+ length--;
+ }
+ }
+
+ if (j != (cols - 1)) {
+ *print++ = ' ';
+ length--;
+ }
+ }
+
+ if (i != (cols_count - 1)) {
+ for (k = 0; k < 2; k++) {
+ *print++ = ' ';
+ length--;
+ }
+ }
+ }
+
+ // Spacer print
+
+ for (i = 0; i < (unsigned int) spacer; i++) {
+ *print++ = ' ';
+ length--;
+ }
+
+ // ASCII print
+
+ p -= rollback;
+ offset -= rollback;
+
+ for (i = 0; i < cols_count; i++) {
+ for (j = 0; j < cols; j++) {
+ if (offset < size) {
+ if (isascii(*p) && isprint(*p))
+ *print = *p;
+ else
+ *print = '.';
+
+ print++;
+ length--;
+
+ p++;
+ offset++;
+ rollback++;
+ }
+ }
+
+ if (i != (cols_count - 1) && offset < size) {
+ *print++ = ' ';
+ length--;
+ }
+ }
+
+ *print = '\0';
+
+ RIL_LOGD("%s", string);
+ }
+
+ return 0;
+}
+
+int strings_array_free(char **array, size_t size)
+{
+ unsigned int count;
+ unsigned int i;
+
+ if (array == NULL)
+ return -1;
+
+ if (size == 0) {
+ for (i = 0; array[i] != NULL; i++)
+ free(array[i]);
+ } else {
+ count = size / sizeof(char *);
+ if (count == 0)
+ return -1;
+
+ for (i = 0; i < count; i++) {
+ if (array[i] != NULL)
+ free(array[i]);
+ }
+ }
+
+ return 0;
+}
+
+int eventfd_flush(int fd)
+{
+ eventfd_t flush;
+ int rc;
+
+ rc = eventfd_read(fd, &flush);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int eventfd_recv(int fd, eventfd_t *event)
+{
+ int rc;
+
+ rc = eventfd_read(fd, event);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+int eventfd_send(int fd, eventfd_t event)
+{
+ int rc;
+
+ eventfd_flush(fd);
+
+ rc = eventfd_write(fd, event);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/util.h b/utils.h
index b962e46..f651d35 100644
--- a/util.h
+++ b/utils.h
@@ -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,33 +18,25 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _SAMSUNG_RIL_UTIL_H_
-#define _SAMSUNG_RIL_UTIL_H_
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+#include <stdlib.h>
+#include <sys/eventfd.h>
struct list_head {
struct list_head *prev;
struct list_head *next;
- void *data;
+ const void *data;
};
-struct list_head *list_head_alloc(void *data, struct list_head *prev, struct list_head *next);
+struct list_head *list_head_alloc(struct list_head *prev, struct list_head *next,
+ const void *data);
void list_head_free(struct list_head *list);
-
-void bin2hex(const unsigned char *data, int length, char *buf);
-void hex2bin(const char *data, int length, unsigned char *buf);
-int gsm72ascii(unsigned char *data, char **data_dec, int length);
-int ascii2gsm7_ussd(char *data, unsigned char **data_enc, int length);
-size_t ascii2gsm7(char *ascii, unsigned char *gsm7);
-void hex_dump(void *data, int size);
-int utf8_write(char *utf8, int offset, int v);
-char *pdu_create(char *number, char *message);
-
-typedef enum {
- SMS_CODING_SCHEME_UNKNOWN = 0,
- SMS_CODING_SCHEME_GSM7,
- SMS_CODING_SCHEME_UCS2
-} SmsCodingScheme;
-
-SmsCodingScheme sms_get_coding_scheme(int dataCoding);
+int data_dump(const void *data, size_t size);
+int strings_array_free(char **array, size_t size);
+int eventfd_flush(int fd);
+int eventfd_recv(int fd, eventfd_t *event);
+int eventfd_send(int fd, eventfd_t event);
#endif