Samsung-RIL rewrite: harder, better, probably not faster but definitely stronger master
authorPaul Kocialkowski <contact@paulk.fr>
Thu, 7 Aug 2014 11:12:15 +0000 (13:12 +0200)
committerPaul Kocialkowski <contact@paulk.fr>
Thu, 7 Aug 2014 11:12:15 +0000 (13:12 +0200)
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
38 files changed:
Android.mk
call.c
client.c
data.c [new file with mode: 0644]
disp.c [deleted file]
gen.c
gprs.c [deleted file]
include/plmn_list.h
include/plmn_list.sh
include/ril_oem.h [new file with mode: 0644]
include/samsung-ril-socket.h
include/sim.h
ipc.c
ipc.h
misc.c
net.c [deleted file]
network.c [new file with mode: 0644]
oem.c [new file with mode: 0644]
power.c [new file with mode: 0644]
pwr.c [deleted file]
rfs.c
samsung-ril.c
samsung-ril.h
sat.c [deleted file]
sec.c [deleted file]
sim.c [new file with mode: 0644]
sms.c
snd.c [deleted file]
sound.c [new file with mode: 0644]
srs-client/include/srs-client.h
srs-client/srs-client.c
srs.c
srs.h
ss.c [deleted file]
svc.c [deleted file]
util.c [deleted file]
utils.c [new file with mode: 0644]
utils.h [moved from util.h with 51% similarity]

index 08b4f48..29f0c24 100644 (file)
@@ -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 (file)
--- 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
  * 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;
 }
index 92ebc2c..1e06554 100644 (file)
--- 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
  * 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 (file)
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 (file)
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 (file)
--- 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
  * 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 (file)
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));
-}
index a415d35..8595e43 100644 (file)
@@ -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
index 26e9616..0a17068 100755 (executable)
@@ -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 (file)
index 0000000..c38db00
--- /dev/null
@@ -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
index d231e62..9e919d1 100644 (file)
@@ -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
  * 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
index dc16808..d3ec95c 100644 (file)
@@ -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
 #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 (file)
--- 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
  * 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 (file)
--- 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
 #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 (file)
--- 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
  * 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 (file)
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");
-