wgmodem2.5 support
cover wgmodem2.5 support
Hi,
This series of patches adds wgmodem2.5 support to isimodem and provides a plugin for the ST-Ericsson u8500 platform. I'm sending these on Jessica's behalf.
After discussions with Aki about how to handle the 2 versions of ISI we have implemented 2 methods to handle this, first in case the resource IDs differ between the 2 version we use this as a way to tell them apart, otherwise we check the version information from the modem server.
Caveat: We haven't found any good way of integrating the u8500 IMEI specific handling into the u8500 plugin, it currently resides in devinfo.
Jessica Nilsson (18):
gisi: pipe and pep for wgmodem2.5
gisi: modem version detection
isimodem: general build updates for wgmodem2.5
gisi: fix subscription for wgmodem2.5
plugins: add plugin for u8500
plugins: add u8500 to udev
isimodem: add wgmodem2.5 to devinfo
isimodem: UICC sim support for wgmodem2.5
isimodem: clip colp clir colr wgmodem2.5
isimodem: wgmodem2.5 added to voicecall
isimodem: gprs-context updates wgmodem2.5
isimodem: wgmodem2.5 support in USSD
isimodem: SS_GSM_BARRING_INFO added
isimodem: wgmodem2.5 added to call-forwarding
isimodem: wgmodem2.5 added to ssn
isimodem: sms updated with wgmodem2.5
isimodem: CBS for wgmodem2.5
isimodem: initial support for UICC phonebook
Makefile.am | 7 +- drivers/isimodem/call-barring.c | 99 ++- drivers/isimodem/call-forwarding.c | 30 +- drivers/isimodem/call-settings.c | 697 ++++++++++- drivers/isimodem/call.h | 89 ++ drivers/isimodem/cbs.c | 425 ++++++- drivers/isimodem/debug.c | 197 +++ drivers/isimodem/debug.h | 10 + drivers/isimodem/devinfo.c | 161 ++- drivers/isimodem/gprs-context.c | 95 +- drivers/isimodem/info.h | 3 + drivers/isimodem/mtc.h | 38 + drivers/isimodem/phonebook.c | 1241 ++++++++++++++++++- drivers/isimodem/sim.c | 2381 ++++++++++++++++++++++++++++++++++-- drivers/isimodem/sms.c | 972 +++++++++++++-- drivers/isimodem/sms.h | 41 +- drivers/isimodem/ss.h | 22 + drivers/isimodem/ssn.c | 382 ++++++- drivers/isimodem/uicc.h | 268 ++++ drivers/isimodem/ussd.c | 36 +- drivers/isimodem/voicecall.c | 218 +++- gisi/message.c | 8 + gisi/message.h | 1 + gisi/modem.c | 51 +- gisi/modem.h | 7 + gisi/pep.c | 330 +++++ gisi/pep.h | 6 + gisi/pipe.c | 180 +++- gisi/pipe.h | 17 + plugins/ofono.rules | 3 + plugins/u8500.c | 506 ++++++++ plugins/udev.c | 2 + 32 files changed, 8073 insertions(+), 450 deletions(-) create mode 100644 drivers/isimodem/uicc.h create mode 100644 plugins/u8500.c
--
1.7.3.5
PATCH 1/18 gisi: pipe and pep for wgmodem2.5
From: Jessica Nilsson <[email protected]>
--- gisi/message.c | 8 ++ gisi/message.h | 1 + gisi/modem.c | 20 ++++ gisi/modem.h | 1 + gisi/pep.c | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gisi/pep.h | 6 + gisi/pipe.c | 180 ++++++++++++++++++++++++++++-- gisi/pipe.h | 17 +++ 8 files changed, 551 insertions(+), 12 deletions(-)
gisi/message.c +8 -0
@@ -65,6 +65,14 @@ uint8_t g_isi_msg_resource(const GIsiMessage *msg)return msg->addr->spn_resource; } +uint8_t g_isi_msg_device (const GIsiMessage *msg) +{ +if (msg ==NULL || msg->addr ==NULL ) +return 0 ; + +return msg->addr->spn_dev; +} +uint16_t g_isi_msg_object (const GIsiMessage *msg) {if (msg ==NULL || msg->addr ==NULL )
gisi/message.h +1 -0
@@ -52,6 +52,7 @@ int g_isi_msg_version_minor(const GIsiMessage *msg);int g_isi_msg_error (const GIsiMessage *msg);const char *g_isi_msg_strerror (const GIsiMessage *msg);uint8_t g_isi_msg_resource (const GIsiMessage *msg); +uint8_t g_isi_msg_device (const GIsiMessage *msg);uint16_t g_isi_msg_object (const GIsiMessage *msg);uint8_t g_isi_msg_id (const GIsiMessage *msg);
gisi/modem.c +20 -0
@@ -519,6 +519,26 @@ GIsiModem *g_isi_modem_create_by_name(const char *name)return g_isi_modem_create (if_nametoindex (name)); } +guint g_isi_modem_add_to_watch (GIsiModem *modem,int fd) +{ +GIOChannel *channel; +guint watch; + +if (modem ==NULL || fd <0 ) +return 0 ; + + channel =g_io_channel_unix_new (fd); +g_io_channel_set_close_on_unref (channel, TRUE); +g_io_channel_set_encoding (channel,NULL ,NULL ); +g_io_channel_set_buffered (channel, FALSE); + watch =g_io_add_watch (channel, +G_IO_IN |G_IO_ERR |G_IO_HUP |G_IO_NVAL , + isi_callback, modem); +g_io_channel_unref (channel); + +return watch; +} +void *g_isi_modem_set_userdata (GIsiModem *modem,void *data) {void *old;
gisi/modem.h +1 -0
@@ -48,6 +48,7 @@ typedef void (*GIsiDebugFunc)(const char *fmt, ...);GIsiModem *g_isi_modem_create (unsigned index);GIsiModem *g_isi_modem_create_by_name (const char *name);void g_isi_modem_destroy (GIsiModem *modem); +guint g_isi_modem_add_to_watch (GIsiModem *modem,int fd);unsigned g_isi_modem_index (GIsiModem *modem);
gisi/pep.c +330 -0
355 lines not on this page · raw message
gisi/pep.h +6 -0
@@ -23,6 +23,7 @@#define __GISI_PEP_H#include "modem.h" +#include "pipe.h" #ifdef __cplusplusextern "C" {
@@ -37,6 +38,11 @@ uint16_t g_isi_pep_get_object(const GIsiPEP *pep);unsigned g_isi_pep_get_ifindex (const GIsiPEP *pep);char *g_isi_pep_get_ifname (const GIsiPEP *pep,char *ifname); +void g_isi_pep_enable (GIsiPipe *pipe,uint8_t dev); +gboolean g_isi_pep_connect (GIsiPipe *pipe,uint8_t obj,uint8_t dev); +void g_isi_pep_disconnect (GIsiPipe *pipe,uint8_t dev); + + #ifdef __cplusplus }#endif
gisi/pipe.c +168 -12
293 lines not on this page · raw message
gisi/pipe.h +17 -0
@@ -26,24 +26,41 @@extern "C" {#endif +#include "client.h" +struct _GIsiPipe ;typedef struct _GIsiPipe GIsiPipe ; +typedef void (*GIsiPipeHandler )(GIsiPipe *pipe);typedef void (*GIsiPipeErrorHandler )(GIsiPipe *pipe);GIsiPipe *g_isi_pipe_create (GIsiModem *modem,GIsiPipeHandler cb,uint16_t obj1,uint16_t obj2,uint8_t type1,uint8_t type2);void g_isi_pipe_destroy (GIsiPipe *pipe); +void g_isi_pipe_server_destroy (GIsiPipe *pipe);void g_isi_pipe_set_error_handler (GIsiPipe *pipe,GIsiPipeErrorHandler cb);int g_isi_pipe_get_error (const GIsiPipe *pipe);void *g_isi_pipe_set_userdata (GIsiPipe *pipe,void *data);void *g_isi_pipe_get_userdata (GIsiPipe *pipe);uint8_t g_isi_pipe_get_handle (GIsiPipe *pipe); +gboolean g_isi_pipe_get_enabling (GIsiPipe *pipe); +void g_isi_pipe_set_enabling (GIsiPipe *pipe,gboolean value); +void g_isi_pipe_set_enabled (GIsiPipe *pipe,gboolean value);int g_isi_pipe_start (GIsiPipe *pipe); +GIsiClient *g_isi_pipe_client (GIsiPipe *pipe); +void g_isi_pipe_set_handle (GIsiPipe *pipe,uint8_t handle); +void g_isi_pipe_start_handler (GIsiPipe *pipe); + +void g_isi_pipe_handle_error (GIsiPipe *pipe,uint8_t code); +void g_isi_pipe_set_error_general (GIsiPipe *pipe); +void g_isi_pipe_set_error_timeout (GIsiPipe *pipe); +void g_isi_pipe_set_error_invalid_handle (GIsiPipe *pipe); + + #ifdef __cplusplus }#endif
Signature · 1 line
1.7.3.5
Re: [PATCH 01/18] gisi: pipe and pep for wgmodem2.5
Quoted 1 line · you
From: Jessica Nilsson <[email protected]>
I don't understand why you put a pipe controller in user-space. Why do we need a pipe controller at all? As far as I can tell, implementing connect() on PEP sockets would be much more elegant (and symmetric).
Signature · 2 lines
Rémi Denis-Courmont Nokia Devices R&D, Maemo Software, Helsinki
RE: [PATCH 01/18] gisi: pipe and pep for wgmodem2.5
Quoted 3 lines
As far as I can tell, implementing
connect()on PEP
sockets would be much more elegant (and symmetric).
Lacking better things to do, that's something we (= you) could push upstream?
MikaL
Re: [PATCH 01/18] gisi: pipe and pep for wgmodem2.5
In reply to Rémi Denis-CourmontQuoted 7 lines · Rémi Denis-Courmont
Quoted 1 line · you
From: Jessica Nilsson<[email protected]>
I don't understand why you put a pipe controller in user-space. Why do we need a pipe controller at all? As far as I can tell, implementing
connect()on PEP sockets would be much more elegant (and symmetric).
Previously there was no pipe controller in the kernel so we needed one in ofono.
We are looking into changing it.
Regards
Andreas
PATCH 2/18 gisi: modem version detection
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- gisi/modem.c | 27 +++++++++++++++++++++++++++ gisi/modem.h | 6 ++++++ 2 files changed, 33 insertions(+), 0 deletions(-)
gisi/modem.c +27 -0
@@ -62,6 +62,7 @@ struct _GIsiModem {uint8_t device;GHashTable *services;gboolean subs_source; +GIsiVersion version;int req_fd;int ind_fd;guint req_watch;
@@ -539,6 +540,32 @@ guint g_isi_modem_add_to_watch(GIsiModem *modem, int fd)return watch; } +gboolean g_isi_modem_set_version (GIsiModem *modem,const GIsiVersion version) +{ +if (modem ==NULL ) +return FALSE; + + modem->version = version; + +return TRUE; +} + +int g_isi_modem_version_major (const GIsiModem *modem) +{ +if (modem ==NULL ) +return -1 ; + +return modem->version.major; +} + +int g_isi_modem_version_minor (const GIsiModem *modem) +{ +if (modem ==NULL ) +return -1 ; + +return modem->version.minor; +} +void *g_isi_modem_set_userdata (GIsiModem *modem,void *data) {void *old;
gisi/modem.h +6 -0
@@ -58,6 +58,12 @@ int g_isi_modem_set_device(GIsiModem *modem, uint8_t dev);void g_isi_modem_set_trace (GIsiModem *modem,GIsiNotifyFunc notify);void g_isi_modem_set_debug (GIsiModem *modem,GIsiDebugFunc debug); +gboolean g_isi_modem_set_version (GIsiModem *modem, +const GIsiVersion version); + +int g_isi_modem_version_major (const GIsiModem *modem); +int g_isi_modem_version_minor (const GIsiModem *modem); +void *g_isi_modem_set_userdata (GIsiModem *modem,void *data);void *g_isi_modem_get_userdata (GIsiModem *modem);
Signature · 1 line
1.7.3.5
PATCH 3/18 isimodem: general build updates for wgmodem2.5
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/debug.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/isimodem/debug.h | 8 +++++++ drivers/isimodem/mtc.h | 38 ++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 0 deletions(-)
drivers/isimodem/debug.c +48 -0
@@ -166,6 +166,54 @@ const char *mtc_modem_state_name(enum mtc_modem_state value)return "MTC_<UNKNOWN>" ; } +const char *mce_message_id_name (enum mce_message_id value) +{ +switch (value) { +_ (MCE_MODEM_STATE_IND ); +_ (MCE_MODEM_STATE_QUERY_REQ ); +_ (MCE_MODEM_STATE_QUERY_RESP ); +_ (MCE_RF_STATE_REQ ); +_ (MCE_RF_STATE_RESP ); +_ (MCE_RF_STATE_IND ); +_ (MCE_RF_STATE_QUERY_REQ ); +_ (MCE_RF_STATE_QUERY_RESP ); +_ (MCE_POWER_OFF_REQ ); +_ (MCE_POWER_OFF_RESP ); + } +return "MCE_<UNKNOWN>" ; +} + +const char *mce_modem_state_name (enum mce_modem_state value) +{ +switch (value) { +_ (MCE_NORMAL ); +_ (MCE_LOCAL ); +_ (MCE_SW_RESET ); +_ (MCE_POWER_OFF ); + } +return "MCE_<UNKNOWN>" ; +} + +const char *mce_status_info (enum mce_status_info value) +{ +switch (value) { +_ (MCE_OK ); +_ (MCE_FAIL ); +_ (MCE_ALREADY_ACTIVE ); +_ (MCE_TRANSITION_ONGOING ); + } +return "MCE_<UNKNOWN>" ; +} + +const char *mce_rf_state_name (enum mce_rf_state value) +{ +switch (value) { +_ (MCE_RF_OFF ); +_ (MCE_RF_ON ); + } +return "MCE_RF<UNKNOWN>" ; +} +const char *sms_isi_cause_name (enum sms_isi_cause value) {switch (value) {
drivers/isimodem/debug.h +8 -0
@@ -41,6 +41,14 @@ const char *ss_ussd_type_name(enum ss_ussd_type value);const char *mtc_isi_cause_name (enum mtc_isi_cause value);const char *mtc_message_id_name (enum mtc_message_id value);const char *mtc_modem_state_name (enum mtc_modem_state value); +const char *mce_rf_state_name (enum mce_rf_state value); + +const char *mce_message_id_name (enum mce_message_id value); +const char *mce_modem_state_name (enum mce_modem_state value); +const char *mce_status_info (enum mce_status_info value); + +const char *uicc_subblock_name (uint8_t value); +const char *uicc_status_name (uint8_t value);const char *sms_gsm_cause_name (enum sms_gsm_cause value);const char *sms_isi_cause_name (enum sms_isi_cause value);
drivers/isimodem/mtc.h +38 -0
@@ -27,9 +27,47 @@ extern "C" {#endif #define PN_MTC 0x15 +#define PN_MODEM_MCE 0xC2#define MTC_TIMEOUT 5#define MTC_STATE_REQ_TIMEOUT (6 + 5) +enum mce_message_id { +MCE_MODEM_STATE_IND =0x00 , +MCE_MODEM_STATE_QUERY_REQ =0x01 , +MCE_MODEM_STATE_QUERY_RESP =0x02 , +MCE_RF_STATE_REQ =0x03 , +MCE_RF_STATE_RESP =0x04 , +MCE_RF_STATE_IND =0x05 , +MCE_RF_STATE_QUERY_REQ =0x06 , +MCE_RF_STATE_QUERY_RESP =0x07 , +MCE_POWER_OFF_REQ =0x08 , +MCE_POWER_OFF_RESP =0x09 +}; + +enum mce_rf_state { +MCE_RF_OFF =0x00 , +MCE_RF_ON =0x01 +}; + +enum mce_status_info { +MCE_OK =0x00 , +MCE_FAIL =0x01 , +MCE_ALREADY_ACTIVE =0x06 , +MCE_TRANSITION_ONGOING =0x16 +}; + +enum mce_modem_state { +MCE_NORMAL =0x00 , +MCE_LOCAL =0x01 , +MCE_SW_RESET =0x80 , +MCE_POWER_OFF =0x81 +}; + +enum mce_isi_action { +MCE_START =0x03 , +MCE_READY =0x04 +}; +enum mtc_isi_cause {MTC_OK =0x00 ,MTC_FAIL =0x01 ,
Signature · 1 line
1.7.3.5
Re: [PATCH 03/18] isimodem: general build updates for wgmodem2.5
Hi,
2011/2/15 Andreas Westin <[email protected]>:
Quoted 7 lines
From: Jessica Nilsson <[email protected]>
---
drivers/isimodem/debug.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++drivers/isimodem/debug.h| 8 +++++++
drivers/isimodem/mtc.h | 38 ++++++++++++++++++++++++++++++++++++3 files changed, 94 insertions(+), 0 deletions(-)
I pushed this patch, but modified the commit message a bit.
Cheers,
Aki
PATCH 4/18 gisi: fix subscription for wgmodem2.5
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- gisi/modem.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
gisi/modem.c +3 -1
@@ -370,13 +370,15 @@ static gboolean modem_subs_update(gpointer data)if (legacy) msg[3 + count] = mux->resource; -else +else {/* Resource field is 32bit and Little-endian */ msg[4 + count *4 +3 ] = mux->resource; + } count++; } + commgr.spn_dev = legacy ? modem->device :PN_DEV_MODEM ; len = legacy ?3 + count :4 + count *4 ; msg[2 ] = count;
Signature · 1 line
1.7.3.5
Re: [PATCH 04/18] gisi: fix subscription for wgmodem2.5
Hi Andreas,
2011/2/15 Andreas Westin <[email protected]>:
Quoted 7 lines
if (legacy)
msg[3 + count] =mux->resource;
- else
+ else {
/* Resource field is 32bit and Little-endian */ msg[4 + count * 4 + 3] =mux->resource;
+ }
Curly brackets are either in both if and else, or in neither. I actually prefer not to have them here, since the first line is just a comment in the else statement. ;)
Quoted 6 lines
count++;
}+ commgr.spn_dev = legacy ?
modem->device:PN_DEV_MODEM; len = legacy ? 3 + count : 4 + count * 4; msg[2] = count;
This is not necessary, as a modem plugin is supposed to call g_isi_modem_set_device() to set the modem->device to whatever it needs to right after creating the GIsiModem instance.
In other words, the assumption is that when the GIsiModem instace is actually used, all necessary internal data, such as flags and the remote device have already been set.
Cheers,
Aki
Re: [PATCH 04/18] gisi: fix subscription for wgmodem2.5
Hi Aki,
Quoted 3 lines · Aki Niemi
Curly brackets are either in both if and else, or in neither. I actually prefer not to have them here, since the first line is just a comment in the else statement. ;)
Yes you're right :)
Quoted 7 lines
This is not necessary, as a modem plugin is supposed to call
g_isi_modem_set_device()to set themodem->deviceto whatever it needs to right after creating the GIsiModem instance.In other words, the assumption is that when the GIsiModem instace is actually used, all necessary internal data, such as flags and the remote device have already been set.
Tested and works fine, will submit a new patch for the u8500 plugin. This is not done in the n900 plugin though, perhaps not necessary ?
Regards
Andreas
Re: [PATCH 04/18] gisi: fix subscription for wgmodem2.5
Hi Andreas,
2011/2/16 Andreas WESTIN <[email protected]>:
Quoted 2 lines
Tested and works fine, will submit a new patch for the u8500 plugin. This is not done in the n900 plugin though, perhaps not necessary ?
The default is PN_DEV_HOST, which is what the N900 uses.
Cheers,
Aki
PATCH 5/18 plugins: add plugin for u8500
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- Makefile.am | 3 + plugins/u8500.c | 506 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 509 insertions(+), 0 deletions(-) create mode 100644 plugins/u8500.c
Makefile.am +3 -0
@@ -144,6 +144,9 @@ builtin_sources += plugins/isiusb.c builtin_modules += n900 builtin_sources += plugins/n900.c plugins/nokia-gpio.h plugins/nokia-gpio.c + +builtin_modules += u8500 +builtin_sources += plugins/u8500.c endif if ATMODEM
plugins/u8500.c new file +506 -0
506 lines not on this page · raw message
Signature · 1 line
1.7.3.5
Re: [PATCH 05/18] plugins: add plugin for u8500
Hi,
2011/2/15 Andreas Westin <[email protected]>:
Quoted 12 lines
plugins/u8500.c new file +12
-0+static int u8500_probe (struct ofono_modem *modem) +{ + const char *ifname = ofono_modem_get_string(modem, "Interface"); + unsigned address = ofono_modem_get_integer(modem, "Address"); + GIsiModem *isimodem; + GIsiClient *client = NULL; + GIsiPhonetNetlink *link = NULL; + struct isi_data *isi = NULL; + + if (ifname == NULL) + return -EINVAL; +
plugins/u8500.c line 297
Quoted 10 lines
plugins/u8500.c new file +10
-0+ DBG("(%p) with %s", modem, ifname); + + isimodem = g_isi_modem_create_by_name(ifname); + if (isimodem == NULL) { + DBG("Interface=%s: %s", ifname, strerror(errno)); + return -errno; + } + + if (!g_isi_modem_set_version(isimodem, modemversion)) + return -EINVAL;
I'm not going to add this API in GIsiModem. If we went this route, and used vendor quirks inside the isimodem driver, then it would make a whole lot more sense to do it in the driver create(), not here.
But we're not going that route. Each driver detects the version of the ISI service it is talking to when it is probed.
Cheers,
Aki
Re: [PATCH 05/18] plugins: add plugin for u8500
Quoted 30 lines · Aki Niemi
Hi,
2011/2/15 Andreas Westin<[email protected]>:
Quoted 12 lines
plugins/u8500.c new file +12
-0+static int u8500_probe (struct ofono_modem *modem) +{ +const char *ifname =ofono_modem_get_string (modem,"Interface" ); +unsigned address =ofono_modem_get_integer (modem,"Address" ); +GIsiModem *isimodem; +GIsiClient *client =NULL ; +GIsiPhonetNetlink *link =NULL ; +struct isi_data *isi =NULL ; + +if (ifname ==NULL ) +return -EINVAL ; +plugins/u8500.c line 297
Quoted 10 lines
plugins/u8500.c new file +10
-0+DBG ("(%p) with %s" , modem, ifname); + + isimodem =g_isi_modem_create_by_name (ifname); +if (isimodem ==NULL ) { +DBG ("Interface=%s: %s" , ifname,strerror (errno)); +return -errno; + } + +if (!g_isi_modem_set_version (isimodem, modemversion)) +return -EINVAL ;I'm not going to add this API in GIsiModem. If we went this route, and used vendor quirks inside the isimodem driver, then it would make a whole lot more sense to do it in the driver
create(), not here.
Quoted 3 lines
But we're not going that route. Each driver detects the version of the ISI service it is talking to when it is probed.
Yes this should not be there, but maybe I misunderstood you regarding the version handling. I was under the impression that we checked the version we get from doing PN_MTC or PN_MODEM_MCE ?
Cheers
Andreas
Re: [PATCH 05/18] plugins: add plugin for u8500
Hi Andreas,
2011/2/16 Andreas WESTIN <[email protected]>:
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
+ if (!g_isi_modem_set_version(isimodem, modemversion))
+ return-EINVAL;I'm not going to add this API in GIsiModem. If we went this route, and used vendor quirks inside the isimodem driver, then it would make a whole lot more sense to do it in the driver
create(), not here.
Quoted 7 lines
Quoted 3 lines
But we're not going that route. Each driver detects the version of the ISI service it is talking to when it is probed.
Yes this should not be there, but maybe I misunderstood you regarding the version handling. I was under the impression that we checked the version we get from doing
PN_MTCorPN_MODEM_MCE?
The modem driver is a bit of a special case again. There is no generic isimodem modem driver, but each modem plugin implements their own version. Here, just use PN_MODEM_MCE, since that is what the U8500 uses.
Cheers,
Aki
PATCH 6/18 plugins: add u8500 to udev
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- plugins/ofono.rules | 3 +++ plugins/udev.c | 2 ++ 2 files changed, 5 insertions(+), 0 deletions(-)
plugins/ofono.rules +3 -0
@@ -356,6 +356,9 @@ SUBSYSTEMS=="usb", ENV{OFONO_DRIVER}="isiusb", ENV{OFONO_ISI_ADDRESS}="16" # Nokia N900 modem SUBSYSTEMS=="hsi", ENV{OFONO_DRIVER}="n900", ENV{OFONO_ISI_ADDRESS}="108" +# STE u8500 +KERNEL=="shrm0", ENV{OFONO_DRIVER}="u8500" + LABEL="ofono_isi_end" SUBSYSTEM!="usb", GOTO="ofono_end"
plugins/udev.c +2 -0
@@ -666,6 +666,8 @@ done:add_nokia (modem, udev_device); else if (g_strcmp0(driver, "isiusb") == 0) add_isi(modem, udev_device); + else if (g_strcmp0(driver, "u8500") == 0) + add_isi(modem, udev_device); else if (g_strcmp0(driver, "n900") == 0) add_isi(modem, udev_device); else if (g_strcmp0(driver, "gobi") == 0)
Signature · 1 line
1.7.3.5
PATCH 7/18 isimodem: add wgmodem2.5 to devinfo
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/debug.c | 1 + drivers/isimodem/devinfo.c | 161 ++++++++++++++++++++++++++++++++++++-------- drivers/isimodem/info.h | 3 + 3 files changed, 136 insertions(+), 29 deletions(-)
drivers/isimodem/debug.c +1 -0
@@ -481,6 +481,7 @@ const char *info_message_id_name(enum info_message_id value)const char *info_subblock_name (enum info_subblock value) {switch (value) { +_ (INFO_SB_MODEMSW_VERSION );_ (INFO_SB_PRODUCT_INFO_NAME );_ (INFO_SB_PRODUCT_INFO_MANUFACTURER );_ (INFO_SB_SN_IMEI_PLAIN );
drivers/isimodem/devinfo.c +132 -29
261 lines not on this page · raw message
drivers/isimodem/info.h +3 -0
@@ -27,6 +27,8 @@ extern "C" {#endif #define PN_PHONE_INFO 0x1B +#define PN_MODEM_INFO 0xC5 +#define PN_EPOC_INFO 98#define INFO_TIMEOUT 5
@@ -50,6 +52,7 @@ enum info_message_id { };enum info_subblock { +INFO_SB_MODEMSW_VERSION =0x00 ,INFO_SB_PRODUCT_INFO_NAME =0x01 ,INFO_SB_PRODUCT_INFO_MANUFACTURER =0x07 ,INFO_SB_SN_IMEI_PLAIN =0x41 ,
Signature · 1 line
1.7.3.5
Re: [PATCH 07/18] isimodem: add wgmodem2.5 to devinfo
Hi,
2011/2/15 Andreas Westin <[email protected]>:
drivers/isimodem/devinfo.c static void isi_query_manufacturer(struct ofono_devinfo *info, · line 124
Quoted 11 lines
drivers/isimodem/devinfo.c +7
-0@@ -111,17 +115,22 @@ static void isi_query_manufacturer(struct ofono_devinfo *info, struct devinfo_data *dev = ofono_devinfo_get_data(info); struct isi_cb_data *cbd = isi_cb_data_new(dev, cb, data); + if (cbd == NULL || dev == NULL) + goto error; + + if (g_isi_client_resource(dev->client) == PN_MODEM_INFO) { + goto error; + } else { +
So do I understand this right, that PN_MODEM_INFO doesn't return any of manufacturer, model, revision, or serial information at all?
If so, then I don't understand why any of this code is here. To implement the serial number query, you just need to implement and register your custom devinfo driver in the U8500 plugin that reads the serial from under /etc.
Cheers,
Aki
PATCH 8/18 isimodem: UICC sim support for wgmodem2.5
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- Makefile.am | 4 +- drivers/isimodem/debug.c | 84 ++ drivers/isimodem/debug.h | 1 + drivers/isimodem/sim.c | 2381 ++++++++++++++++++++++++++++++++++++++++++++-- drivers/isimodem/uicc.h | 268 ++++++ 5 files changed, 2662 insertions(+), 76 deletions(-) create mode 100644 drivers/isimodem/uicc.h
Makefile.am +3 -1
@@ -137,7 +137,9 @@ builtin_sources += $(gisi_sources) \ drivers/isimodem/gprs.c \ drivers/isimodem/gprs-context.c \ drivers/isimodem/gpds.h \ - drivers/isimodem/audio-settings.c + drivers/isimodem/audio-settings.c \ + drivers/isimodem/uicc.h + builtin_modules += isiusb builtin_sources += plugins/isiusb.c
drivers/isimodem/debug.c +84 -0
90 lines not on this page · raw message
drivers/isimodem/debug.h +1 -0
@@ -27,6 +27,7 @@#include "ss.h" #include "mtc.h" #include "sms.h" +#include "uicc.h" #include "sim.h" #include "info.h" #include "call.h"
drivers/isimodem/sim.c +2306 -75
2,563 lines not on this page · raw message
drivers/isimodem/uicc.h new file +268 -0
268 lines not on this page · raw message
Signature · 1 line
1.7.3.5
Re: [PATCH 08/18] isimodem: UICC sim support for wgmodem2.5
Hi,
2011/2/15 Andreas Westin <[email protected]>:
(snip)
Quoted 39 lines
drivers/isimodem/sim.c +12
-2@@ -3,6 +3,7 @@ * oFono - Open Source Telephony * * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) ST-Ericsson SA 2011. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as@@ -33,24 +34,216 @@ #include <gisi/message.h> #include <gisi/client.h> +#include <gisi/iter.h> #include <ofono/log.h> #include <ofono/modem.h> #include <ofono/sim.h> -#include "simutil.h" +#include <ofono/dbus.h> +#include "simutil.h" #include "isimodem.h" #include "isiutil.h" #include "sim.h" +#include "uicc.h" #include "debug.h" -#define SIM_MAX_SPN_LENGTH 16 +#define PIN_PROMPT +#define STATUS_WORD_HANDLING + +#define SIM_MAX_SPN_LENGTH 16 +#define CLIENT_ID 1 + +
drivers/isimodem/sim.c line 67
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+/* File info parameters */ +#define FCP_TEMPLATE 0x62 +#define FCP_FILE_SIZE 0x80 +#define FCP_FILE_DESC 0x82 +#define FCP_FILE_ID 0x83 +#define FCP_FILE_LIFECYCLE 0x8A +#define FCP_FILE_SECURITY_ARR 0x8B +#define FCP_FILE_SECURITY_COMPACT 0x8C +#define FCP_FILE_SECURITY_EXPANDED 0xAB +#define FCP_PIN_STATUS 0xC6
This should be an enum.
drivers/isimodem/sim.c line 68
Quoted 1 line
drivers/isimodem/sim.c +1
-0+#define SIM_EFARR_FILEID 0x6F06
Why is this not in simutil.h?
Quoted 66 lines
drivers/isimodem/sim.c +62
-0+#define ADF_USIM 0x7FFF +#define MAX_SIM_APPS 10 +#define NOT_AVAILABLE -1 +#define NOT_ACTIVATED -1 struct sim_data { GIsiClient *client; + GIsiClient *primary; + GIsiClient *secondary; + gboolean iccid; gboolean registered; + gboolean uicc_app_started; + gboolean pin_state_received; + gboolean passwd_required; + int app_id; + int trying_app_id; + int app_type; + int trying_app_type; + uint8_t client_id; + uint8_t current_pin_id; + uint8_t pin1_id; + uint8_t pin2_id; +}; + +struct ofono_sim_local { + char *iccid; + char *imsi; + enum ofono_sim_phase phase; + unsigned char mnc_length; + GSList *own_numbers; + GSList *new_numbers; + GSList *service_numbers; + gboolean sdn_ready; + enum ofono_sim_state state; + enum ofono_sim_password_type pin_type; + gboolean locked_pins[OFONO_SIM_PASSWORD_INVALID]; + char **language_prefs; + GQueue *simop_q; + gint simop_source; + unsigned char efmsisdn_length; + unsigned char efmsisdn_records; + unsigned char *efli; + unsigned char efli_length; + enum ofono_sim_cphs_phase cphs_phase; + unsigned char cphs_service_table[2]; + struct ofono_watchlist *state_watches; + const struct ofono_sim_driver *driver; + void *driver_data; + struct ofono_atom *atom; + DBusMessage *pending; +}; + +struct sim_passwd_to_pin_id { + uint8_t passwd_type; + uint8_t pin_id; +}; + +static struct sim_passwd_to_pin_id const pin_ids[] = { + {OFONO_SIM_PASSWORD_NONE, 0}, + {OFONO_SIM_PASSWORD_SIM_PIN, 1}, + {OFONO_SIM_PASSWORD_PHSIM_PIN, 0}, + {OFONO_SIM_PASSWORD_PHFSIM_PIN, 0}, + {OFONO_SIM_PASSWORD_SIM_PIN2, -1}, + {OFONO_SIM_PASSWORD_PHNET_PIN, 0x11}, + {OFONO_SIM_PASSWORD_PHNETSUB_PIN, 0}, + {OFONO_SIM_PASSWORD_PHSP_PIN, 0},
drivers/isimodem/sim.c line 144
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+ {OFONO_SIM_PASSWORD_PHCORP_PIN, 0}, + {OFONO_SIM_PASSWORD_SIM_PUK, -1}, + {OFONO_SIM_PASSWORD_PHFSIM_PUK, 0}, + {OFONO_SIM_PASSWORD_SIM_PUK2, -1}, + {OFONO_SIM_PASSWORD_PHNET_PUK, 0}, + {OFONO_SIM_PASSWORD_PHNETSUB_PUK, 0}, + {OFONO_SIM_PASSWORD_PHSP_PUK, 0}, + {OFONO_SIM_PASSWORD_PHCORP_PUK, 0}, + {OFONO_SIM_PASSWORD_INVALID, 0} +};
I don't like you mixing hex and decimal values, and above all, some of these are also assigning signed values to an unsigned variable.
drivers/isimodem/sim.c line 152
Quoted 8 lines
drivers/isimodem/sim.c +8
-0+ +const uint8_t upin_id =0x11 ; + +/* Current SIM */ +static struct ofono_sim *uicc_sim; +/* UICC client */ +static GIsiClient *pn_uicc_client; +static int uicc_users;
I doubt this is going to work.
So what happens when someone plugs in two isimodems into the system? Is there a specific reason that the UICC client needs to be shared among the rest of the drivers? Why can't each of them just create their own instance, and let the gisi modem handle the client reuse optimizations.
drivers/isimodem/sim.c line 159
Quoted 7 lines
drivers/isimodem/sim.c +7
-0+ +struct sim_applications { + int app_list[MAX_SIM_APPS]; + int app_type[MAX_SIM_APPS]; +}; + +struct sim_applications *sim_application_list_p;
Is this a global list, or a per-modem list?
Quoted 76 lines
drivers/isimodem/sim.c +76
-0+struct file_info { + int fileid; + int length; + int structure; + int record_length; + uint8_t access[3]; + uint8_t file_status; +}; + +static struct file_info const static_file_info[] = { + { + SIM_EFSPN_FILEID, 17, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 0, { 0x0e, 0xff, 0xee } + }, + { + SIM_EF_ICCID_FILEID, 10, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 10, { 0x0f, 0xff, 0xee } + }, + { + SIM_EFPL_FILEID, 1, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 1, { 0x0f, 0xff, 0xff } + }, /* not found */ + { + SIM_EFLI_FILEID, 1, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 1, { 0x0f, 0xff, 0xff } + }, /* not found */ + { + SIM_EFMSISDN_FILEID, 28, OFONO_SIM_FILE_STRUCTURE_FIXED, + 28, { 0x01, 0xff, 0xee } + }, + { + SIM_EFAD_FILEID, 20, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 20, { 0x0e, 0xff, 0xee } + }, + { + SIM_EFPHASE_FILEID, 1, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 1, { 0x0e, 0xff, 0xee } + }, + { + SIM_EFPNN_FILEID, 4 * 18, OFONO_SIM_FILE_STRUCTURE_FIXED, + 18, { 0x0e, 0xff, 0xee } + }, /* 4 records, name 16 bytes */ + { + SIM_EFOPL_FILEID, 4 * 24, OFONO_SIM_FILE_STRUCTURE_FIXED, + 24, { 0x0e, 0xff, 0xee } + }, /* 4 records, name 16 bytes */ + { + SIM_EFMBI_FILEID, 5, OFONO_SIM_FILE_STRUCTURE_FIXED, + 5, { 0x0e, 0xff, 0xee } + }, + { + SIM_EFMWIS_FILEID, 6, OFONO_SIM_FILE_STRUCTURE_FIXED, + 6, { 0x01, 0xff, 0xee } + }, + { + SIM_EFSPDI_FILEID, 64, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 64, { 0x0e, 0xff, 0xee } + }, + { + SIM_EFECC_FILEID, 5 * 3, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 3, { 0x0e, 0xff, 0xee } + }, /* Can be also FIXED in 3G */ + { + SIM_EFCBMIR_FILEID, 8 * 4, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 4, { 0x01, 0xff, 0xee } + }, /* 8 records */ + { + SIM_EFCBMI_FILEID, 8 * 2, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 2, { 0x01, 0xff, 0xee } + }, /* 8 records */ + { + SIM_EFCBMID_FILEID, 8 * 2, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 2, { 0x01, 0xff, 0x11 } + }, /* 8 records */ + { + SIM_EFSMSP_FILEID, 56, OFONO_SIM_FILE_STRUCTURE_FIXED,
drivers/isimodem/sim.c line 246
Quoted 10 lines
drivers/isimodem/sim.c +8
-0+ 56, { 0x01, 0xff, 0xee } + }, + { + SIM_EFIMSI_FILEID, 9, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + 9, { 0x0e, 0xff, 0xee } + }, }; +static uint8_t get_sfi (const int fileid); +
This doesn't need forward declaration. Just put the implementation here. However, I would rename this to something like fileid_to_short_fileid()
Quoted 23 lines
drivers/isimodem/sim.c +8
-8struct sim_imsi { uint8_t length; uint8_t imsi[8];@@ -66,14 +259,283 @@ struct sim_spn { uint8_t disp_roam; }; -struct file_info { - int fileid; - int length; - int structure; - int record_length; - uint8_t access[3]; - uint8_t file_status; -}; +static void handle_app_uicc_usim (GIsiSubBlockIter *iter, + struct sim_data *sd, + uint16_t *length, + uint16_t *record_length, + uint8_t *records, + uint8_t *structure); + +static void uicc_pin_prompt(struct ofono_sim *sim,
drivers/isimodem/sim.c struct sim_spn { · line 279
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+ enum ofono_sim_password_type passwd_type, + ofono_sim_passwd_cb_t cb, + void *data, + uint8_t service); + +static void uicc_application_activate_req (GIsiClient *client, + void *opaque, + unsigned char appl_type, + unsigned char aid); +
Forward declarations should be avoided if at all possible.
drivers/isimodem/sim.c struct sim_spn { · line 288
Quoted 9 lines
drivers/isimodem/sim.c +9
-0+static int sim_applications_get_next_index (struct sim_applications *sa, + int current_app) +{ + if (current_app < (MAX_SIM_APPS - 1)) { + int i; + + for (i = ++current_app; i < MAX_SIM_APPS; i++) { + if (sa->app_list[i] && + (sa->app_type[i] != UICC_APPL_TYPE_UNKNOWN))
Empty line before the if, and if the statement spans multiple lines, every new line needs an extra indentation.
drivers/isimodem/sim.c struct sim_spn { · line 294
Quoted 6 lines
drivers/isimodem/sim.c +6
-0+ return i; + } + } + + return NOT_AVAILABLE; +}
I would refactor this function to return early, if the current_app is out of range, and not the other way around.
Quoted 233 lines
drivers/isimodem/sim.c +233
-0+static uint8_t get_pin_id (struct sim_data *sd, + uint8_t passwd_type, + int8_t *index) +{ + const uint16_t MAX_INDEX = (sizeof(pin_ids)/sizeof( + struct sim_passwd_to_pin_id)); + uint8_t i, pin_id; + *index = -1; + + for (i = 0; i < MAX_INDEX; i++) { + if (pin_ids[i].passwd_type == passwd_type) + *index = i; + } + + switch (passwd_type) { + case OFONO_SIM_PASSWORD_SIM_PIN: + case OFONO_SIM_PASSWORD_SIM_PUK: + return sd->pin1_id; + case OFONO_SIM_PASSWORD_SIM_PIN2: + case OFONO_SIM_PASSWORD_SIM_PUK2: + return sd->pin2_id; + default: + + if (*index == -1) + pin_id = 0; + else + pin_id = pin_ids[*index].pin_id; + + return pin_id; + } +} + +static void update_locked_pin (struct ofono_sim_local *local_sim, + uint8_t lock_type, uint8_t pinID) +{ + struct sim_data *sd = ofono_sim_get_data((struct ofono_sim *)local_sim); + + switch (lock_type) { + case UICC_PIN_VERIFY_NEEDED: + + if (pinID <= sd->pin1_id) { + local_sim->pin_type = + OFONO_SIM_PASSWORD_SIM_PIN; + local_sim->locked_pins[ + OFONO_SIM_PASSWORD_SIM_PIN] = TRUE; + sd->passwd_required = TRUE; + } else if (pinID == sd->pin2_id) { + local_sim->pin_type = + OFONO_SIM_PASSWORD_SIM_PIN2; + local_sim->locked_pins[ + OFONO_SIM_PASSWORD_SIM_PIN2] = TRUE; + sd->passwd_required = TRUE; + } else if (pinID == upin_id) { + local_sim->pin_type = + OFONO_SIM_PASSWORD_PHNET_PIN; + local_sim->locked_pins[ + OFONO_SIM_PASSWORD_PHNET_PIN] = TRUE; + sd->passwd_required = TRUE; + } + + break; + case UICC_PIN_UNBLOCK_NEEDED: + + if (pinID == sd->pin1_id) { + local_sim->pin_type = + OFONO_SIM_PASSWORD_SIM_PUK; + local_sim->locked_pins[ + OFONO_SIM_PASSWORD_SIM_PUK] = TRUE; + sd->passwd_required = TRUE; + } else if (pinID == sd->pin2_id) { + local_sim->pin_type = + OFONO_SIM_PASSWORD_SIM_PUK2; + local_sim->locked_pins[ + OFONO_SIM_PASSWORD_SIM_PUK2] = TRUE; + sd->passwd_required = TRUE; + } else if (pinID == upin_id) { + local_sim->pin_type = + OFONO_SIM_PASSWORD_PHNET_PUK; + local_sim->locked_pins[ + OFONO_SIM_PASSWORD_PHNET_PUK] = TRUE; + sd->passwd_required = TRUE; + } + + break; + default: + break; + } +} + +static gboolean get_fileid_path (struct ofono_sim *sim, + int *mf_path, + int *df1_path, + int *df2_path, + unsigned char *df_len, + int fileid) +{ + struct sim_data *sd = ofono_sim_get_data(sim); + + switch (fileid) { + case SIM_EFPL_FILEID: + case SIM_EF_ICCID_FILEID: + *mf_path = SIM_MF_FILEID; + *df1_path = 0x0000; + *df2_path = 0x0000; + *df_len = 2; + break; + case SIM_EFSMSP_FILEID: + case SIM_EFSDN_FILEID: + case SIM_EFMSISDN_FILEID: + *mf_path = SIM_MF_FILEID; + + if (UICC_APPL_TYPE_ICC_SIM == sd->app_type) + *df1_path = SIM_DFTELECOM_FILEID; + else + *df1_path = ADF_USIM; + + *df2_path = 0x0000; + *df_len = 4; + break; + case SIM_EFLI_FILEID: + case SIM_EFSPN_FILEID: + case SIM_EFAD_FILEID: + case SIM_EFPNN_FILEID: + case SIM_EFOPL_FILEID: + case SIM_EFMBDN_FILEID: + case SIM_EFMBI_FILEID: + case SIM_EFMWIS_FILEID: + case SIM_EFSPDI_FILEID: + case SIM_EFECC_FILEID: + case SIM_EFCBMI_FILEID: + case SIM_EFCBMIR_FILEID: + case SIM_EFCBMID_FILEID: + case SIM_EFIMSI_FILEID: + case SIM_EFPHASE_FILEID: /* 3GPP TS 11.11 */ + case SIM_EFARR_FILEID: + case SIM_EF_CPHS_INFORMATION_FILEID: + *mf_path = SIM_MF_FILEID; + + if (UICC_APPL_TYPE_ICC_SIM == sd->app_type) + *df1_path = SIM_DFGSM_FILEID; + else + *df1_path = ADF_USIM; + + *df2_path = 0x0000; + *df_len = 4; + break; + /* No info */ + case SIM_EF_CPHS_MBDN_FILEID: + case SIM_EF_CPHS_MWIS_FILEID: + DBG("======== No path info for %04X", fileid); + return FALSE; + case SIM_EFADN_FILEID: /* Only for SIM */ + case SIM_EFEXT1_FILEID: /* Only for SIM */ + *mf_path = SIM_MF_FILEID; + *df1_path = SIM_DFTELECOM_FILEID; + *df2_path = 0x0000; + *df_len = 4; + break; + default: + *mf_path = SIM_MF_FILEID; + *df1_path = SIM_DFTELECOM_FILEID; + *df2_path = SIM_DFPHONEBOOK_FILEID; + *df_len = 6; + break; + } + + return TRUE; +} + +static uint8_t get_sfi (const int fileid) +{ + uint8_t ret; + + /* SFI list from 3GPP TS 31.102 Annex H */ + switch (fileid) { + case SIM_EFECC_FILEID: + ret = 01; + break; + case SIM_EFLI_FILEID: + ret = 02; + break; + case SIM_EFAD_FILEID: + ret = 03; + break; + case SIM_EFIMSI_FILEID: + ret = 07; + break; + case SIM_EFCBMID_FILEID: + ret = 0x0E; + break; + case SIM_EFPNN_FILEID: + ret = 0x19; + break; + case SIM_EFOPL_FILEID: + ret = 0x1A; + break; + default: + ret = UICC_SFI_NOT_PRESENT; + break; + } + + return ret; +} + +int get_app_id (void ) +{ + if (uicc_sim) { + struct sim_data *sd = ofono_sim_get_data(uicc_sim); + DBG("app_id %d", sd->app_id); + return sd->app_id; + } else + return -1; +} + +int get_app_type (void ) +{ + if (uicc_sim) { + struct sim_data *sd = ofono_sim_get_data(uicc_sim); + DBG("app_type %d", sd->app_type); + return sd->app_type; + } else + return -1; +} + +int get_client_id (void ) +{ + if (uicc_sim) { + struct sim_data *sd = ofono_sim_get_data(uicc_sim); + DBG("client_id %d", sd->client_id); + return sd->client_id; + } else + return -1; +}
drivers/isimodem/sim.c struct sim_spn { · line 538
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+ +GIsiClient *read_pn_uicc_client (void ) +{ + return pn_uicc_client; +} + +struct ofono_sim *get_sim (void ) +{ + return uicc_sim; +}
How is this API supposed to be used (presumably) by other drivers?
At a minimum, you should keep track of all of the modem references, and have the other drivers give you their modem reference as a lookup key.
Quoted 33 lines
drivers/isimodem/sim.c +0
-23/* Returns file info */ static gboolean fake_file_info(gpointer user)@@ -89,29 +551,6 @@ static gboolean fake_file_info(gpointer user) return FALSE; } -static void isi_read_file_info (struct ofono_sim *sim,int fileid, - ofono_sim_file_info_cb_t cb, void *data) -{ - int i; - static struct file_info const info[] = { - { SIM_EFSPN_FILEID, 17, 0, 0, { 0x0f, 0xff, 0xff }, 1 }, - { SIM_EF_ICCID_FILEID, 10, 0, 0, { 0x0f, 0xff, 0xff }, 1 }, - }; - int N = sizeof(info) / sizeof(info[0]); - struct isi_cb_data *cbd; - - for (i = 0; i < N; i++) { - if (fileid == info[i].fileid) { - cbd = isi_cb_data_new((void *) &info[i], cb, data); - g_idle_add(fake_file_info, cbd); - return; - } - } - - DBG("Fileid %04X not implemented", fileid); - CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL, 0, data); -} - static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid, uint8_t service) {
drivers/isimodem/sim.c static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid, · line 574
Quoted 8 lines
drivers/isimodem/sim.c +4
-1@@ -129,7 +568,10 @@ static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid, return FALSE; } - if (!g_isi_msg_data_get_byte(msg, 1, &cause) || cause != SIM_SERV_OK) { + if ((!g_isi_msg_data_get_byte(msg, 1, &cause) || + cause != SIM_SERV_OK) && + (!g_isi_msg_data_get_byte(msg, 2, &cause) || + cause != UICC_STATUS_OK)) {
PN_UICC has two different causes?
Quoted 19 lines
drivers/isimodem/sim.c +12
-0DBG("Request failed: %s", sim_isi_cause_name(cause)); return FALSE; }@@ -141,6 +583,303 @@ static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid, return TRUE; } +static void handle_app_uicc_usim (GIsiSubBlockIter *iter, + struct sim_data *sd, + uint16_t *length, + uint16_t *record_length, + uint8_t *records, uint8_t *structure) +{ + uint8_t fcp; + uint8_t fcp_len; + uint8_t read = 0; + uint8_t id; + uint8_t item_len; + uint16_t file_id;
drivers/isimodem/sim.c static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid, · line 607
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+ uint8_t desc; + uint8_t coding; + uint8_t pin_do_len; + uint8_t pin_len; + uint8_t pin_tag; + uint8_t pin_id; + uint8_t pin_tag_pos; + + + (void)g_isi_sb_iter_get_byte(iter, &fcp, 8);
That cast is not necessary, but you should really check the return value.
drivers/isimodem/sim.c static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid, · line 608
Quoted 1 line
drivers/isimodem/sim.c +1
-0+ if (fcp == FCP_TEMPLATE) {
Reduces indentation a lot, if you check that fcp != FCP_TEMPLATE, and goto some 'out' label.
Quoted 1,019 lines
drivers/isimodem/sim.c +671
-23+ (void) g_isi_sb_iter_get_byte(iter, &fcp_len, 9); + while (read < fcp_len) { + (void) g_isi_sb_iter_get_byte(iter, &id, read + 10); + (void) g_isi_sb_iter_get_byte(iter, &item_len, + read + 11); + + switch (id) { + case FCP_FILE_SIZE: + if (item_len == 2) { + g_isi_sb_iter_get_word(iter, length, + read + 10 + 2); + } + break; + case FCP_FILE_ID: + + if (item_len == 2) { + g_isi_sb_iter_get_word(iter, &file_id, + read + 10 + 2); + } + break; + case FCP_FILE_DESC: + if (item_len >= 2) { + g_isi_sb_iter_get_byte(iter, &desc, + read + 10 + 2); + g_isi_sb_iter_get_byte(iter, &coding, + read + 10 + 3); + } + + if (item_len >= 4) { + g_isi_sb_iter_get_word(iter, + record_length, + read + 10 + 4); + g_isi_sb_iter_get_byte(iter, records, + read + 10 + 6); + } + break; + case FCP_PIN_STATUS: + g_isi_sb_iter_get_byte(iter, &pin_do_len, + read + 10 + 3); + pin_tag_pos = read + 10 + 4 + pin_do_len; + g_isi_sb_iter_get_byte(iter, &pin_tag, + pin_tag_pos); + + while (pin_tag == 0x83) { + + g_isi_sb_iter_get_byte(iter, &pin_len, + pin_tag_pos + 1); + g_isi_sb_iter_get_byte(iter, &pin_id, + pin_tag_pos + 2); + + pin_tag_pos += 2 + pin_len; + g_isi_sb_iter_get_byte(iter, &pin_tag, + pin_tag_pos); + + if ((0x01 <= pin_id) && + (pin_id <= 0x08)) + sd->pin1_id = pin_id; + else if ((0x81 <= pin_id) && + (pin_id <= 0x88)) + sd->pin2_id = pin_id; + read += item_len + 2; + } + break; + case FCP_FILE_SECURITY_ARR: + case FCP_FILE_SECURITY_COMPACT: + case FCP_FILE_SECURITY_EXPANDED: + + /* Not implemented, using + * static access rules as these + * are used only for caching + * See ETSI TS 102 221, ch + * 11.1.1.4.7 and + * Annexes E,F and G + */ + case FCP_FILE_LIFECYCLE: + default: + DBG("FCP id %02X not supported", id); + break; + } + + /*Data length + id size + len size */ + read += item_len + 2; + } + } + if ((desc & 7) == 1) + *structure = OFONO_SIM_FILE_STRUCTURE_TRANSPARENT; + else if ((desc & 7) == 2) + *structure = OFONO_SIM_FILE_STRUCTURE_FIXED; + else if ((desc & 7) == 6) + *structure = OFONO_SIM_FILE_STRUCTURE_CYCLIC; +} + +static void isi_file_info_resp (const GIsiMessage *msg,void *data) +{ + struct isi_cb_data *cbd = data; + ofono_sim_file_info_cb_t cb = cbd->cb; + uint16_t length = 0; + uint16_t record_length = 0; + uint8_t structure = -1; + uint8_t records = 0; + uint16_t file_id = 0; + uint8_t access[3] = {0, 0, 0}; + uint8_t item_len = 0; + gboolean everything_ok = FALSE; + /*Access is read from static file info*/ + struct file_info const *info = cbd->user; + GIsiSubBlockIter iter; + struct sim_data *sd = ofono_sim_get_data(uicc_sim); + uint8_t sbcount = 0; + + if (!check_response_status(msg, UICC_APPL_CMD_RESP, + UICC_APPL_FILE_INFO)) + goto error; + + if (info != NULL) { + access[0] = info->access[0]; + access[1] = info->access[1]; + access[2] = info->access[2]; + } + g_isi_msg_data_get_byte(msg, 5, &sbcount); + g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount); + + while (g_isi_sb_iter_is_valid(&iter)) { + DBG("Sub-block %s", + uicc_subblock_name(g_isi_sb_iter_get_id(&iter))); + + switch (g_isi_sb_iter_get_id(&iter)) { + case UICC_SB_FCI: + DBG("UICC_SB_FCI"); + everything_ok = TRUE; + + switch (sd->app_type) { + case UICC_APPL_TYPE_UICC_USIM: + DBG("UICC_APPL_TYPE_UICC_USIM"); + handle_app_uicc_usim(&iter, sd, + &length, &record_length, + &records, &structure); + + break; + case UICC_APPL_TYPE_ICC_SIM: + DBG("UICC_APPL_TYPE_ICC_SIM"); + g_isi_sb_iter_get_word(&iter, &length, 10); + g_isi_sb_iter_get_word(&iter, &file_id, 12); + (void)g_isi_sb_iter_get_byte(&iter, + &access[0], + 16); + (void)g_isi_sb_iter_get_byte(&iter, + &access[0], + 17); + (void)g_isi_sb_iter_get_byte(&iter, + &access[0], + 18); + (void)g_isi_sb_iter_get_byte(&iter, + &item_len, 20); + (void)g_isi_sb_iter_get_byte(&iter, + &structure, + 21); + + if (item_len == 2) + (void)g_isi_sb_iter_get_byte(&iter, + (uint8_t *)&record_length, + 22); + + break; + default: + DBG("UICC application type %d not supported", + sd->app_type); + break; + } + + break; + default: + DBG("Skipping SB"); + break; + } + + if (g_isi_sb_iter_next(&iter) == FALSE) + goto error; + } + + if (everything_ok) { + CALLBACK_WITH_SUCCESS(cb, length, structure, record_length, + access, '\n', cbd->data); + return; + } + +error: + DBG("Error reading file info"); + CALLBACK_WITH_FAILURE(cb, 0, 0, 0, access, '\n', cbd->data); +} + +static void isi_read_file_info (struct ofono_sim *sim,int fileid, + ofono_sim_file_info_cb_t cb, void *data) +{ + int i; + static struct file_info const info[] = { + { SIM_EFSPN_FILEID, 17, 0, 0, { 0x0f, 0xff, 0xff }, 1 }, + { SIM_EF_ICCID_FILEID, 10, 0, 0, { 0x0f, 0xff, 0xff }, 1 }, + }; + int N = sizeof(info) / sizeof(info[0]); + struct sim_data *sd = ofono_sim_get_data(sim); + struct isi_cb_data *cbd; + + if ((sd != NULL) && g_isi_client_resource(sd->client) == PN_UICC) { + /* Prepare for static file info used for access rights */ + int i; + int mf_path = 0; + int df1_path = 0; + int df2_path = 0; + unsigned char df_len = 0; + + N = sizeof(static_file_info) / sizeof(static_file_info[0]); + cbd = isi_cb_data_new(NULL, cb, data); + DBG("File info for ID=%04X app id %d", fileid, sd->app_id); + + for (i = 0; i < N; i++) { + if (fileid == static_file_info[i].fileid && + cbd != NULL) { + cbd->user = (void *) &static_file_info[i]; + continue; + } + } + if (!get_fileid_path(sim, &mf_path, &df1_path, + &df2_path, &df_len, fileid)) { + g_free(cbd); + goto error; + } + if (cbd) { + const unsigned char msg[] = { + UICC_APPL_CMD_REQ, + UICC_APPL_FILE_INFO, + sd->app_id, + UICC_SESSION_ID_NOT_USED, /*Session ID*/ + 0, /*Filler*/ + 0, /*Filler*/ + 1, /*number of subblocks*/ + /* Subblock 1*/ + UICC_SB_APPL_PATH >> 8, + UICC_SB_APPL_PATH & 0xff, + 0, + 16, /*Sub block length*/ + fileid >> 8, /* UICC elementary file ID*/ + fileid & 0xFF, + get_sfi(fileid), /* Elementary file short id*/ + 0, /*filler*/ + df_len, /*DF Path length*/ + 0, /*Filler*/ + mf_path >> 8, + mf_path & 0xff, + df1_path >> 8, /*DF Path*/ + df1_path & 0xFF, + df2_path >> 8, /*DF Path*/ + df2_path & 0xFF, + }; + g_isi_client_send(sd->client, msg, sizeof(msg), + isi_file_info_resp, cbd, g_free); + return; + } + } else { + for (i = 0; i < N; i++) { + if (fileid == info[i].fileid) { + cbd = isi_cb_data_new((void *) &info[i], cb, + data); + g_idle_add(fake_file_info, cbd); + return; + } + } + + } +error: + DBG("Fileid %04X not implemented", fileid); + CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL, 0, data); +} + static void spn_resp_cb(const GIsiMessage *msg, void *data) { struct isi_cb_data *cbd = data;@@ -234,32 +973,142 @@ static gboolean isi_read_iccid(struct ofono_sim *sim, struct isi_cb_data *cbd) read_iccid_resp_cb, cbd, g_free); } +static void isi_read_file_transparent_resp (const GIsiMessage *msg,void *data) +{ + struct isi_cb_data *cbd = data; + ofono_sim_read_cb_t cb = cbd->cb; + uint32_t filelen = 0; + unsigned char filedata[256] = { 0xff }; + gboolean everything_ok = FALSE; + GIsiSubBlockIter iter; + uint8_t sbcount = 0; + + if (!check_response_status(msg, UICC_APPL_CMD_RESP, + UICC_APPL_READ_TRANSPARENT)) + goto error; + + g_isi_msg_data_get_byte(msg, 5, &sbcount); + g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount); + + while (g_isi_sb_iter_is_valid(&iter)) { + DBG("Sub-block %s", + uicc_subblock_name(g_isi_sb_iter_get_id(&iter))); + + switch (g_isi_sb_iter_get_id(&iter)) { + case UICC_SB_FILE_DATA: + g_isi_sb_iter_get_dword(&iter, &filelen, 4); + memmove(&filedata, iter.start + 8, filelen); + everything_ok = TRUE; + break; + default: + break; + } + + g_isi_sb_iter_next(&iter); + } + + if (everything_ok) { + DBG("Transparent EF read: 1st byte %02x, len %d", + filedata[0], filelen); + CALLBACK_WITH_SUCCESS(cb, filedata, filelen, cbd->data); + return; + } + +error: + DBG("Error reading transparent EF"); + CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data); +} + static void isi_read_file_transparent(struct ofono_sim *sim, int fileid, int start, int length, ofono_sim_read_cb_t cb, void *data) { + struct sim_data *sd = ofono_sim_get_data(sim); struct isi_cb_data *cbd; gboolean done; cbd = isi_cb_data_new(sim, cb, data); - if (cbd == NULL) + + if (cbd == NULL || sd == NULL) goto error; - switch (fileid) { - case SIM_EFSPN_FILEID: - done = isi_read_spn(sim, cbd); - break; + if (g_isi_client_resource(sd->client) == PN_UICC) { + int mf_path = 0; + int df1_path = 0; + int df2_path = 0; + unsigned char df_len = 0; + + DBG("File ID=%04X, client %d, AID %d", + fileid, sd->client_id, sd->app_id); + + if (get_fileid_path(sim, &mf_path, &df1_path, + &df2_path, &df_len, fileid)) { + const unsigned char msg[] = { + UICC_APPL_CMD_REQ, + UICC_APPL_READ_TRANSPARENT, + sd->app_id, + UICC_SESSION_ID_NOT_USED, /*Session ID*/ + 0, /*Filler*/ + 0, /*Filler*/ + 3, /*number of subblocks*/ + /* Subblock 1 */ + UICC_SB_CLIENT >> 8, + UICC_SB_CLIENT & 0xff, + 0, + 8, /*Sub block length*/ + 0, 0, 0, /* Filler */ + sd->client_id, + /* Subblock 2*/ + UICC_SB_TRANSPARENT >> 8, + UICC_SB_TRANSPARENT & 0xff, + 0, /*Sub block length*/ + 8, /*Sub block length*/ + 0, /*File offset (0=beginning)*/ + 0, /*File offset (0=beginning)*/ + 0, /*Data amount (0=all)*/ + 0, /*Data amount (0=all)*/ + /* Subblock 3 */ + UICC_SB_APPL_PATH >> 8, + UICC_SB_APPL_PATH & 0xff, + 0, + 16, /* Sub block length*/ + fileid >> 8, /* UICC elementary file ID*/ + fileid & 0xFF, + get_sfi(fileid),/*Elementary file short id*/ + 0, /*filler*/ + df_len, /*DF Path length*/ + 0, /*Filler*/ + mf_path >> 8, + mf_path & 0xff, + df1_path >> 8, /*DF Path*/ + df1_path & 0xFF, + df2_path >> 8, /*DF Path*/ + df2_path & 0xFF + }; + g_isi_client_send_with_timeout( + sd->client, msg, sizeof(msg), SIM_TIMEOUT, + isi_read_file_transparent_resp, cbd, g_free); + return; + } + goto error; - case SIM_EF_ICCID_FILEID: - done = isi_read_iccid(sim, cbd); - break; + } else { + switch (fileid) { + case SIM_EFSPN_FILEID: + done = isi_read_spn(sim, cbd); + break; - default: - done = FALSE; - } + case SIM_EF_ICCID_FILEID: + done = isi_read_iccid(sim, cbd); + break; - if (done) - return; + default: + done = FALSE; + } + + if (done) + return; + } DBG("Fileid %04X not implemented", fileid);@@ -268,12 +1117,125 @@ error: g_free(cbd); } -static void isi_read_file_linear (struct ofono_sim *sim,int fileid, - int record, int length, - ofono_sim_read_cb_t cb, void *data) +static void isi_read_file_linear_fixed_resp (const GIsiMessage *msg,void *data) { - DBG("Fileid %04X not implemented", fileid); + struct isi_cb_data *cbd = data; + ofono_sim_read_cb_t cb = cbd->cb; + uint32_t filelen = 0; + unsigned char filedata[256] = { 0xff }; + gboolean everything_ok = FALSE; + GIsiSubBlockIter iter; + uint8_t sbcount = 0; + + if (!check_response_status(msg, UICC_APPL_CMD_RESP, + UICC_APPL_READ_LINEAR_FIXED)) + goto error; + + everything_ok = FALSE; + g_isi_msg_data_get_byte(msg, 5, &sbcount); + g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount); + + while (g_isi_sb_iter_is_valid(&iter)) { + DBG("Sub-block %s", + uicc_subblock_name(g_isi_sb_iter_get_id(&iter))); + + switch (g_isi_sb_iter_get_id(&iter)) { + case UICC_SB_FILE_DATA: + g_isi_sb_iter_get_dword(&iter, &filelen, 4); + memmove(&filedata, iter.start + 8, filelen); + everything_ok = TRUE; + break; + default: + break; + } + + g_isi_sb_iter_next(&iter); + } + + if (everything_ok) { + DBG("Linear fixed EF read: 1st byte %02x, len %d", + filedata[0], filelen); + CALLBACK_WITH_SUCCESS(cb, filedata, filelen, cbd->data); + return; + } + +error: + DBG("Error reading linear fixed EF"); + CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data); +} + +static void isi_read_file_linear (struct ofono_sim *sim, + int fileid, + int record, + int rec_length, + ofono_sim_read_cb_t cb, + void *data) +{ + struct sim_data *sd = ofono_sim_get_data(sim); + struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data); + int mf_path = 0; + int df1_path = 0; + int df2_path = 0; + unsigned char df_len = 0; + DBG("File ID=%04X, record %d, client %d AID %d", + fileid, record, sd->client_id, sd->app_id); + if (!get_fileid_path(sim, &mf_path, + &df1_path, &df2_path, &df_len, fileid)) + goto error; + if ((cbd != NULL) && (sd != NULL)) { + + const unsigned char msg[] = { + UICC_APPL_CMD_REQ, + UICC_APPL_READ_LINEAR_FIXED, + sd->app_id, + UICC_SESSION_ID_NOT_USED, /*Session ID*/ + 0, /*Filler*/ + 0, /*Filler*/ + 3, /*number of subblocks*/ + /* Subblock 1*/ + UICC_SB_CLIENT >> 8, + UICC_SB_CLIENT & 0xff, + 0, + 8, /*Sub block length */ + 0, 0, 0, /* Filler */ + sd->client_id, + /* Subblock 2 */ + UICC_SB_LINEAR_FIXED >> 8, + UICC_SB_LINEAR_FIXED & 0xff, + 0, /*Sub block length*/ + 8, /*Sub block length*/ + record, /*Record*/ + 0, /*Record offset (0=beginning)*/ + rec_length & 0xff, /*Data amount (0=all)*/ + 0, /*Filler*/ + /* Subblock 3*/ + UICC_SB_APPL_PATH >> 8, + UICC_SB_APPL_PATH & 0xff, + 0, + 16, /*Sub block length*/ + fileid >> 8, /* UICC elementary file ID*/ + fileid & 0xFF, + get_sfi(fileid), /* Elementary file short file id*/ + 0, /*filler*/ + df_len, /*DF Path length*/ + 0, /*Filler*/ + mf_path >> 8, + mf_path & 0xff, + df1_path >> 8, /*DF Path*/ + df1_path & 0xFF, + df2_path >> 8, /*DF Path*/ + df2_path & 0xFF + }; + g_isi_client_send_with_timeout( + sd->client, msg, sizeof(msg), SIM_TIMEOUT, + isi_read_file_linear_fixed_resp, cbd, g_free); + return; + } + +error: + DBG("Not implemented (fileid = %04x)", fileid); CALLBACK_WITH_FAILURE(cb, NULL, 0, data); + g_free(cbd); } static void isi_read_file_cyclic(struct ofono_sim *sim, int fileid,@@ -293,13 +1255,123 @@ static void isi_write_file_transparent(struct ofono_sim *sim, int fileid, CALLBACK_WITH_FAILURE(cb, data); } +static void write_file_linear_cb (const GIsiMessage *msg,void *data) +{ + struct isi_cb_data *cbd = data; + ofono_sim_write_cb_t cb = cbd->cb; + DBG(""); + + if (check_response_status(msg, UICC_APPL_CMD_RESP, + UICC_APPL_UPDATE_LINEAR_FIXED)) + CALLBACK_WITH_SUCCESS(cb, cbd->data); + +} + static void isi_write_file_linear(struct ofono_sim *sim, int fileid, int record, int length, const unsigned char *value, ofono_sim_write_cb_t cb, void *data) { + struct sim_data *sd = ofono_sim_get_data(sim); + struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data); + + if (g_isi_client_resource(sd->client) == PN_UICC) { + int mf_path = 0; + int df1_path = 0; + int df2_path = 0; + unsigned char df_len = 0; + size_t i = 0; + size_t sb_file_data_legth = (2 + 2 + 4 + length + 3) & ~3; + size_t fill_count = sb_file_data_legth - (2 + 2 + 4 + length); + uint8_t *fill_data = g_try_malloc0(fill_count); + + DBG(""); + + if (!fill_data && fill_count > 0) { + g_free(fill_data); + goto error; + } + for (i = 0; i < fill_count; i++) + fill_data[i] = 0x00; + + if (!sd->app_id || !sd->client_id || !sd || !sd->client || + !cbd) { + DBG("Parameter error"); + g_free(fill_data); + goto error; + } + + if (get_fileid_path(sim, &mf_path, &df1_path, + &df2_path, &df_len, fileid)) { + uint8_t msg[] = { + UICC_APPL_CMD_REQ, + UICC_APPL_UPDATE_LINEAR_FIXED, + sd->app_id, + UICC_SESSION_ID_NOT_USED, + 0x00, 0x00, /* fillers */ + 0x04, /* nro of sub blocks */ + /* 1st subblock */ + UICC_SB_CLIENT >> 8, + UICC_SB_CLIENT & 0xFF, + 0x00, 0x08, /* subblock length */ + 0x00, 0x00, 0x00, /* fillers */ + sd->client_id, + /* 2nd subblock */ + UICC_SB_LINEAR_FIXED >> 8, + UICC_SB_LINEAR_FIXED & 0xFF, + 0x00, 0x08, /* subblock length */ + record, /* the record in the file*/ + 0x00, /* record offset (0 == beginning) */ + 0x00, /* data amount, used only for reading */ + 0x00, /* filler */ + /* 3th subblock */ + UICC_SB_APPL_PATH >> 8, + UICC_SB_APPL_PATH & 0xFF, + 0x00, 0x10, /* subblock length */ + fileid >> 8, /* elementary file id */ + fileid & 0xFF, + get_sfi(fileid), + 0x00, /* filler */ + df_len, /* path length */ + 0x00, /* filler */ + mf_path >> 8, /* DF Path MF */ + mf_path & 0xFF, + df1_path >> 8, /* DF Path */ + df1_path & 0xFF, + df2_path >> 8, /* DF Path */ + df2_path & 0xFF, + /* 4nd subblock */ + UICC_SB_FILE_DATA >> 8, + UICC_SB_FILE_DATA & 0xFF, + sb_file_data_legth >> 8, /* subblock length */ + sb_file_data_legth & 0xFF, + length >> 24, /* data length */ + length >> 16, /* need to be shifted */ + length >> 8, + length & 0xFF, + }; + + struct iovec iov[3] = { + { msg, sizeof(msg) }, + { (uint8_t *)value, length }, + { fill_data, fill_count }, + }; + + if (!g_isi_client_vsend_with_timeout(sd->client, iov, + 3, SIM_TIMEOUT, write_file_linear_cb, + cbd, g_free)) { + g_free(fill_data); + goto error; + } + + g_free(fill_data); + return; + } + } DBG("Fileid %04X not implemented", fileid); +error: CALLBACK_WITH_FAILURE(cb, data); + g_free(cbd); } static void isi_write_file_cyclic(struct ofono_sim *sim, int fileid,@@ -309,10 +1381,53 @@ static void isi_write_file_cyclic(struct ofono_sim *sim, int fileid, DBG("Fileid %04X not implemented", fileid); CALLBACK_WITH_FAILURE(cb, data); } - -static void imsi_resp_cb (const GIsiMessage *msg,void *data) +static void uicc_read_imsi_resp (const struct ofono_error *error, + const unsigned char *data, + int len, + void *user) { - struct isi_cb_data *cbd = data; + struct isi_cb_data *cbd = user; + ofono_sim_imsi_cb_t cb = cbd->cb; + /* For coding see TS 24.008 */ + char imsi[SIM_MAX_IMSI_LENGTH + 1]; + int i = 1; /*Skip length, the 1st byte*/ + int j = 0; + int octets; + + if (data == NULL) + goto error; + + octets = data[0]; + + if (octets != 8 || octets > len) + goto error; + + /* Ignore the low-order semi-octet of the first byte */ + imsi[j] = ((data[i] & 0xF0) >> 4) + '0'; + + for (i++, j++; i - 1 < octets && j < SIM_MAX_IMSI_LENGTH; i++) { + char nibble; + imsi[j++] = (data[i] & 0x0F) + '0'; + nibble = (data[i] & 0xF0) >> 4; + + if (nibble != 0x0F) + imsi[j++] = nibble + '0'; + } + + imsi[j] = '\0'; + DBG("IMSI %s", imsi); + CALLBACK_WITH_SUCCESS(cb, imsi, cbd->data); + goto out; +error: + CALLBACK_WITH_FAILURE(cb, NULL, cbd->data); +out: + g_free(cbd); + return; +} + +static void imsi_resp_cb (const GIsiMessage *msg,void *data) +{ + struct isi_cb_data *cbd = data; ofono_sim_imsi_cb_t cb = cbd->cb; struct sim_imsi *resp;@@ -321,9 +1436,6 @@ static void imsi_resp_cb(const GIsiMessage *msg, void *data) char imsi[SIM_MAX_IMSI_LENGTH + 1]; size_t i, j; - if (!check_response_status(msg, SIM_IMSI_RESP_READ_IMSI, READ_IMSI)) - goto error; - if (!g_isi_msg_data_get_struct(msg, 2, (const void **) &resp, len)) goto error;@@ -352,16 +1464,24 @@ static void isi_read_imsi(struct ofono_sim *sim, { struct sim_data *sd = ofono_sim_get_data(sim); struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data); + size_t len; const uint8_t msg[] = { SIM_IMSI_REQ_READ_IMSI,READ_IMSI
};
-size_tlen = sizeof(msg);if (cbd == NULL || sd == NULL)
goto error;+ if (
g_isi_client_resource(sd->client)==PN_UICC) {
+ isi_read_file_transparent(sim,SIM_EFIMSI_FILEID, 0, 9,
+uicc_read_imsi_resp, cbd);
+ return;
+ }
+ len = sizeof(msg);drivers/isimodem/sim.c +2
-0+ +if (
g_isi_client_send(sd->client, msg, len, imsi_resp_cb, cbd, g_free)) return;drivers/isimodem/sim.c +235
-0@@ -370,6 +1490,976 @@ error: g_free(cbd); } +static void uicc_application_activate_resp (const GIsiMessage *msg,void *data) +{ + struct ofono_sim *sim = data; + GIsiSubBlockIter iter; + uint8_t sbcount = 0; + struct sim_data *sd = ofono_sim_get_data(sim); + uint8_t *msg_data = (uint8_t *)g_isi_msg_data(msg); + + if (!check_response_status(msg, UICC_APPLICATION_RESP, + UICC_APPL_HOST_ACTIVATE)) + return; + + if ((msg_data[2] == UICC_STATUS_OK) || + (msg_data[2] == UICC_STATUS_APPL_ACTIVE)) { + if (!sd->uicc_app_started) { + sd->app_id = sd->trying_app_id; + sd->app_type = sd->trying_app_type; + sd->uicc_app_started = TRUE; + DBG("UICC application activated"); + ofono_sim_inserted_notify(sim, TRUE); + ofono_sim_register(sim); + g_free(sim_application_list_p); + } + } else { + int i = sim_applications_get_next_index( + sim_application_list_p, sd->trying_app_id); + + if (i == NOT_AVAILABLE) { + g_free(sim_application_list_p); + return; + } + + DBG("Activation Error, trying to activate APP with ID:%d", i); + uicc_application_activate_req(sd->client, sim, + sim_application_list_p->app_type[i], + sim_application_list_p->app_list[i]); + return; + } + + g_isi_msg_data_get_byte(msg, 5, &sbcount); + g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount); + + while (g_isi_sb_iter_is_valid(&iter)) { + DBG("Sub-block %s", + uicc_subblock_name(g_isi_sb_iter_get_id(&iter))); + + switch (g_isi_sb_iter_get_id(&iter)) { + case UICC_SB_CLIENT: { + guint8 client = 0; + g_isi_sb_iter_get_byte(&iter, &client, 7); + DBG("Client id %d", client); + sd->client_id = client; + break; + } + case UICC_SB_FCI: + DBG("UICC_SB_FCI"); + + if (sd->app_type == UICC_APPL_TYPE_UICC_USIM) { + uint16_t length, record_length; + uint8_t records, structure; + handle_app_uicc_usim(&iter, sd, &length, + &record_length, &records, + &structure); + } + + break; + case UICC_SB_CHV: + DBG("UICC_SB_CHV"); + + if (sd->app_type == UICC_APPL_TYPE_ICC_SIM) { + uint8_t chv_id = 0, pin_id = 0; + (void) g_isi_sb_iter_get_byte(&iter, + &chv_id, 4); + (void) g_isi_sb_iter_get_byte(&iter, + &pin_id, 5); + DBG("UICC_APPL_TYPE_UICC_SIM"); + + if (chv_id == 1) + sd->pin1_id = pin_id; + else if (chv_id == 2) + sd->pin2_id = pin_id; + } + + break; + default: + DBG("Skipping sub-block: %s (%zu bytes)", + uicc_subblock_name(g_isi_sb_iter_get_id(&iter)), + g_isi_sb_iter_get_len(&iter)); + break; + } + + (void)g_isi_sb_iter_next(&iter); + } +} + +static void uicc_application_activate_req (GIsiClient *client, + void *opaque, + unsigned char appl_type, + unsigned char aid) +{ + const unsigned char msg[] = { + UICC_APPLICATION_REQ, + UICC_APPL_HOST_ACTIVATE, + 2, /* number of subblocks*/ + /* Subblock 1 */ + UICC_SB_APPLICATION >> 8, + UICC_SB_APPLICATION & 0xff, + 0, /*subblock length*/ + 8, /*subblock length*/ + 0, /*filler*/ + 0, /*filler*/ + appl_type, + aid, + /* Subblock 2 */ + UICC_SB_APPL_INFO >> 8, + UICC_SB_APPL_INFO & 0xff, + 0, /*subblock length*/ + 8, /*subblock length*/ + 0, /*filler*/ + 0, /*filler*/ + 0, /*filler*/ + /* whether the application initialization procedure + * will follow the activation or not */ + UICC_APPL_START_UP_INIT_PROC + }; + + DBG("Appl type %d, AID %d", appl_type, aid); + + g_isi_client_send_with_timeout( + client, msg, sizeof(msg), SIM_TIMEOUT, + uicc_application_activate_resp, opaque, NULL); +} + +static void uicc_application_list_resp (const GIsiMessage *msg,void *data) +{ + struct ofono_sim *sim = data; + gboolean everything_ok = TRUE; + int index = NOT_AVAILABLE; + struct sim_data *sd = ofono_sim_get_data(sim); + + if (!check_response_status(msg, UICC_APPLICATION_RESP, + UICC_APPL_LIST)) { + uint8_t status = 0; + + g_isi_msg_data_get_byte(msg, 2, &status); + if (status != UICC_STATUS_FAIL) + return; + everything_ok = FALSE; + } + + sim_application_list_p = g_try_new0(struct sim_applications, 1); + + if (everything_ok) { + GIsiSubBlockIter iter; + uint8_t sbcount = 0; + g_isi_msg_data_get_byte(msg, 5, &sbcount); + g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount); + + while (g_isi_sb_iter_is_valid(&iter)) { + DBG("Sub-block %s", + uicc_subblock_name( + g_isi_sb_iter_get_id(&iter))); + + switch (g_isi_sb_iter_get_id(&iter)) { + case UICC_SB_APPL_DATA_OBJECT: { + guint8 appl_id = -1; + guint8 appl_type = -1; + guint8 status = -1; + gboolean ret; + ret = g_isi_sb_iter_get_byte( + &iter, &appl_type, 6); + ret = g_isi_sb_iter_get_byte( + &iter, &appl_id, 7); + (void) g_isi_sb_iter_get_byte( + &iter, &status, 8); + DBG("Appl type=%d, Appl id=%d, Appl status=%d", + appl_type, appl_id, status); + + sim_application_list_p->app_list[appl_id] = + appl_id; + sim_application_list_p->app_type[appl_id] = + appl_type; + break; + } + default: + DBG("Skipping sub-block: %s (%zu bytes)", + uicc_subblock_name( + g_isi_sb_iter_get_id(&iter)), + g_isi_sb_iter_get_len(&iter)); + break; + } + + g_isi_sb_iter_next(&iter); + } + } + + if (!sd->uicc_app_started) { + index = sim_applications_get_next_index(sim_application_list_p, + NOT_ACTIVATED); + + if (index != NOT_AVAILABLE) { + DBG("Activating APP index:%d", index); + sd->trying_app_id = + sim_application_list_p->app_list[index]; + sd->trying_app_type = + sim_application_list_p->app_type[index]; + DBG("Activating APP ID: %d APP type: %d", + sd->trying_app_id, sd->trying_app_type); + uicc_application_activate_req(sd->client, sim, + sim_application_list_p->app_type[index], + sim_application_list_p->app_list[index]); + } else + g_free(sim_application_list_p); + } +} + +static void uicc_application_list_req (GIsiClient *client, + void *opaque) +{ + const unsigned char msg[] = { + UICC_APPLICATION_REQ, + UICC_APPL_LIST, + 0 /* number of subblocks*/ + }; + DBG(""); + + g_isi_client_send_with_timeout( + client, msg, sizeof(msg), SIM_TIMEOUT, + uicc_application_list_resp, opaque, NULL); +} + +static void uicc_pin_enter_resp (const GIsiMessage *msg,void *data) +{ + struct isi_cb_data *cbd = data; + ofono_sim_lock_unlock_cb_t cb = cbd->cb;
drivers/isimodem/sim.c error: · line 1737
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+ struct ofono_sim_local *local_sim = + (struct ofono_sim_local *) cbd->user; + struct ofono_error error; + GIsiSubBlockIter iter; + struct sim_data *sd = + ofono_sim_get_data((struct ofono_sim *) local_sim); + uint8_t status = 0, sbcount = 0; + + if (msg == NULL) + goto error;
Looks reasonable...
drivers/isimodem/sim.c error: · line 1749
Quoted 11 lines
drivers/isimodem/sim.c +11
-0+ g_isi_msg_data_get_byte(msg, 2, &status); + if (status == UICC_STATUS_OK) { + sd->passwd_required = FALSE; + error.type = OFONO_ERROR_TYPE_NO_ERROR; + error.error = 0; + goto out; + } + +error: + g_isi_msg_data_get_byte(msg, 5, &sbcount); + g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
Huh? You ended up here because msg == NULL!
drivers/isimodem/sim.c error: · line 1763
Quoted 13 lines
drivers/isimodem/sim.c +13
-0+ while (g_isi_sb_iter_is_valid(&iter)) { + DBG("Sub-block %s", + uicc_subblock_name(g_isi_sb_iter_get_id(&iter))); + + switch (g_isi_sb_iter_get_id(&iter)) { + case UICC_SB_STATUS_WORD: { + uint16_t status; + g_isi_sb_iter_get_word(&iter, &status, 6); + DBG("APDU status word = %04X", status); + + switch (status) { + case 0x6983: + case 0x9840:
Why aren't these in some PN_UICC related enum?
Quoted 16 lines
drivers/isimodem/sim.c +16
-0+ DBG("Authentication method blocked"); + update_locked_pin(local_sim, + UICC_PIN_UNBLOCK_NEEDED, + sd->current_pin_id); + break; + default: + + if ((status & 0xfff0) == 0x63c0) + DBG("Attempts left %d", status & 0xf); + + break; + } + + break; + } + default:
drivers/isimodem/sim.c error: · line 1789
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+ break; + } + + g_isi_sb_iter_next(&iter); + } + + error.type = OFONO_ERROR_TYPE_FAILURE; + error.error = 1; +out: + cb(&error, cbd->data);
Could you use the CALLBACK_WITH_* macros here instead?
Quoted 33 lines
drivers/isimodem/sim.c +33
-0+} + +static void uicc_pin_enter (struct ofono_sim *sim,const char *passwd, + ofono_sim_lock_unlock_cb_t cb, void *data) +{ + struct sim_data *sd = ofono_sim_get_data(sim); + struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data); + sd->current_pin_id = sd->pin1_id; /* No way to enter PIN2 */ + DBG("PIN=%s PINID=%02x", passwd, sd->current_pin_id); + + if (cbd && sd) { + unsigned char pinlen = strlen(passwd); + unsigned char msg[] = { + UICC_PIN_REQ, + UICC_PIN_VERIFY, + sd->app_id, + 0, /* Filler */ + 0, /* Filler */ + 0, /* Filler */ + 1, /* number of subblocks */ + /* Subblock 1 */ + UICC_SB_PIN >> 8, + UICC_SB_PIN & 0xff, + 0, + 16, /* Max length */ + sd->current_pin_id, /* PIN id */ + UICC_PIN_OLD, /* PIN qualifier */ + pinlen, /* PIN length */ + 0, + 0, + 0, + 0, + 0,
drivers/isimodem/sim.c error: · line 1832
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+ 0, + 0, + 0, + 0 + }; + + if ((pinlen < 4) || (pinlen > 8)) + goto error; + + memmove(&msg[14], passwd, pinlen);
We have typically used struct iovec and the vsend() API for these types of messages.
drivers/isimodem/sim.c error: · line 1846
Quoted 13 lines
drivers/isimodem/sim.c +13
-0+ g_isi_client_send_with_timeout(sd->client, msg, sizeof(msg), + SIM_TIMEOUT, uicc_pin_enter_resp, cbd, + g_free); + return; + } + +error: + CALLBACK_WITH_FAILURE(cb, data); + g_free(cbd); +} + +enum ofono_sim_password_type passwd_type_for_query = + OFONO_SIM_PASSWORD_SIM_PIN;
Just put OFONO_SIM_PASSWORD_SIM_PIN directly in those two places where you end up using this.
Quoted 108 lines
drivers/isimodem/sim.c +108
-0+static void uicc_pin_prompt_resp (const GIsiMessage *msg,void *data) +{ + struct isi_cb_data *cbd = data; + ofono_sim_passwd_cb_t cb = cbd->cb; + struct ofono_sim_local *local_sim = + (struct ofono_sim_local *) cbd->user; + struct sim_data *sd = + ofono_sim_get_data((struct ofono_sim *)local_sim); + + unsigned char lock_type = -1; + GIsiSubBlockIter iter; + uint8_t status = UICC_STATUS_UNKNOWN; + uint8_t pin_attempts = -1; + uint8_t puk_attempts = -1; + + if (!check_response_status(msg, UICC_PIN_RESP, + UICC_PIN_PROMPT_VERIFY) && !check_response_status(msg, + UICC_PIN_RESP, UICC_PIN_INFO)) + goto error; + + if (check_response_status(msg, UICC_PIN_RESP, UICC_PIN_PROMPT_VERIFY)) { + sd->pin_state_received = TRUE; + g_isi_msg_data_get_byte(msg, 2, &status); + } else if (check_response_status(msg, UICC_PIN_RESP, UICC_PIN_INFO)) { + uint8_t sbcount = 0; + + sd->pin_state_received = TRUE; + g_isi_msg_data_get_byte(msg, 5, &sbcount); + g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount); + + while (g_isi_sb_iter_is_valid(&iter)) { + DBG("Sub-block %s", + uicc_subblock_name(g_isi_sb_iter_get_id( + &iter))); + + switch (g_isi_sb_iter_get_id(&iter)) { + case UICC_SB_PIN_INFO: + g_isi_sb_iter_get_byte(&iter, &status, 4); + g_isi_sb_iter_get_byte(&iter, + &pin_attempts, 5); + g_isi_sb_iter_get_byte(&iter, + &puk_attempts, 6); + DBG("Status=%s, PIN attempts=%d, \ +PUK attempts=%d" , + uicc_status_name(status), + pin_attempts, puk_attempts); + break; + default: + break; + } + + g_isi_sb_iter_next(&iter); + } + } + + if ((status == UICC_STATUS_OK) || + (status == UICC_STATUS_PIN_ENABLED)) { + /* PIN query on, indication should tell + * if it is verified or not + */ + if (pin_attempts == 0) { + DBG("PIN blocked"); + update_locked_pin(local_sim, + UICC_PIN_UNBLOCK_NEEDED, + sd->current_pin_id); + } else { + DBG("PIN query enabled"); + update_locked_pin(local_sim, + UICC_PIN_VERIFY_NEEDED, + sd->current_pin_id); + } + + lock_type = local_sim->pin_type; + } else if (status == UICC_STATUS_PIN_DISABLED) { + if (pin_attempts == 0) { + DBG("PIN blocked"); + update_locked_pin(local_sim, + UICC_PIN_UNBLOCK_NEEDED, + sd->current_pin_id); + lock_type = local_sim->pin_type; + } else { + DBG("PIN query disabled"); + local_sim->locked_pins[OFONO_SIM_PASSWORD_SIM_PIN] = + FALSE; + local_sim->locked_pins[OFONO_SIM_PASSWORD_SIM_PIN2] = + FALSE; + lock_type = OFONO_SIM_PASSWORD_NONE; + } + } + + if (check_response_status(msg, UICC_PIN_RESP, UICC_PIN_PROMPT_VERIFY)) { + uicc_pin_prompt(cbd->user, + passwd_type_for_query, + cb, + cbd->data, + UICC_PIN_INFO); + } + + CALLBACK_WITH_SUCCESS(cb, lock_type, cbd->data); + return; +error: + DBG("PIN prompt verify failed"); + CALLBACK_WITH_FAILURE(cb, -1, cbd->data); +} + +static void uicc_pin_prompt(struct ofono_sim *sim, + enum ofono_sim_password_type passwd_type, + ofono_sim_passwd_cb_t cb,
drivers/isimodem/sim.c error: · line 1965
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+ void *data, + uint8_t service) +{ + struct sim_data *sd = ofono_sim_get_data(sim); + struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data); + int8_t index; + sd->current_pin_id = get_pin_id(sd, passwd_type, &index); + DBG("PINID = %02x", sd->current_pin_id); + + if ((cbd) && (sd) && (sd->current_pin_id)) {
Check for NULL here, and for zero pin_id, and return with error.
Quoted 222 lines
drivers/isimodem/sim.c +222
-0+ unsigned char msg[] = { + UICC_PIN_REQ, + service, + sd->app_id, + 0, /*Filler*/ + 0, /*Filler*/ + 0, /*Filler*/ + 1, /*number of subblocks*/ + /* Subblock 1 */ + UICC_SB_PIN_REF >> 8, + UICC_SB_PIN_REF & 0xff, + 0, /*Sub block length.*/ + 8, + sd->current_pin_id, /*PIN ID*/ + 0, /*Filler*/ + 0, /*Filler*/ + 0 /*Filler*/ + }; + g_isi_client_send_with_timeout(sd->client, msg, sizeof(msg), + SIM_TIMEOUT, uicc_pin_prompt_resp, cbd, + g_free); + } else { + DBG("PIN info query failed"); + CALLBACK_WITH_FAILURE(cb, -1, data); + g_free(cbd); + } +} + +static void uicc_passwd_state_query (struct ofono_sim *sim, + ofono_sim_passwd_cb_t cb, + void *data) +{ + struct sim_data *sd = ofono_sim_get_data(sim); + struct ofono_sim_local *local_sim = (struct ofono_sim_local *)sim; + + if (sd->pin_state_received) { + int lock_type = OFONO_SIM_PASSWORD_NONE; + + if (sd->passwd_required) { + /* These should be in priority order, highest last */ + if (local_sim->locked_pins[ + OFONO_SIM_PASSWORD_SIM_PIN] == TRUE) + lock_type = OFONO_SIM_PASSWORD_SIM_PIN; + + if (local_sim->locked_pins[ + OFONO_SIM_PASSWORD_SIM_PIN2] == TRUE) + lock_type = OFONO_SIM_PASSWORD_SIM_PIN2; + + if (local_sim->locked_pins[ + OFONO_SIM_PASSWORD_PHNET_PIN] == TRUE) + lock_type = OFONO_SIM_PASSWORD_PHNET_PIN; + + if (local_sim->locked_pins[ + OFONO_SIM_PASSWORD_SIM_PUK] == TRUE) + lock_type = OFONO_SIM_PASSWORD_SIM_PUK; + + if (local_sim->locked_pins[ + OFONO_SIM_PASSWORD_SIM_PUK2] == TRUE) + lock_type = OFONO_SIM_PASSWORD_SIM_PUK2; + + if (local_sim->locked_pins[ + OFONO_SIM_PASSWORD_PHNET_PUK] == TRUE) + lock_type = OFONO_SIM_PASSWORD_PHNET_PUK; + } + + DBG("UICC lock type=%d", lock_type); + CALLBACK_WITH_SUCCESS(cb, lock_type, data); + } else { + if (sd->uicc_app_started) { + /* No indication received but UICC app is + * started, let's query the state + */ + DBG("Querying PIN info"); + uicc_pin_prompt(sim, passwd_type_for_query, + cb, data, UICC_PIN_PROMPT_VERIFY); + return; + } + + DBG("No UICC_PIN_IND received"); + CALLBACK_WITH_FAILURE(cb, -1, data); + } +} + +static void uicc_pin_enable_resp (const GIsiMessage *msg,void *data) +{ + struct isi_cb_data *cbd = data; + ofono_sim_lock_unlock_cb_t cb = cbd->cb; + struct ofono_sim_local *local_sim = + (struct ofono_sim_local *) cbd->user; + struct sim_data *sd = + ofono_sim_get_data((struct ofono_sim *) local_sim); + + GIsiSubBlockIter iter; + uint8_t sbcount = 0; + + if (!check_response_status(msg, UICC_PIN_RESP, UICC_PIN_DISABLE) && + !check_response_status(msg, UICC_PIN_RESP, + UICC_PIN_ENABLE)) + goto error; + + DBG("PIN lock/unlock succeeded"); + CALLBACK_WITH_SUCCESS(cb, cbd->data); + return; + +error: + g_isi_msg_data_get_byte(msg, 5, &sbcount); + g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount); + + while (g_isi_sb_iter_is_valid(&iter)) { + DBG("Sub-block %s", + uicc_subblock_name(g_isi_sb_iter_get_id(&iter))); + + switch (g_isi_sb_iter_get_id(&iter)) { + case UICC_SB_STATUS_WORD: { + uint16_t status; + g_isi_sb_iter_get_word(&iter, &status, 6); + DBG("APDU status word = %04X", status); + + switch (status) { + case 0x6983: + case 0x9840: + DBG("Authentication method blocked"); + update_locked_pin(local_sim, + UICC_PIN_UNBLOCK_NEEDED, + sd->current_pin_id); + break; + default: + + if ((status & 0xfff0) == 0x63c0) + DBG("Attempts left %d", status & 0xf); + + break; + } + } + default: + break; + } + + g_isi_sb_iter_next(&iter); + } + + DBG("PIN lock/unlock failed"); + CALLBACK_WITH_FAILURE(cb, cbd->data); +} + +static void uicc_pin_enable (struct ofono_sim *sim, + enum ofono_sim_password_type passwd_type, + int enable, const char *passwd, + ofono_sim_lock_unlock_cb_t cb, void *data) +{ + struct sim_data *sd = ofono_sim_get_data(sim); + struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data); + int8_t index; + unsigned char service = 0; + sd->current_pin_id = get_pin_id(sd, passwd_type, &index); + + DBG("Lock=%d, PIN code=%s, PIN ID =%d", + enable, passwd, sd->current_pin_id); + if (enable) { + DBG("Enabling PIN"); + service = UICC_PIN_ENABLE; + } else { + DBG("Disabling PIN"); + service = UICC_PIN_DISABLE; + } + if ((cbd) && (sd) && (sd->current_pin_id)) { + + unsigned char pinlen = strlen(passwd); + + unsigned char msg[] = { + UICC_PIN_REQ, + service, + sd->app_id, + 0, /*Filler*/ + 0, /*Filler*/ + 0, /*Filler*/ + 1, /*number of subblocks*/ + /* Subblock 1 */ + UICC_SB_PIN >> 8, + UICC_SB_PIN & 0xff, + 0, + 16, /*Max length*/ + sd->current_pin_id, /* PIN id */ + UICC_PIN_OLD, /* PIN qualifier */ + pinlen, /* PIN length */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }; + + if ((pinlen < 4) || (pinlen > 8)) + goto error; + memmove(&msg[14], passwd, pinlen); + g_isi_client_send_with_timeout( + sd->client, msg, sizeof(msg), SIM_TIMEOUT, + uicc_pin_enable_resp, cbd, g_free); + return; + } + +error: + DBG("Error"); + CALLBACK_WITH_FAILURE(cb, data); + g_free(cbd); + return; +} + +static void uicc_pin_change_resp (const GIsiMessage *msg,void *data) +{ + struct isi_cb_data *cbd = data; + ofono_sim_lock_unlock_cb_t cb = cbd->cb; + struct ofono_sim_local *local_sim = + (struct ofono_sim_local *) cbd->user; + struct sim_data *sd = + ofono_sim_get_data((struct ofono_sim *) local_sim); + + GIsiSubBlockIter iter;
drivers/isimodem/sim.c error: · line 2197
Quoted 10 lines
drivers/isimodem/sim.c +10
-0+ uint8_t sbcount = 0; + + if (!check_response_status(msg, UICC_PIN_RESP, UICC_PIN_CHANGE)) + goto error; + + DBG("PIN change succeeded"); + CALLBACK_WITH_SUCCESS(cb, cbd->data); + return; + +error:
Same as above, this can't be right that you end up decoding the message when there is a response reporting failure?
Cheers,
Aki
PATCH 9/18 isimodem: clip colp clir colr wgmodem2.5
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/call-settings.c | 697 +++++++++++++++++++++++++++++++++++++- drivers/isimodem/call.h | 9 + drivers/isimodem/debug.c | 4 + drivers/isimodem/ss.h | 22 ++ 4 files changed, 714 insertions(+), 18 deletions(-)
drivers/isimodem/call-settings.c +679 -18
@@ -3,6 +3,7 @@* oFono - Open Source Telephony * * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). +* Copyright (C) ST-Ericsson SA 2011. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
@@ -43,10 +44,15 @@#include "ss.h" #include "debug.h" +#define CLIP_ETC +struct settings_data {GIsiClient *client; }; +#define content_size 40 +static char content[content_size] = {0 }; +static void update_status_mask (unsigned int *mask,int bsc) {switch (bsc) {
@@ -88,7 +94,6 @@ static void update_status_mask(unsigned int *mask, int bsc)break ; } } -static gboolean check_response_status (const GIsiMessage *msg,uint8_t msgid) {if (g_isi_msg_error (msg) <0 ) {
@@ -104,6 +109,59 @@ static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid)return TRUE; } +static void clip_query_cb (const GIsiMessage *msg,void *data) +{ +GIsiSubBlockIter iter; +struct isi_cb_data *cbd = data; + +ofono_call_settings_status_cb_t cb = cbd->cb; +uint8_t service; +guint32 mask =0 ; + +if (!check_response_status (msg,SS_SERVICE_COMPLETED_RESP )) + goto error; + +if (!g_isi_msg_data_get_byte (msg,0 , &service) || + service !=SS_INTERROGATION ) + goto error; + +for (g_isi_sb_iter_init (&iter, msg,6 ); +g_isi_sb_iter_is_valid (&iter); +g_isi_sb_iter_next (&iter)) { +DBG ("Sub-block %s" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter))); + +switch (g_isi_sb_iter_get_id (&iter)) { +case SS_STATUS_RESULT : { +guint8 ss_status; + +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + +DBG ("SS_STATUS_RESULT=%d" , ss_status); + +if (ss_status &SS_GSM_PROVISIONED ) + mask =1 ; + } +break ; +case SS_GSM_ADDITIONAL_INFO : +break ; +default : +DBG ("Skipping sub-block: %s (%zd bytes)" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter)), +g_isi_sb_iter_get_len (&iter)); +break ; + } + } + +DBG ("status_mask %d\n" , mask); +CALLBACK_WITH_SUCCESS (cb, mask, cbd->data); +return ; +error: +CALLBACK_WITH_FAILURE (cb,0 , cbd->data); +} + +static gboolean decode_gsm_bsc_info (GIsiSubBlockIter *iter,uint32_t *mask) {uint8_t num;
@@ -136,23 +194,611 @@ static void query_resp_cb(const GIsiMessage *msg, void *data) goto error;for (g_isi_sb_iter_init (&iter, msg,6 ); +g_isi_sb_iter_is_valid (&iter); +g_isi_sb_iter_next (&iter)) { + +if (g_isi_sb_iter_get_id (&iter) ==SS_GSM_BSC_INFO ) { +if (!decode_gsm_bsc_info (&iter, &mask)) + goto error; + +CALLBACK_WITH_SUCCESS (cb, mask, cbd->data); +return ; + }else if (g_isi_sb_iter_get_id (&iter) ==SS_STATUS_RESULT ) { +guint8 ss_status; + +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + +if (ss_status &SS_GSM_PROVISIONED ) + mask =1 ; +CALLBACK_WITH_SUCCESS (cb, mask, cbd->data); +return ; + } + } + +error: +CALLBACK_WITH_FAILURE (cb,0 , cbd->data); +} + +static void isi_clip_query (struct ofono_call_settings *cs, +ofono_call_settings_status_cb_t cb,void *data) +{ +struct settings_data *sd =ofono_call_settings_get_data (cs); +struct isi_cb_data *cbd =isi_cb_data_new (cs, cb, data); +unsigned char msg[] = { +SS_SERVICE_REQ , +SS_INTERROGATION , +SS_ALL_TELE_AND_BEARER , +SS_GSM_CLIP >>8 ,/* Supplementary services */ +SS_GSM_CLIP &0xFF ,/* code */ +SS_SEND_ADDITIONAL_INFO , +0 /* Subblock count */ + }; +DBG ("" ); + +if (cbd ==NULL ) + goto error; + +if (g_isi_client_send (sd->client, msg,sizeof (msg), + clip_query_cb, cbd, g_free)) +return ; + +error: +CALLBACK_WITH_FAILURE (cb,0 , data); +g_free (cbd); +} + +static int set_clir_status (const char *value) +{ +DBG ("Setting CLIR status to %s" , value); +strncpy (content, value, content_size); + content[content_size-1 ] =0 ; +return EXIT_SUCCESS ; +} + +static int get_clir_status (void ) +{ +DBG ("Getting CLIR status %s" , content); + +if (!strcmp (content,"OFONO_CLIR_OPTION_INVOCATION" )) +return OFONO_CLIR_OPTION_INVOCATION ; + +if (!strcmp (content,"OFONO_CLIR_OPTION_SUPPRESSION" )) +return OFONO_CLIR_OPTION_SUPPRESSION ; + +return OFONO_CLIR_OPTION_DEFAULT ; +} + +static void clir_set_cb (const GIsiMessage *msg,void *data) +{ +GIsiSubBlockIter iter, iter_info; +struct isi_cb_data *cbd = data; +ofono_call_settings_set_cb_t cb = cbd->cb; +gint override =OFONO_CLIR_OPTION_DEFAULT ; +gint network =CLIR_STATUS_UNKNOWN ; +uint8_t service; + +if (!check_response_status (msg,SS_SERVICE_COMPLETED_RESP )) + goto error; + +if (!g_isi_msg_data_get_byte (msg,0 , &service) || + service !=SS_INTERROGATION ) + goto error; + +for (g_isi_sb_iter_init (&iter, msg,6 );g_isi_sb_iter_is_valid (&iter);g_isi_sb_iter_next (&iter)) { +DBG ("Sub-block %s" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter))); -if (g_isi_sb_iter_get_id (&iter) !=SS_GSM_BSC_INFO ) -continue ; +switch (g_isi_sb_iter_get_id (&iter)) { +case SS_STATUS_RESULT : { +guint8 ss_status; + +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + +DBG ("SS_STATUS_RESULT=%d" , ss_status); + +if (!(ss_status &SS_GSM_PROVISIONED )) + network =CLIR_STATUS_NOT_PROVISIONED ; + } +break ; +case SS_GSM_ADDITIONAL_INFO : +break ; +case SS_GSM_GENERIC_SERVICE_INFO : { +guint8 ss_status =0 ; +guint8 clir_option =0 ; +void *info =NULL ; +GIsiMessage info_msg; + +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + +if (!(ss_status &SS_GSM_PROVISIONED )) + network =CLIR_STATUS_NOT_PROVISIONED ; + +if (!g_isi_sb_iter_get_data (&iter, &info,4 )) + goto error; + + info_msg.addr =NULL ; + info_msg.error =0 ; +/* +* GIsiMessage function adds 2 to data pointer and +* removes 2 from len +*/ + info_msg.data = info -2 ; + info_msg.len = msg->len -6 +2 ; + +for (g_isi_sb_iter_init (&iter_info, &info_msg,0 ); +g_isi_sb_iter_is_valid (&iter_info); +g_isi_sb_iter_next (&iter_info)) { +DBG ("Sub-block %s" , +ss_subblock_name ( +g_isi_sb_iter_get_id (&iter_info))); + +switch (g_isi_sb_iter_get_id (&iter_info)) { +case SS_GSM_CLIR_INFO : { +if (!g_isi_sb_iter_get_byte (&iter_info, + &clir_option,2 )) + goto error; + } +break ; + } + +DBG ("SS_STATUS_RESULT=%d, CLIR_OPTION=%d" , + ss_status, clir_option); + } + +if (network !=CLIR_STATUS_NOT_PROVISIONED ) { +int result; +DBG ("CLIR set successfully." ); + result =set_clir_status ( +"OFONO_CLIR_OPTION_INVOCATION" ); + +if (result ==EXIT_FAILURE ) + goto error; + }else { +DBG ("CLIR option not supported by network " +"provider." ); + } + } +break ; +default : +DBG ("Skipping sub-block: %s (%zd bytes)" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter)), +g_isi_sb_iter_get_len (&iter)); +break ; + } + } -if (!decode_gsm_bsc_info (&iter, &mask)) +DBG ("override=%d, network=%d\n" , override, network); +CALLBACK_WITH_SUCCESS (cb, cbd->data); +return ; +error: +CALLBACK_WITH_FAILURE (cb, cbd->data); +} + +static void isi_clir_set (struct ofono_call_settings *cs, +int mode, +ofono_call_settings_set_cb_t cb, +void *data) +{ +struct settings_data *sd =ofono_call_settings_get_data (cs); +struct isi_cb_data *cbd =isi_cb_data_new (cs, cb, data); +int result =0 ; +/* +* CLIR cannot be activated in Network, but we can override it +* using local settings - 3GPP TS 24.081 Chapter 2.5 +*/ + +switch (mode) { +case (OFONO_CLIR_OPTION_DEFAULT ): + result =set_clir_status ("OFONO_CLIR_OPTION_DEFAULT" ); +break ; +/* CLIR enabled (number not shown) */ +case (OFONO_CLIR_OPTION_INVOCATION ): { +/* +* We send interrogation request to check if Network +* has CLIR option provisioned. +*/ +unsigned char msg[] = { +SS_SERVICE_REQ , +SS_INTERROGATION , +SS_ALL_TELE_AND_BEARER , +SS_GSM_CLIR >>8 ,/* Supplementary services */ +SS_GSM_CLIR &0xFF ,/* code */ +SS_SEND_ADDITIONAL_INFO , +0 /* Subblock count */ + }; + +DBG ("Attempting to set the CLIR - checking Network Settings" ); + +if (cbd ==NULL ) + goto error; + +if (g_isi_client_send (sd->client, msg,sizeof (msg), + clir_set_cb, cbd, g_free)) + +return ; +else goto error; + } +break ; +case (OFONO_CLIR_OPTION_SUPPRESSION ):/* CLIR disabled (number shown) */ + result =set_clir_status ("OFONO_CLIR_OPTION_SUPPRESSION" ); +break ; +default : +DBG ("CLIR mode not supported %d" , mode); +break ; + } + +if (result ==EXIT_FAILURE ) + goto error; + +DBG ("CLIR set to mode: %d" , mode); +CALLBACK_WITH_SUCCESS (cb, data); + goto out; +error: +CALLBACK_WITH_FAILURE (cb, data); +out: +g_free (cbd); +return ; +} + +static void clir_query_cb (const GIsiMessage *msg,void *data) +{ +GIsiSubBlockIter iter, iter_info; +struct isi_cb_data *cbd = data; +ofono_call_settings_clir_cb_t cb = cbd->cb; +uint8_t service; +gint override =OFONO_CLIR_OPTION_DEFAULT ; +gint network =CLIR_STATUS_UNKNOWN ; + + +if (!check_response_status (msg,SS_SERVICE_COMPLETED_RESP )) + goto error; + +if (!g_isi_msg_data_get_byte (msg,0 , &service) || + service !=SS_INTERROGATION ) + goto error; + +for (g_isi_sb_iter_init (&iter, msg,6 ); +g_isi_sb_iter_is_valid (&iter); +g_isi_sb_iter_next (&iter)) { +DBG ("Sub-block %s" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter))); +switch (g_isi_sb_iter_get_id (&iter)) { +case SS_STATUS_RESULT : { +guint8 ss_status; + +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + +DBG ("SS_STATUS_RESULT=%d" , ss_status); + +if (!(ss_status &SS_GSM_PROVISIONED )) + network =CLIR_STATUS_NOT_PROVISIONED ; + } +break ; +case SS_GSM_ADDITIONAL_INFO : +break ; +case SS_GSM_GENERIC_SERVICE_INFO : { +guint8 ss_status =0 ; +guint8 clir_option =0 ; +void *info =NULL ; +GIsiMessage info_msg; + +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + +if (!(ss_status &SS_GSM_PROVISIONED )) + network =CLIR_STATUS_NOT_PROVISIONED ; + +if (!g_isi_sb_iter_get_data (&iter, &info,4 )) + goto error; + + info_msg.addr =NULL ; + info_msg.error =0 ; +/* GIsiMessage function adds 2 to data pointer and +* removes 2 from len */ + info_msg.data = info -2 ; + info_msg.len = msg->len -6 +2 ; + +for (g_isi_sb_iter_init (&iter_info, &info_msg,0 ); +g_isi_sb_iter_is_valid (&iter_info); +g_isi_sb_iter_next (&iter_info)) { +uint8_t id =g_isi_sb_iter_get_id (&iter_info); +DBG ("Sub-sub-block %d" , id); + +switch (id) { +case SS_GSM_CLIR_INFO : { +if (!g_isi_sb_iter_get_byte (&iter_info, + &clir_option,2 )) + goto error; +break ; + } +default : +break ; + } + +DBG ("SS_STATUS_RESULT=%d, CLIR_OPTION=%d" , + ss_status, clir_option); + } + +if (network !=CLIR_STATUS_NOT_PROVISIONED ) { +switch (clir_option) { +case SS_GSM_CLI_PERMANENT : + network = +CLIR_STATUS_PROVISIONED_PERMANENT ; +break ; +case SS_GSM_DEFAULT_RESTRICTED : +break ; +case SS_GSM_CLI_DEFAULT_ALLOWED : + network = +CLIR_STATUS_TEMPORARY_ALLOWED ; +break ; +case SS_GSM_OVERRIDE_ENABLED : + override = +OFONO_CLIR_OPTION_SUPPRESSION ; +break ; +case SS_GSM_OVERRIDE_DISABLED : + override = +OFONO_CLIR_OPTION_INVOCATION ; +break ; +default : +break ; + } + } + } +break ; +default : +DBG ("Skipping sub-block: %s (%zd bytes)" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter)), +g_isi_sb_iter_get_len (&iter)); +break ; + } + } +/* +* CLIR cannot be activated,registrated in Network, but we can override +* it using local settings - 33GPP TS 24.081 Chapter 2.5 +* we have to read status and pass override parameter to Ofono +*/ + +if (network !=CLIR_STATUS_NOT_PROVISIONED ) { + override =get_clir_status (); +DBG ("CLIR mode queried %d\n" , override); + } + +DBG ("override=%d, network=%d\n" , override, network); +CALLBACK_WITH_SUCCESS (cb, override, network, cbd->data); +return ; +error: +CALLBACK_WITH_FAILURE (cb, override, network, cbd->data); +} + +static void isi_clir_query (struct ofono_call_settings *cs, +ofono_call_settings_clir_cb_t cb,void *data) +{ +struct settings_data *sd =ofono_call_settings_get_data (cs); +struct isi_cb_data *cbd =isi_cb_data_new (cs, cb, data); +int override =0 , network =2 ; +unsigned char msg[] = { +SS_SERVICE_REQ , +SS_INTERROGATION , +SS_ALL_TELE_AND_BEARER , +SS_GSM_CLIR >>8 ,/* Supplementary services */ +SS_GSM_CLIR &0xFF ,/* code */ +SS_SEND_ADDITIONAL_INFO , +0 /* Subblock count */ + }; +DBG ("" ); + +if (cbd ==NULL ) + goto error; + +if (g_isi_client_send (sd->client, msg,sizeof (msg), + clir_query_cb, cbd, g_free)) +return ; + +error: +CALLBACK_WITH_FAILURE (cb, override, network, data); +g_free (cbd); +} + +static void colp_query_cb (const GIsiMessage *msg,void *data) +{ +GIsiSubBlockIter iter; +struct isi_cb_data *cbd = data; +ofono_call_settings_status_cb_t cb = cbd->cb; +uint8_t service; +guint32 mask =0 ; + +if (!check_response_status (msg,SS_SERVICE_COMPLETED_RESP )) + goto error; + +if (!g_isi_msg_data_get_byte (msg,0 , &service) || + service !=SS_INTERROGATION ) + goto error; + +for (g_isi_sb_iter_init (&iter, msg,6 ); +g_isi_sb_iter_is_valid (&iter); +g_isi_sb_iter_next (&iter)) { +DBG ("Sub-block %s" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter))); + +switch (g_isi_sb_iter_get_id (&iter)) { +case SS_STATUS_RESULT : { +guint8 ss_status; + +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + +DBG ("SS_STATUS_RESULT=%d" , ss_status); + +if (ss_status &SS_GSM_PROVISIONED ) + mask =1 ; + } +break ; +case SS_GSM_ADDITIONAL_INFO : +break ; +case SS_GSM_BSC_INFO : { +guint8 bsc; +guint8 count; +guint8 i; + +if (!g_isi_sb_iter_get_byte (&iter, &count,2 )) + goto error; + +for (i =0 ; i < count; i++) { +if (!g_isi_sb_iter_get_byte (&iter, &bsc,3 + i)) + goto error; + +update_status_mask (&mask, bsc); + } + +break ; + } +default : +DBG ("Skipping sub-block: %s (%zd bytes)" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter)), +g_isi_sb_iter_get_len (&iter)); +break ; + } + } + +DBG ("status_mask %d\n" , mask); +CALLBACK_WITH_SUCCESS (cb, mask, cbd->data); +return ; +error: +CALLBACK_WITH_FAILURE (cb,0 , cbd->data); +} + +static void isi_colp_query (struct ofono_call_settings *cs, +ofono_call_settings_status_cb_t cb,void *data) +{ +struct settings_data *sd =ofono_call_settings_get_data (cs); +struct isi_cb_data *cbd =isi_cb_data_new (cs, cb, data); +unsigned char msg[] = { +SS_SERVICE_REQ , +SS_INTERROGATION , +SS_ALL_TELE_AND_BEARER , +SS_GSM_COLP >>8 ,/* Supplementary services */ +SS_GSM_COLP &0xFF ,/* code */ +SS_SEND_ADDITIONAL_INFO , +0 /* Subblock count */ + }; +DBG ("" ); + +if (cbd ==NULL ) + goto error; -CALLBACK_WITH_SUCCESS (cb, mask, cbd->data); +if (g_isi_client_send (sd->client, msg,sizeof (msg), + colp_query_cb, cbd, g_free))return ; + +error: +CALLBACK_WITH_FAILURE (cb,0 , data); +g_free (cbd); +} + +static void colr_query_cb (const GIsiMessage *msg,void *data) +{ +GIsiSubBlockIter iter; +struct isi_cb_data *cbd = data; +ofono_call_settings_status_cb_t cb = cbd->cb; +uint8_t service; +guint32 mask =0 ; + +if (!check_response_status (msg,SS_SERVICE_COMPLETED_RESP )) + goto error; + +if (!g_isi_msg_data_get_byte (msg,0 , &service) || + service !=SS_INTERROGATION ) + goto error; + +for (g_isi_sb_iter_init (&iter, msg,6 ); +g_isi_sb_iter_is_valid (&iter); +g_isi_sb_iter_next (&iter)) { +DBG ("Sub-block %s" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter))); + +switch (g_isi_sb_iter_get_id (&iter)) { +case SS_STATUS_RESULT : { +guint8 ss_status; + +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + +DBG ("SS_STATUS_RESULT=%d" , ss_status); + +if (ss_status &SS_GSM_PROVISIONED ) + mask =1 ; + } +break ; +case SS_GSM_ADDITIONAL_INFO : +break ; +case SS_GSM_BSC_INFO : { +guint8 bsc; +guint8 count; +guint8 i; + +if (!g_isi_sb_iter_get_byte (&iter, &count,2 )) + goto error; +for (i =0 ; i < count; i++) { +if (!g_isi_sb_iter_get_byte (&iter, &bsc, +3 + i)) + goto error; + +update_status_mask (&mask, bsc); + } + +break ; + } +default : +DBG ("Skipping sub-block: %s (%zd bytes)" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter)), +g_isi_sb_iter_get_len (&iter)); +break ; + } } +DBG ("status_mask %d\n" , mask); +CALLBACK_WITH_SUCCESS (cb, mask, cbd->data); +return ; error:CALLBACK_WITH_FAILURE (cb,0 , cbd->data); } +static void isi_colr_query (struct ofono_call_settings *cs, +ofono_call_settings_status_cb_t cb,void *data) +{ +struct settings_data *sd =ofono_call_settings_get_data (cs); +struct isi_cb_data *cbd =isi_cb_data_new (cs, cb, data); +unsigned char msg[] = { +SS_SERVICE_REQ , +SS_INTERROGATION , +SS_ALL_TELE_AND_BEARER , +SS_GSM_COLR >>8 ,/* Supplementary services */ +SS_GSM_COLR &0xFF ,/* code */ +SS_SEND_ADDITIONAL_INFO , +0 /* Subblock count */ + }; +DBG ("" ); + +if (cbd ==NULL ) + goto error; + +if (g_isi_client_send (sd->client, msg,sizeof (msg), + colr_query_cb, cbd, g_free)) + +return ; + +error: +CALLBACK_WITH_FAILURE (cb,0 , data); +g_free (cbd); +} +static void isi_cw_query (struct ofono_call_settings *cs,int cls,ofono_call_settings_status_cb_t cb,void *data) {
@@ -205,17 +851,31 @@ static void set_resp_cb(const GIsiMessage *msg, void *data)if (g_isi_sb_iter_get_id (&iter) !=SS_GSM_DATA )continue ; -if (!g_isi_sb_iter_get_byte (&iter, &status,2 )) - goto error; +if (g_isi_sb_iter_get_id (&iter) ==SS_GSM_DATA ) { +if (!g_isi_sb_iter_get_byte (&iter, &status,2 )) + goto error; -if ((status &SS_GSM_ACTIVE ) && (service ==SS_DEACTIVATION )) - goto error; +if ((status &SS_GSM_ACTIVE ) && + (service ==SS_DEACTIVATION )) + goto error; -if (!(status &SS_GSM_ACTIVE ) && (service ==SS_ACTIVATION )) - goto error; +if (!(status &SS_GSM_ACTIVE ) && + (service ==SS_ACTIVATION )) + goto error; -CALLBACK_WITH_SUCCESS (cb, cbd->data); -return ; +CALLBACK_WITH_SUCCESS (cb, cbd->data); +return ; + }else if (g_isi_sb_iter_get_id (&iter) ==SS_GSM_DATA ) { +guint8 ss_status; + +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + + +CALLBACK_WITH_SUCCESS (cb, cbd->data); +return ; + + } } error:
@@ -273,6 +933,7 @@ static int isi_call_settings_probe(struct ofono_call_settings *cs,return -ENOMEM ; sd->client =g_isi_client_create (modem,PN_SS ); +if (sd->client ==NULL ) {g_free (sd);return -ENOMEM ;
@@ -302,11 +963,11 @@ static struct ofono_call_settings_driver driver = { .name = "isimodem", .probe = isi_call_settings_probe, .remove = isi_call_settings_remove, - .clip_query = NULL, - .colp_query = NULL, - .clir_query = NULL, - .colr_query = NULL, - .clir_set = NULL, + .clip_query = isi_clip_query, + .colp_query = isi_colp_query, + .clir_query = isi_clir_query, + .colr_query = isi_colr_query, + .clir_set = isi_clir_set, .cw_query = isi_cw_query, .cw_set = isi_cw_set };
drivers/isimodem/call.h +9 -0
@@ -402,6 +402,15 @@ enum { CALL_DTMF_DISABLE_TONE_IND_SEND = 0x02, }; +/* 27.007 Section 7.7 */ +enum clir_status { +CLIR_STATUS_NOT_PROVISIONED =0 , +CLIR_STATUS_PROVISIONED_PERMANENT , +CLIR_STATUS_UNKNOWN , +CLIR_STATUS_TEMPORARY_RESTRICTED , +CLIR_STATUS_TEMPORARY_ALLOWED +}; +#ifdef __cplusplus };#endif
drivers/isimodem/debug.c +4 -0
@@ -95,10 +95,14 @@ const char *ss_subblock_name(enum ss_subblock value)_ (SS_GSM_FORWARDING_FEATURE );_ (SS_GSM_DATA );_ (SS_GSM_BSC_INFO ); +_ (SS_GSM_GENERIC_SERVICE_INFO ); +_ (SS_GSM_CLIR_INFO );_ (SS_GSM_PASSWORD_INFO );_ (SS_GSM_INDICATE_PASSWORD_ERROR );_ (SS_GSM_INDICATE_ERROR );_ (SS_GSM_ADDITIONAL_INFO ); +_ (SS_GSM_BARRING_INFO ); +_ (SS_GSM_BARRING_FEATURE );_ (SS_GSM_USSD_STRING ); }return "SS_<UNKNOWN>" ;
drivers/isimodem/ss.h +22 -0
@@ -94,6 +94,12 @@ enum ss_codes {SS_GSM_BARR_OUT_INTER =331 ,SS_GSM_BARR_OUT_INTER_EXC_HOME =332 ,SS_GSM_BARR_ALL_IN_ROAM =351 , +SS_GSM_CLIP =0x001E , +SS_GSM_CLIR =0x001F , +SS_GSM_COLP =0x004C , +SS_GSM_COLR =0x004D , +SS_GSM_CNAP =0x012C , +SS_GSM_ECT =0x0060 }; enum ss_response_data {
@@ -106,9 +112,13 @@ enum ss_subblock {SS_GSM_PASSWORD =0x03 ,SS_GSM_FORWARDING_INFO =0x04 ,SS_GSM_FORWARDING_FEATURE =0x05 , +SS_GSM_BARRING_INFO =0x06 , +SS_GSM_BARRING_FEATURE =0x07 ,SS_GSM_DATA =0x08 ,SS_GSM_BSC_INFO =0x09 , +SS_GSM_GENERIC_SERVICE_INFO =0x0A ,SS_GSM_PASSWORD_INFO =0x0B , +SS_GSM_CLIR_INFO =0x0C ,SS_GSM_INDICATE_PASSWORD_ERROR =0x0D ,SS_GSM_INDICATE_ERROR =0x0E , SS_GSM_ADDITIONAL_INFO = 0x2F,
@@ -122,4 +132,16 @@ enum ss_isi_cause { SS_GSM_QUIESCENT = 0x08, }; +enum ss_gsm_cli_restriction_option { +SS_GSM_CLI_PERMANENT =0x00 , +SS_GSM_DEFAULT_RESTRICTED =0x01 , +SS_GSM_CLI_DEFAULT_ALLOWED =0x02 , +SS_GSM_OVERRIDE_ENABLED =0x03 , +SS_GSM_OVERRIDE_DISABLED =0x04 +}; + +enum ss_constants { +SS_UNDEFINED_TIME =0x00 , +}; +#endif /* __ISIMODEM_SS_H */
Signature · 1 line
1.7.3.5
Re: [PATCH 09/18] isimodem: clip colp clir colr wgmodem2.5
Hi Andreas,
2011/2/15 Andreas Westin <[email protected]>:
Quoted 22 lines
From: Jessica Nilsson <[email protected]>
---
drivers/isimodem/call-settings.c | 697 +++++++++++++++++++++++++++++++++++++-drivers/isimodem/call.h| 9 +drivers/isimodem/debug.c| 4 +
drivers/isimodem/ss.h | 22 ++4 files changed, 714 insertions(+), 18 deletions(-)drivers/isimodem/call-settings.c +1
-0@@ -3,6 +3,7 @@ * oFono - Open Source Telephony * * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) ST-Ericsson SA 2011. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
drivers/isimodem/call-settings.c line 48
Quoted 5 lines
drivers/isimodem/call-settings.c +2
-0@@ -43,10 +44,15 @@ #include "ss.h" #include "debug.h" +#define CLIP_ETC +
I don't see this used anywhere in the code.
Quoted 7 lines
drivers/isimodem/call-settings.c +3
-0struct settings_data { GIsiClient *client; }; +#define content_size 40 +static char content[content_size] = {0 }; +
(snip)
Quoted 10 lines
drivers/isimodem/call-settings.c +10
-0+static int set_clir_status (const char *value) +{ + DBG("Setting CLIR status to %s", value); + strncpy(content, value, content_size); + content[content_size-1] = 0; + return EXIT_SUCCESS; +} + +static int get_clir_status (void ) +{
drivers/isimodem/call-settings.c static void query_resp_cb(const GIsiMessage *msg, void *data) · line 270
Quoted 10 lines
drivers/isimodem/call-settings.c +10
-0+ DBG("Getting CLIR status %s", content); + + if (!strcmp(content, "OFONO_CLIR_OPTION_INVOCATION")) + return OFONO_CLIR_OPTION_INVOCATION; + + if (!strcmp(content, "OFONO_CLIR_OPTION_SUPPRESSION")) + return OFONO_CLIR_OPTION_SUPPRESSION; + + return OFONO_CLIR_OPTION_DEFAULT; +}
I don't understand this part. Why is 'content' a static buffer, and why is strncpy() used? All I see are const strings copied there.
Also, if the getter anyway returns an int, why not store an int there in the first place? Could it also be part of the call-settings driver data?
Quoted 102 lines
drivers/isimodem/call-settings.c +17
-0+static void clir_set_cb (const GIsiMessage *msg,void *data) +{ + GIsiSubBlockIter iter, iter_info; + struct isi_cb_data *cbd = data; + ofono_call_settings_set_cb_t cb = cbd->cb; + gint override = OFONO_CLIR_OPTION_DEFAULT; + gint network = CLIR_STATUS_UNKNOWN; + uint8_t service; + + if (!check_response_status(msg, SS_SERVICE_COMPLETED_RESP)) + goto error; + + if (!g_isi_msg_data_get_byte(msg, 0, &service) || + service != SS_INTERROGATION) + goto error; + + for (g_isi_sb_iter_init(&iter, msg, 6);g_isi_sb_iter_is_valid(&iter);
g_isi_sb_iter_next(&iter)) {
+ DBG("Sub-block %s",
+ ss_subblock_name(g_isi_sb_iter_get_id(&iter)));- if (
g_isi_sb_iter_get_id(&iter)!=SS_GSM_BSC_INFO)
- continue;
+ switch (g_isi_sb_iter_get_id(&iter)) {
+ caseSS_STATUS_RESULT: {
+ guint8ss_status;drivers/isimodem/call-settings.c +75
-0+ + if (!g_isi_sb_iter_get_byte(&iter, &ss_status, 2)) + goto error; + + DBG("SS_STATUS_RESULT=%d", ss_status); + + if (!(ss_status & SS_GSM_PROVISIONED)) + network = CLIR_STATUS_NOT_PROVISIONED; + } + break; + case SS_GSM_ADDITIONAL_INFO: + break; + case SS_GSM_GENERIC_SERVICE_INFO: { + guint8 ss_status = 0; + guint8 clir_option = 0; + void *info = NULL; + GIsiMessage info_msg; + + if (!g_isi_sb_iter_get_byte(&iter, &ss_status, 2)) + goto error; + + if (!(ss_status & SS_GSM_PROVISIONED)) + network = CLIR_STATUS_NOT_PROVISIONED; + + if (!g_isi_sb_iter_get_data(&iter, &info, 4)) + goto error; + + info_msg.addr = NULL; + info_msg.error = 0; + /* + * GIsiMessage function adds 2 to data pointer and + * removes 2 from len + */ + info_msg.data = info - 2; + info_msg.len = msg->len - 6 + 2; + + for (g_isi_sb_iter_init(&iter_info, &info_msg, 0); + g_isi_sb_iter_is_valid(&iter_info); + g_isi_sb_iter_next(&iter_info)) { + DBG("Sub-block %s", + ss_subblock_name( + g_isi_sb_iter_get_id(&iter_info))); + + switch (g_isi_sb_iter_get_id(&iter_info)) { + case SS_GSM_CLIR_INFO: { + if (!g_isi_sb_iter_get_byte(&iter_info, + &clir_option, 2)) + goto error; + } + break; + } + + DBG("SS_STATUS_RESULT=%d, CLIR_OPTION=%d", + ss_status, clir_option); + } + + if (network != CLIR_STATUS_NOT_PROVISIONED) { + int result; + DBG("CLIR set successfully."); + result = set_clir_status( + "OFONO_CLIR_OPTION_INVOCATION"); + + if (result == EXIT_FAILURE) + goto error; + } else { + DBG("CLIR option not supported by network " + "provider."); + } + } + break; + default: + DBG("Skipping sub-block: %s (%zd bytes)", + ss_subblock_name(g_isi_sb_iter_get_id(&iter)), + g_isi_sb_iter_get_len(&iter)); + break;
drivers/isimodem/call-settings.c static void query_resp_cb(const GIsiMessage *msg, void *data) · line 380
Quoted 10 lines
drivers/isimodem/call-settings.c +8
-1+ } + } - if (!decode_gsm_bsc_info(&iter, &mask)) + DBG("override=%d, network=%d\n", override, network); + CALLBACK_WITH_SUCCESS(cb, cbd->data); + return; +error: + CALLBACK_WITH_FAILURE(cb, cbd->data); +}
This function is really hard to follow. I would consider breaking it up so that each sub-block decoder is a separate static function of its own.
Quoted 7 lines
drivers/isimodem/call-settings.c +7
-0+static void isi_clir_set (struct ofono_call_settings *cs, + int mode, + ofono_call_settings_set_cb_t cb, + void *data) +{ + struct settings_data *sd = ofono_call_settings_get_data(cs); + struct isi_cb_data *cbd = isi_cb_data_new(cs, cb, data);
drivers/isimodem/call-settings.c static void query_resp_cb(const GIsiMessage *msg, void *data) · line 398
Quoted 10 lines
drivers/isimodem/call-settings.c +10
-0+ int result = 0; + /* + * CLIR cannot be activated in Network, but we can override it + * using local settings - 3GPP TS 24.081 Chapter 2.5 + */ + + switch (mode) { + case(OFONO_CLIR_OPTION_DEFAULT): + result = set_clir_status("OFONO_CLIR_OPTION_DEFAULT"); + break;
Indentation is broken here.
Quoted 75 lines
+ /* CLIR enabled (number not shown) */
+case(OFONO_CLIR_OPTION_INVOCATION): {
+ /*
+ * We send interrogation request to check if Network
+ * has CLIR option provisioned.
+ */
+ unsigned char msg[] = {
+SS_SERVICE_REQ,
+SS_INTERROGATION,
+SS_ALL_TELE_AND_BEARER,
+SS_GSM_CLIR>> 8, /* Supplementary services */
+SS_GSM_CLIR&0xFF, /* code */
+SS_SEND_ADDITIONAL_INFO,
+ 0 /* Subblock count */
+ };drivers/isimodem/call-settings.c +11
-0+ + DBG("Attempting to set the CLIR - checking Network Settings"); + + if (cbd == NULL) + goto error; + + if (g_isi_client_send(sd->client, msg, sizeof(msg), + clir_set_cb, cbd, g_free)) + + return; + elsegoto error;
+ }
+ break;
+case(OFONO_CLIR_OPTION_SUPPRESSION): /* CLIR disabled (number shown) */
+ result =set_clir_status("OFONO_CLIR_OPTION_SUPPRESSION");
+ break;
+ default:
+DBG("CLIR mode not supported %d", mode);
+ break;
+ }drivers/isimodem/call-settings.c +39
-0+ + if (result == EXIT_FAILURE) + goto error; + + DBG("CLIR set to mode: %d", mode); + CALLBACK_WITH_SUCCESS(cb, data); + goto out; +error: + CALLBACK_WITH_FAILURE(cb, data); +out: + g_free(cbd); + return; +} + +static void clir_query_cb (const GIsiMessage *msg,void *data) +{ + GIsiSubBlockIter iter, iter_info; + struct isi_cb_data *cbd = data; + ofono_call_settings_clir_cb_t cb = cbd->cb; + uint8_t service; + gint override = OFONO_CLIR_OPTION_DEFAULT; + gint network = CLIR_STATUS_UNKNOWN; + + + if (!check_response_status(msg, SS_SERVICE_COMPLETED_RESP)) + goto error; + + if (!g_isi_msg_data_get_byte(msg, 0, &service) || + service != SS_INTERROGATION) + goto error; + + for (g_isi_sb_iter_init(&iter, msg, 6); + g_isi_sb_iter_is_valid(&iter); + g_isi_sb_iter_next(&iter)) { + DBG("Sub-block %s", + ss_subblock_name(g_isi_sb_iter_get_id(&iter))); + switch (g_isi_sb_iter_get_id(&iter)) { + case SS_STATUS_RESULT: { + guint8 ss_status;
drivers/isimodem/call-settings.c static void query_resp_cb(const GIsiMessage *msg, void *data) · line 483
Quoted 10 lines
drivers/isimodem/call-settings.c +10
-0+ + if (!g_isi_sb_iter_get_byte(&iter, &ss_status, 2)) + goto error; + + DBG("SS_STATUS_RESULT=%d", ss_status); + + if (!(ss_status & SS_GSM_PROVISIONED)) + network = CLIR_STATUS_NOT_PROVISIONED; + } + break;
Indentation is broken here. Why is the break outside the brackets anyway?
Quoted 85 lines
+ case
SS_GSM_ADDITIONAL_INFO:
+ break;
+ caseSS_GSM_GENERIC_SERVICE_INFO: {
+ guint8ss_status= 0;
+ guint8clir_option= 0;
+ void *info = NULL;
+ GIsiMessageinfo_msg;drivers/isimodem/call-settings.c +78
-0+ + if (!g_isi_sb_iter_get_byte(&iter, &ss_status, 2)) + goto error; + + if (!(ss_status & SS_GSM_PROVISIONED)) + network = CLIR_STATUS_NOT_PROVISIONED; + + if (!g_isi_sb_iter_get_data(&iter, &info, 4)) + goto error; + + info_msg.addr = NULL; + info_msg.error = 0; + /* GIsiMessage function adds 2 to data pointer and + * removes 2 from len */ + info_msg.data = info - 2; + info_msg.len = msg->len - 6 + 2; + + for (g_isi_sb_iter_init(&iter_info, &info_msg, 0); + g_isi_sb_iter_is_valid(&iter_info); + g_isi_sb_iter_next(&iter_info)) { + uint8_t id = g_isi_sb_iter_get_id(&iter_info); + DBG("Sub-sub-block %d", id); + + switch (id) { + case SS_GSM_CLIR_INFO: { + if (!g_isi_sb_iter_get_byte(&iter_info, + &clir_option, 2)) + goto error; + break; + } + default: + break; + } + + DBG("SS_STATUS_RESULT=%d, CLIR_OPTION=%d", + ss_status, clir_option); + } + + if (network != CLIR_STATUS_NOT_PROVISIONED) { + switch (clir_option) { + case SS_GSM_CLI_PERMANENT: + network = + CLIR_STATUS_PROVISIONED_PERMANENT; + break; + case SS_GSM_DEFAULT_RESTRICTED: + break; + case SS_GSM_CLI_DEFAULT_ALLOWED: + network = + CLIR_STATUS_TEMPORARY_ALLOWED; + break; + case SS_GSM_OVERRIDE_ENABLED: + override = + OFONO_CLIR_OPTION_SUPPRESSION; + break; + case SS_GSM_OVERRIDE_DISABLED: + override = + OFONO_CLIR_OPTION_INVOCATION; + break; + default: + break; + } + } + } + break; + default: + DBG("Skipping sub-block: %s (%zd bytes)", + ss_subblock_name(g_isi_sb_iter_get_id(&iter)), + g_isi_sb_iter_get_len(&iter)); + break; + } + } + /* + * CLIR cannot be activated,registrated in Network, but we can override + * it using local settings - 33GPP TS 24.081 Chapter 2.5 + * we have to read status and pass override parameter to Ofono + */ + + if (network != CLIR_STATUS_NOT_PROVISIONED) {
drivers/isimodem/call-settings.c static void query_resp_cb(const GIsiMessage *msg, void *data) · line 578
Quoted 10 lines
drivers/isimodem/call-settings.c +10
-0+ override = get_clir_status(); + DBG("CLIR mode queried %d\n", override); + } + + DBG("override=%d, network=%d\n", override, network); + CALLBACK_WITH_SUCCESS(cb, override, network, cbd->data); + return; +error: + CALLBACK_WITH_FAILURE(cb, override, network, cbd->data); +}
Same as above; this function needs some refactoring to split the decoding up into several functions.
Cheers,
Aki
PATCH 10/18 isimodem: wgmodem2.5 added to voicecall
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/call.h | 82 ++++++++++++++++- drivers/isimodem/voicecall.c | 218 +++++++++++++++++++++++++++++++++--------- 2 files changed, 253 insertions(+), 47 deletions(-)
drivers/isimodem/call.h +81 -1
@@ -27,6 +27,8 @@ extern "C" {#endif #define PN_CALL 0x01 +#define PN_MODEM_CALL 0xC9 +#define CALL_MODEM_PROP_PRESENT_DEFAULT 0x00enum call_message_id {CALL_CREATE_REQ =0x01 ,
@@ -333,6 +335,7 @@ enum call_subblock {CALL_MODE_CHANGE_INFO =0x36 ,CALL_ADDITIONAL_PARAMS =0x37 ,CALL_DSAC_INFO =0x38 , + CALL_LINE_ID = 0x47, }; enum call_id {
@@ -351,6 +354,10 @@ enum call_id { CALL_ID_ALL = 0xF0, }; +enum call_dtmf_pause_values { +CALL_DTMF_PAUSE_1S =0x01 +}; +enum call_mode {CALL_MODE_EMERGENCY =0x00 ,CALL_MODE_SPEECH =0x01 ,
@@ -369,6 +376,12 @@ enum { CALL_GSM_PRESENTATION_DEFAULT = 0x07, }; +enum call_modem_line_id { +CALL_MODEM_PRESENT_DEFAULT =0x00 , +CALL_MODEM_PRESENT_ALLOWED =0x01 , +CALL_MODEM_PRESENT_RESTRICTED =0x02 +}; +enum call_operation {CALL_OP_HOLD =0x01 ,CALL_OP_RETRIEVE =0x02 ,
@@ -402,9 +415,76 @@ enum { CALL_DTMF_DISABLE_TONE_IND_SEND = 0x02, }; +enum call_notification_indicator { +CALL_NOTIFY_USER_SUSPENDED =0x00 , +CALL_NOTIFY_USER_RESUMED =0x01 , +CALL_NOTIFY_BEARER_CHANGE =0x02 +}; + +enum call_mmi_ss_codes { +CALL_SSC_ALL_FWDS =0x0002 , +CALL_SSC_ALL_COND_FWD =0x0004 , +CALL_SSC_CFU =0x0015 , +CALL_SSC_CFB =0x0043 , +CALL_SSC_CFNRY =0x003D , +CALL_SSC_CFGNC =0x003E , +CALL_SSC_OUTGOING_BARR_SERV =0x014D , +CALL_SSC_INCOMING_BARR_SERV =0x0161 , +CALL_SSC_CALL_WAITING =0x002B , +CALL_SSC_CLIR =0x001F , +CALL_SSC_ETC =0x0060 , +CALL_SSC_MPTY =0xFFFE , +CALL_SSC_CALL_HOLD =0xFFFF +}; + +enum call_ss_status { +CALL_SS_STATUS_ACTIVE =0x01 , +CALL_SS_STATUS_REGISTERED =0x02 , +CALL_SS_STATUS_PROVISIONED =0x04 , +CALL_SS_STATUS_QUIESCENT =0x08 +}; + +enum call_ss_notification { +CALL_SSN_INCOMING_IS_FWD =0x01 , +CALL_SSN_INCOMING_FWD =0x02 , +CALL_SSN_OUTGOING_FWD =0x04 +}; + +enum call_ss_indicator { +CALL_SSI_CALL_IS_WAITING =0x01 , +CALL_SSI_MPTY =0x02 , +CALL_SSI_CLIR_SUPPR_REJ =0x04 +}; + +enum call_ss_hold_indicator { +CALL_HOLD_IND_RETRIEVED =0x00 , +CALL_HOLD_IND_ON_HOLD =0x01 +}; + +enum call_ss_ect_indicator { +CALL_ECT_CALL_STATE_ALERT =0x00 , +CALL_ECT_CALL_STATE_ACTIVE =0x01 +}; + +enum call_notification_sb_values { +CALL_SB_NOTIFY =0xB1 , +CALL_SB_SS_NOTIFY =0xB2 , +CALL_SB_SS_CODE =0xB3 , +CALL_SB_SS_STATUS =0xB4 , +CALL_SB_SS_NOTIFY_INDICATOR =0xB5 , +CALL_SB_SS_HOLD_INDICATOR =0xB6 , +CALL_SB_SS_ECT_INDICATOR =0xB7 , +CALL_SB_REMOTE_ADDRESS =0xA6 , +CALL_SB_REMOTE_SUBADDRESS =0xA7 , +CALL_SB_CUG_INFO =0xA0 , +CALL_SB_ORIGIN_INFO =0x0E , +CALL_SB_ALERTING_PATTERN =0xA1 , +CALL_SB_ALERTING_INFO =0x0C +}; +/* 27.007 Section 7.7 */ enum clir_status { -CLIR_STATUS_NOT_PROVISIONED =0 , +CLIR_STATUS_NOT_PROVISIONED =0 ,CLIR_STATUS_PROVISIONED_PERMANENT ,CLIR_STATUS_UNKNOWN ,CLIR_STATUS_TEMPORARY_RESTRICTED ,
drivers/isimodem/voicecall.c +172 -46
325 lines not on this page · raw message
Signature · 1 line
1.7.3.5
PATCH 11/18 isimodem: gprs-context updates wgmodem2.5
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/gprs-context.c | 95 +++++++++++++++++++++++++------------- 1 files changed, 62 insertions(+), 33 deletions(-)
drivers/isimodem/gprs-context.c +62 -33
@@ -347,32 +347,52 @@ static void send_context_authenticate(GIsiClient *client, void *opaque)struct context_data *cd = opaque;size_t username_len =strlen (cd->username);size_t password_len =strlen (cd->password); +size_t sb_user_info_len = (3 + username_len +3 ) & ~3 ; +size_t fill_sb_user_info_count = + sb_user_info_len - (3 + username_len); +uint8_t *fill_sb_user_info_data = +g_try_malloc0 (fill_sb_user_info_count); +size_t sb_password_info_len = (3 + password_len +3 ) & ~3 ; +size_t fill_sb_password_info_count = + sb_user_info_len - (3 + password_len); +uint8_t *fill_sb_password_info_data = +g_try_malloc0 (fill_sb_password_info_count);const unsigned char top[] = {GPDS_CONTEXT_AUTH_REQ , cd->handle,2 ,/* sub blocks */ GPDS_USER_NAME_INFO , -3 + username_len +3 , + sb_user_info_len, username_len,/* Username goes here */ };const unsigned char bottom[] = {GPDS_PASSWORD_INFO , -3 + password_len +3 , + sb_password_info_len, password_len,/* Password goes here */ }; -const struct iovec iov[4 ] = { - { (uint8_t *) top,sizeof (top) }, +const struct iovec iov[6 ] = { + { (uint8_t *)top,sizeof (top) }, { cd->username, username_len }, - { (uint8_t *) bottom,sizeof (bottom) }, + { fill_sb_user_info_data, fill_sb_user_info_count }, + { (uint8_t *)bottom,sizeof (bottom) }, { cd->password, password_len }, + { fill_sb_password_info_data, fill_sb_password_info_count}, }; -if (!g_isi_client_vsend (client, iov,4 , context_auth_cb, cd,NULL )) +if (fill_sb_user_info_data ==NULL + && fill_sb_user_info_count >0 ) +gprs_up_fail (cd); + +if (fill_sb_password_info_data ==NULL + && fill_sb_password_info_count >0 ) +gprs_up_fail (cd); + +if (!g_isi_client_vsend (client, iov,6 , context_auth_cb, cd,NULL ))gprs_up_fail (cd); }
@@ -393,34 +413,43 @@ static void link_conf_cb(const GIsiMessage *msg, void *opaque) {struct context_data *cd = opaque;size_t apn_len =strlen (cd->apn); +size_t sb_apn_info_len = (3 + apn_len +3 ) & ~3 ; +size_t fill_count = sb_apn_info_len - (3 + apn_len); +uint8_t *fill_data =g_try_malloc0 (fill_count); + +if (fill_data ==NULL && fill_count >0 ) +return gprs_up_fail (cd); + +if (check_resp (msg,GPDS_LL_CONFIGURE_RESP ,2 , cd, gprs_up_fail)) { + +const unsigned char msg[] = { +GPDS_CONTEXT_CONFIGURE_REQ , + cd->handle,/* context ID */ + cd->type,/* PDP type */ +GPDS_CONT_TYPE_NORMAL , + cd->handle,/* primary context ID */ +0x00 ,/* filler */ +2 ,/* sub blocks */ +GPDS_DNS_ADDRESS_REQ_INFO , +4 ,/* subblock length */ +0 ,0 ,/* padding */ +GPDS_APN_INFO , + sb_apn_info_len, + apn_len, + }; + +const struct iovec iov[3 ] = { + { (uint8_t *)msg,sizeof (msg) }, + { cd->apn, apn_len }, + { fill_data, fill_count} + }; + +if (!g_isi_client_vsend_with_timeout (cd->client, iov,3 , +GPDS_TIMEOUT , context_conf_cb, cd,NULL )) +return gprs_up_fail (cd); + }else +return gprs_up_fail (cd); -const unsigned char req[] = { -GPDS_CONTEXT_CONFIGURE_REQ , - cd->handle,/* context ID */ - cd->type,/* PDP type */ -GPDS_CONT_TYPE_NORMAL , - cd->handle,/* primary context ID */ -0x00 ,/* filler */ -2 ,/* sub blocks */ -GPDS_DNS_ADDRESS_REQ_INFO , -4 ,/* subblock length */ -0 ,0 ,/* padding */ -GPDS_APN_INFO , -3 + apn_len +3 , - apn_len, - }; - -const struct iovec iov[2 ] = { - { (uint8_t *) req,sizeof (req) }, - { cd->apn, apn_len }, - }; - -if (!check_resp (msg,GPDS_LL_CONFIGURE_RESP ,2 , cd, gprs_up_fail)) -return ; - -if (!g_isi_client_vsend (cd->client, iov,2 , - context_conf_cb, cd,NULL )) -gprs_up_fail (cd); }static void create_context_cb (const GIsiMessage *msg,void *opaque)
Signature · 1 line
1.7.3.5
Re: [PATCH 11/18] isimodem: gprs-context updates wgmodem2.5
Hi,
2011/2/15 Andreas Westin <[email protected]>:
Quoted 12 lines
From: Jessica Nilsson <[email protected]>
---
drivers/isimodem/gprs-context.c | 95 +++++++++++++++++++++++++-------------1 files changed, 62 insertions(+), 33 deletions(-)drivers/isimodem/gprs-context.c +0
-0@@ -347,32 +347,52 @@ static void send_context_authenticate(GIsiClient *client, void *opaque) struct context_data *cd = opaque;
drivers/isimodem/gprs-context.c static void send_context_authenticate(GIsiClient *client, void *opaque) · line 357
Quoted 10 lines
drivers/isimodem/gprs-context.c +8
-0size_t username_len = strlen(cd->username); size_t password_len = strlen(cd->password); + size_t sb_user_info_len = (3 + username_len + 3) & ~3; + size_t fill_sb_user_info_count = + sb_user_info_len - (3 + username_len); + uint8_t *fill_sb_user_info_data = + g_try_malloc0(fill_sb_user_info_count); + size_t sb_password_info_len = (3 + password_len + 3) & ~3; + size_t fill_sb_password_info_count = + sb_user_info_len - (3 + password_len);
This should be sb_password_info_len, no?
drivers/isimodem/gprs-context.c static void send_context_authenticate(GIsiClient *client, void *opaque) · line 359
Quoted 2 lines
drivers/isimodem/gprs-context.c +2
-0+ uint8_t *fill_sb_password_info_data = + g_try_malloc0(fill_sb_password_info_count);
There's no reason to allocate the padding from heap. (Especially if they're never freed.)
I applied this patch, but fixed the above issues afterwards. Please check that it's still doing the right thing.
Cheers,
Aki
PATCH 12/18 isimodem: wgmodem2.5 support in USSD
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/ussd.c | 36 ++++++++++++++++++++++++++++++------ 1 files changed, 30 insertions(+), 6 deletions(-)
drivers/isimodem/ussd.c +30 -6
@@ -166,7 +166,11 @@ static void isi_request(struct ofono_ussd *ussd, int dcs, { struct ussd_data *ud = ofono_ussd_get_data(ussd); struct isi_cb_data *cbd = isi_cb_data_new(ussd, cb, data); - const uint8_t msg[] = { + const uint8_t padding_bytes[] = {0, 0, 0, 0, 0, 0, 0, 0}; + GIsiModem *modem; + uint8_t iov_size = 2; + + uint8_t msg[] = { SS_GSM_USSD_SEND_REQ, ud->mt_session ? SS_GSM_USSD_MT_REPLY
@@ -178,15 +182,34 @@ static void isi_request(struct ofono_ussd *ussd, int dcs, len, /* string length *//* USSD string goes here */ }; -const struct iovec iov[2 ] = { - { (uint8_t *) msg,sizeof (msg) }, - { (uint8_t *) pdu, len } - }; +struct iovec iov[3 ] = { {0 ,0 }, {0 ,0 }, {0 ,0 } };if (cbd ==NULL || ud ==NULL ) goto error; -if (g_isi_client_vsend (ud->client, iov,2 , + modem =g_isi_client_modem (ud->client); + +if (g_isi_modem_version_major (modem) ==2 && +g_isi_modem_version_minor (modem) >=0 ) { +uint8_t filled_len = (4 + len +3 ) & ~3 ; +struct iovec t_iov[3 ] = { + { (uint8_t *) msg,sizeof (msg) }, + { (uint8_t *)pdu, len }, + { (uint8_t *) padding_bytes, (filled_len - len -4 ) } + }; + iov_size =3 ; +memmove (iov, t_iov,sizeof (struct iovec ) * iov_size); + + msg[4 ] = filled_len; + }else { +struct iovec t_iov[2 ] = { + { (uint8_t *) msg,sizeof (msg) }, + { (uint8_t *) pdu, len } + }; +memmove (iov, t_iov,sizeof (struct iovec ) * iov_size); + } + +if (g_isi_client_vsend (ud->client, iov, iov_size, ussd_send_resp_cb, cbd, g_free))return ;
@@ -241,6 +264,7 @@ static int isi_ussd_probe(struct ofono_ussd *ussd, unsigned int vendor,struct ussd_data *ud; ud = g_try_new0(struct ussd_data, 1); +if (ud ==NULL )return -ENOMEM ;
Signature · 1 line
1.7.3.5
PATCH 13/18 isimodem: SS_GSM_BARRING_INFO added
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
SS_GSM_BSC_INFO added.
--- drivers/isimodem/call-barring.c | 99 ++++++++++++++++++++++++++++++++++---- 1 files changed, 88 insertions(+), 11 deletions(-)
drivers/isimodem/call-barring.c +88 -11
@@ -190,6 +190,40 @@ static void update_status_mask(unsigned int *mask, int bsc) } } +static gboolean decode_gsm_barring_info (const void *restrict data,size_t len, +guint32 *mask) +{ +GIsiSubBlockIter iter; + +for (g_isi_sb_iter_init (&iter, data,0 ); +g_isi_sb_iter_is_valid (&iter); +g_isi_sb_iter_next (&iter)) { +switch (g_isi_sb_iter_get_id (&iter)) { +case SS_GSM_BARRING_FEATURE : { +uint8_t status; +uint8_t bsc; + +if (!g_isi_sb_iter_get_byte (&iter, &bsc,2 ) || + !g_isi_sb_iter_get_byte (&iter, &status, +3 )) +return FALSE; + +if (status &SS_GSM_ACTIVE ) +update_status_mask (mask, bsc); + +break ; + } +default : +DBG ("Skipping sub-block: %s (%zd bytes)" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter)), +g_isi_sb_iter_get_len (&iter)); +break ; + } + } + +return TRUE; +} +static void query_resp_cb (const GIsiMessage *msg,void *data) {struct isi_cb_data *cbd = data;
@@ -197,9 +231,6 @@ static void query_resp_cb(const GIsiMessage *msg, void *data)GIsiSubBlockIter iter;uint32_t mask =0 ;uint8_t type; -uint8_t count =0 ; -uint8_t bsc =0 ; -uint8_t i;if (!check_response_status (msg,SS_SERVICE_COMPLETED_RESP )) goto error;
@@ -214,18 +245,65 @@ static void query_resp_cb(const GIsiMessage *msg, void *data)g_isi_sb_iter_is_valid (&iter); g_isi_sb_iter_next(&iter)) { -if (g_isi_sb_iter_get_id (&iter) !=SS_GSM_BSC_INFO ) -continue ; +switch (g_isi_sb_iter_get_id (&iter)) { -if (!g_isi_sb_iter_get_byte (&iter, &count,2 )) - goto error; +case SS_STATUS_RESULT : { +guint8 ss_status; -for (i =0 ; i < count; i++) { +if (!g_isi_sb_iter_get_byte (&iter, &ss_status,2 )) + goto error; + +DBG ("SS_STATUS_RESULT=%d" , ss_status); -if (!g_isi_sb_iter_get_byte (&iter, &bsc,3 + i)) +if (ss_status &SS_GSM_ACTIVE ) + mask =1 ; + +break ; + } + +case SS_GSM_BARRING_INFO : { +void *info =NULL ; +size_t infolen; + +if (!g_isi_sb_iter_get_data (&iter, &info,4 )) + goto error; + + infolen =g_isi_sb_iter_get_len (&iter) -4 ; + +if (!decode_gsm_barring_info (info, infolen, &mask)) + goto error; + +break ; + } + +case SS_GSM_BSC_INFO : { + +guint8 count =0 ; +guint8 i; + +if (!g_isi_sb_iter_get_byte (&iter, &count,2 )) goto error; -update_status_mask (&mask, bsc); +for (i =0 ; i < count; i++) { + +guint8 bsc =0 ; + +if (!g_isi_sb_iter_get_byte (&iter, &bsc,3 + i)) + goto error; + +update_status_mask (&mask, bsc); + } +break ; + } + +case SS_GSM_ADDITIONAL_INFO : +break ; + +default : +DBG ("Skipping sub-block: %s (%zd bytes)" , +ss_subblock_name (g_isi_sb_iter_get_id (&iter)), +g_isi_sb_iter_get_len (&iter)); +break ; } }
@@ -342,7 +420,6 @@ static void reachable_cb(const GIsiMessage *msg, void *data)ofono_call_barring_register (barr); } -static int isi_call_barring_probe (struct ofono_call_barring *barr,unsigned int vendor,void *user) {
Signature · 1 line
1.7.3.5
PATCH 14/18 isimodem: wgmodem2.5 added to call-forwarding
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/call-forwarding.c | 31 +++++++++++++++++++++++++++---- 1 files changed, 27 insertions(+), 4 deletions(-)
drivers/isimodem/call-forwarding.c +27 -4
@@ -212,6 +212,7 @@ static void isi_registration(struct ofono_call_forwarding *cf, int type,int ss_code;int num_filler;char *ucs2 =NULL ; +GIsiModem *modem;unsigned char msg[100 ] = {SS_SERVICE_REQ ,
@@ -230,11 +231,17 @@ static void isi_registration(struct ofono_call_forwarding *cf, int type,/* Followed by number in UCS-2, zero sub address bytes, and 0 * to 3 bytes of filler */ -DBG ("forwarding type %d class %d\n" , type, cls);if (cbd ==NULL || fd ==NULL ||strlen (number->number) >28 ) goto error; +DBG ("forwarding type %d class %d\n" , type, cls); + modem =g_isi_client_modem (fd->client); + +if (g_isi_modem_version_major (modem) ==2 && +g_isi_modem_version_minor (modem) >=0 ) + msg[10 ] =SS_UNDEFINED_TIME ; + ss_code =forw_type_to_isi_code (type);if (ss_code <0 ) goto error;
@@ -248,6 +255,10 @@ static void isi_registration(struct ofono_call_forwarding *cf, int type, msg[8 ] =6 +2 *strlen (number->number) + num_filler; +/* Time must not be set for any other than NoReply for ISI2.5 */ +if (ss_code ==SS_GSM_FORW_NO_REPLY ) + msg[10 ] = time; + ucs2 =g_convert (number->number,strlen (number->number),"UCS-2BE" ,"UTF-8//TRANSLIT" ,NULL ,NULL ,NULL );if (ucs2 ==NULL )
@@ -330,10 +341,12 @@ error:static void query_resp_cb (const GIsiMessage *msg,void *data) { -struct isi_cb_data *cbd = data;ofono_call_forwarding_query_cb_t cb = cbd->cb; +struct ofono_call_forwarding *cf = cbd->user; +struct forw_data *fd =ofono_call_forwarding_get_data (cf);GIsiSubBlockIter iter; +GIsiModem *modem;struct ofono_call_forwarding_condition list = { .status =0 ,
@@ -366,8 +379,17 @@ static void query_resp_cb(const GIsiMessage *msg, void *data) &number)) goto error; -/* As in 27.007 section 7.11 */ - list.status = status &SS_GSM_ACTIVE ; + modem =g_isi_client_modem (fd->client); + +if (g_isi_modem_version_major (modem) ==2 && +g_isi_modem_version_minor (modem) >=0 ) { + list.status = status & (SS_GSM_ACTIVE | +SS_GSM_REGISTERED | +SS_GSM_PROVISIONED ); + }else { +/* As in 27.007 section 7.11 */ + list.status = status &SS_GSM_ACTIVE ; + } list.time = noreply; list.phone_number.type = ton |0x80 ;
@@ -447,6 +469,7 @@ static int isi_call_forwarding_probe(struct ofono_call_forwarding *cf,return -ENOMEM ; fd->client =g_isi_client_create (modem,PN_SS ); +if (fd->client ==NULL ) {g_free (fd);return -ENOMEM ;
Signature · 1 line
1.7.3.5
PATCH 15/18 isimodem: wgmodem2.5 added to ssn
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/call-forwarding.c | 1 - drivers/isimodem/ssn.c | 382 +++++++++++++++++++++++++++++++++++- 2 files changed, 377 insertions(+), 6 deletions(-)
drivers/isimodem/call-forwarding.c +0 -1
@@ -469,7 +469,6 @@ static int isi_call_forwarding_probe(struct ofono_call_forwarding *cf,return -ENOMEM ; fd->client =g_isi_client_create (modem,PN_SS ); -if (fd->client ==NULL ) {g_free (fd);return -ENOMEM ;
drivers/isimodem/ssn.c +377 -5
419 lines not on this page · raw message
Signature · 1 line
1.7.3.5
PATCH 16/18 isimodem: sms updated with wgmodem2.5
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/debug.c | 56 +++ drivers/isimodem/debug.h | 1 + drivers/isimodem/sms.c | 972 +++++++++++++++++++++++++++++++++++++++------- drivers/isimodem/sms.h | 34 ++ 4 files changed, 927 insertions(+), 136 deletions(-)
drivers/isimodem/debug.c +56 -0
@@ -53,6 +53,7 @@ const char *pn_resource_name(int value)_ (PN_GSS );_ (PN_GPDS );_ (PN_WRAN ); +_ (PN_UICC ); }return "PN_<UNKNOWN>" ; }
@@ -218,6 +219,47 @@ const char *mce_rf_state_name(enum mce_rf_state value)return "MCE_RF<UNKNOWN>" ; } +const char *uicc_message_id_name (enum uicc_message_id value) +{ +switch (value) { +_ (UICC_REQ ); +_ (UICC_RESP ); +_ (UICC_IND ); +_ (UICC_CARD_REQ ); +_ (UICC_CARD_RESP ); +_ (UICC_CARD_IND ); +_ (UICC_APPLICATION_REQ ); +_ (UICC_APPLICATION_RESP ); +_ (UICC_APPLICATION_IND ); +_ (UICC_PIN_REQ ); +_ (UICC_PIN_RESP ); +_ (UICC_PIN_IND ); +_ (UICC_APPL_CMD_REQ ); +_ (UICC_APPL_CMD_RESP ); +_ (UICC_APPL_CMD_IND ); +_ (UICC_CONNECTOR_REQ ); +_ (UICC_CONNECTOR_RESP ); +_ (UICC_CAT_REQ ); +_ (UICC_CAT_RESP ); +_ (UICC_CAT_IND ); +_ (UICC_APDU_REQ ); +_ (UICC_APDU_RESP ); +_ (UICC_APDU_RESET_IND ); +_ (UICC_REFRESH_REQ ); +_ (UICC_REFRESH_RESP ); +_ (UICC_REFRESH_IND ); +_ (UICC_SIMLOCK_REQ ); +_ (UICC_SIMLOCK_RESP ); +_ (UICC_APDU_SAP_REQ ); +_ (UICC_APDU_SAP_RESP ); +_ (UICC_APDU_SAP_IND ); +_ (UICC_PWR_CTRL_REQ ); +_ (UICC_PWR_CTRL_RESP ); +_ (UICC_PWR_CTRL_IND ); + } +return "UICC_<UNKNOWN>" ; +} +const char *uicc_status_name (uint8_t value) {switch (value) {
@@ -403,6 +445,15 @@ const char *sms_message_id_name(enum sms_message_id value)_ (SMS_GSM_CB_ROUTING_RESP );_ (SMS_GSM_CB_ROUTING_NTF );_ (SMS_MESSAGE_SEND_STATUS_IND ); +_ (SMS_SETTINGS_UPDATE_REQ ); +_ (SMS_SETTINGS_UPDATE_RESP ); +_ (SMS_SETTINGS_READ_REQ ); +_ (SMS_SETTINGS_READ_RESP ); +_ (SMS_RECEIVED_MSG_REPORT_REQ ); +_ (SMS_RECEIVED_MSG_REPORT_RESP ); +_ (SMS_RECEIVE_MESSAGE_REQ ); +_ (SMS_RECEIVE_MESSAGE_RESP ); +_ (SMS_RECEIVED_MSG_IND );_ (SMS_COMMON_MESSAGE ); }return "SMS_<UNKNOWN>" ;
@@ -420,6 +471,9 @@ const char *sms_subblock_name(enum sms_subblock value)_ (SMS_GSM_ROUTING );_ (SMS_GSM_CB_MESSAGE );_ (SMS_GSM_TPDU ); +_ (SMS_GSM_TPDU_25 ); +_ (SMS_GSM_ROUTE_INFO ); +_ (SMS_GSM_PARAMETERS );_ (SMS_COMMON_DATA );_ (SMS_ADDRESS ); }
@@ -1224,6 +1278,8 @@ static const char *res_to_name(uint8_t res, uint8_t id)return gss_message_id_name (id);case PN_GPDS :return gpds_message_id_name (id); +case PN_UICC : +return uicc_message_id_name (id); }return "UNKNOWN" ; }
drivers/isimodem/debug.h +1 -0
@@ -48,6 +48,7 @@ const char *mce_message_id_name(enum mce_message_id value);const char *mce_modem_state_name (enum mce_modem_state value);const char *mce_status_info (enum mce_status_info value); +const char *uicc_message_id_name (enum uicc_message_id value);const char *uicc_subblock_name (uint8_t value);const char *uicc_status_name (uint8_t value);
drivers/isimodem/sms.c +836 -136
1,220 lines not on this page · raw message
drivers/isimodem/sms.h +34 -0
@@ -55,6 +55,7 @@ enum sms_isi_cause { };enum sms_isi_cause_type { +SMS_CAUSE_TYPE_COMMON =0x00 ,SMS_CAUSE_TYPE_GSM =0x01 , };
@@ -125,6 +126,15 @@ enum sms_message_id {SMS_GSM_CB_ROUTING_RESP =0x0C ,SMS_GSM_CB_ROUTING_NTF =0x0D ,SMS_MESSAGE_SEND_STATUS_IND =0x22 , +SMS_SETTINGS_UPDATE_REQ =0x30 , +SMS_SETTINGS_UPDATE_RESP =0x31 , +SMS_SETTINGS_READ_REQ =0x32 , +SMS_SETTINGS_READ_RESP =0x33 , +SMS_RECEIVED_MSG_REPORT_REQ =0x3B , +SMS_RECEIVED_MSG_REPORT_RESP =0x3C , +SMS_RECEIVE_MESSAGE_REQ =0x41 , +SMS_RECEIVE_MESSAGE_RESP =0x42 , +SMS_RECEIVED_MSG_IND =0x43 ,SMS_COMMON_MESSAGE =0xF0 };
@@ -138,6 +148,9 @@ enum sms_subblock {SMS_GSM_ROUTING =0x0D ,SMS_GSM_CB_MESSAGE =0x0E ,SMS_GSM_TPDU =0x11 , +SMS_GSM_TPDU_25 =0x001C , +SMS_GSM_ROUTE_INFO =0x0023 , +SMS_GSM_PARAMETERS =0x0031 ,SMS_COMMON_DATA =0x80 , SMS_ADDRESS = 0x82, };
@@ -175,6 +188,7 @@ enum sms_address_type {SMS_UNICODE_ADDRESS =0x00 ,SMS_GSM_0340_ADDRESS =0x01 ,SMS_GSM_0411_ADDRESS =0x02 , +SMS_SMSC_ADDRESS =0x02 }; enum sms_sender_type {
@@ -192,6 +206,26 @@ enum sms_subject_list_type {SMS_CB_NOT_ALLOWED_IDS_LIST =0x01 }; +enum sms_reception_command { +SMS_RECEPTION_ACTIVATE =0x01 , +SMS_RECEPTION_DEACTIVATE =0x02 +}; + +enum sms_reception_status { +SMS_RECEPTION_ACTIVE =0x01 , +SMS_RECEPTION_INACTIVE =0x02 +}; + +enum sms_setting_type { +SMS_SETTING_TYPE_ROUTE =0x02 +}; + +enum sms_route_priority { +SMS_ROUTE_NOT_AVAILABLE =0x00 , +SMS_ROUTE_PRIORITY_1 =0x01 , +SMS_ROUTE_PRIORITY_2 =0x02 +}; +#ifdef __cplusplus };#endif
Signature · 1 line
1.7.3.5
Re: [PATCH 16/18] isimodem: sms updated with wgmodem2.5
Hi,
2011/2/15 Andreas Westin <[email protected]>:
Quoted 56 lines
From: Jessica Nilsson <[email protected]>
---
drivers/isimodem/debug.c | 56 +++
drivers/isimodem/debug.h | 1 +
drivers/isimodem/sms.c | 972 +++++++++++++++++++++++++++++++++++++++-------drivers/isimodem/sms.h| 34 ++4 files changed, 927 insertions(+), 136 deletions(-)drivers/isimodem/debug.c +32
-0@@ -53,6 +53,7 @@ const char *pn_resource_name(int value) _(PN_GSS); _(PN_GPDS); _(PN_WRAN); + _(PN_UICC); } return "PN_<UNKNOWN>"; }@@ -218,6 +219,47 @@ const char *mce_rf_state_name(enum mce_rf_state value) return "MCE_RF<UNKNOWN>"; } +const char *uicc_message_id_name (enum uicc_message_id value) +{ + switch (value) { + _(UICC_REQ); + _(UICC_RESP); + _(UICC_IND); + _(UICC_CARD_REQ); + _(UICC_CARD_RESP); + _(UICC_CARD_IND); + _(UICC_APPLICATION_REQ); + _(UICC_APPLICATION_RESP); + _(UICC_APPLICATION_IND); + _(UICC_PIN_REQ); + _(UICC_PIN_RESP); + _(UICC_PIN_IND); + _(UICC_APPL_CMD_REQ); + _(UICC_APPL_CMD_RESP); + _(UICC_APPL_CMD_IND); + _(UICC_CONNECTOR_REQ); + _(UICC_CONNECTOR_RESP); + _(UICC_CAT_REQ); + _(UICC_CAT_RESP); + _(UICC_CAT_IND); + _(UICC_APDU_REQ); + _(UICC_APDU_RESP); + _(UICC_APDU_RESET_IND); + _(UICC_REFRESH_REQ); + _(UICC_REFRESH_RESP); + _(UICC_REFRESH_IND); + _(UICC_SIMLOCK_REQ); + _(UICC_SIMLOCK_RESP);
drivers/isimodem/debug.c const char *mce_rf_state_name(enum mce_rf_state value) · line 262
Quoted 10 lines
drivers/isimodem/debug.c +10
-0+ _(UICC_APDU_SAP_REQ); + _(UICC_APDU_SAP_RESP); + _(UICC_APDU_SAP_IND); + _(UICC_PWR_CTRL_REQ); + _(UICC_PWR_CTRL_RESP); + _(UICC_PWR_CTRL_IND); + } + return "UICC_<UNKNOWN>"; +} +
This UICC stuff seems to be leftovers form patch 8/18.
(snip)
Quoted 10 lines
drivers/isimodem/debug.c +4
-2@@ -664,28 +1334,44 @@ static int isi_sms_probe(struct ofono_sms *sms, unsigned int vendor, if (sd == NULL) return -ENOMEM; - sd->params.absent = 0xFF; - sd->params.alphalen = 1; /* Includes final UCS2-coded NUL */ + sd->sim_params.absent = 0xFF; + sd->sim_params.alphalen = 1; /* Includes final UCS2-coded NUL */ + + sd->usim_params.indicators = 0xFF;
drivers/isimodem/debug.c static int isi_sms_probe(struct ofono_sms *sms, unsigned int vendor, · line 1349
Quoted 10 lines
drivers/isimodem/debug.c +4
-1+ sd->usim_params.alphalen = 0; /* Includes final UCS2-coded NUL */ + sd->client = g_isi_client_create(modem, PN_SMS); if (sd->client == NULL) goto nomem; - sd->sim = g_isi_client_create(modem, PN_SIM); + sd->sim = g_isi_client_create(modem, PN_UICC); +
After this, the driver will no longer work with N900 or the isimodem plugin.
Cheers,
Aki
Re: [PATCH 16/18] isimodem: sms updated with wgmodem2.5
Hi,
Quoted 63 lines · Aki Niemi
Hi,
2011/2/15 Andreas Westin<[email protected]>:
Quoted 60 lines
From: Jessica Nilsson<[email protected]>
--- drivers/isimodem/debug.c | 56 +++ drivers/isimodem/debug.h | 1 + drivers/isimodem/sms.c | 972 +++++++++++++++++++++++++++++++++++++++------- drivers/isimodem/sms.h | 34 ++ 4 files changed, 927 insertions(+), 136 deletions(-)drivers/isimodem/debug.c +36
-0@@ -53,6 +53,7 @@ const char *pn_resource_name(int value)_ (PN_GSS );_ (PN_GPDS );_ (PN_WRAN ); +_ (PN_UICC ); }return "PN_<UNKNOWN>" ; }@@ -218,6 +219,47 @@ const char *mce_rf_state_name(enum mce_rf_state value)return "MCE_RF<UNKNOWN>" ; } +const char *uicc_message_id_name (enum uicc_message_id value) +{ +switch (value) { +_ (UICC_REQ ); +_ (UICC_RESP ); +_ (UICC_IND ); +_ (UICC_CARD_REQ ); +_ (UICC_CARD_RESP ); +_ (UICC_CARD_IND ); +_ (UICC_APPLICATION_REQ ); +_ (UICC_APPLICATION_RESP ); +_ (UICC_APPLICATION_IND ); +_ (UICC_PIN_REQ ); +_ (UICC_PIN_RESP ); +_ (UICC_PIN_IND ); +_ (UICC_APPL_CMD_REQ ); +_ (UICC_APPL_CMD_RESP ); +_ (UICC_APPL_CMD_IND ); +_ (UICC_CONNECTOR_REQ ); +_ (UICC_CONNECTOR_RESP ); +_ (UICC_CAT_REQ ); +_ (UICC_CAT_RESP ); +_ (UICC_CAT_IND ); +_ (UICC_APDU_REQ ); +_ (UICC_APDU_RESP ); +_ (UICC_APDU_RESET_IND ); +_ (UICC_REFRESH_REQ ); +_ (UICC_REFRESH_RESP ); +_ (UICC_REFRESH_IND ); +_ (UICC_SIMLOCK_REQ ); +_ (UICC_SIMLOCK_RESP ); +_ (UICC_APDU_SAP_REQ ); +_ (UICC_APDU_SAP_RESP ); +_ (UICC_APDU_SAP_IND ); +_ (UICC_PWR_CTRL_REQ );
Quoted 8 lines
drivers/isimodem/debug.c const char *mce_rf_state_name(enum mce_rf_state value) · line 262
Quoted 6 lines
drivers/isimodem/debug.c +6
-0+_ (UICC_PWR_CTRL_RESP ); +_ (UICC_PWR_CTRL_IND ); + } +return "UICC_<UNKNOWN>" ; +} +This UICC stuff seems to be leftovers form patch 8/18.
Well they are related to SMS, debug prints. But yes they are also UICC. Do you want them in patch 8 ?
Quoted 18 lines
Quoted 18 lines
drivers/isimodem/debug.c +6
-2@@ -664,28 +1334,44 @@ static int isi_sms_probe(struct ofono_sms *sms, unsigned int vendor,if (sd ==NULL )return -ENOMEM ; - sd->params.absent =0xFF ; - sd->params.alphalen =1 ;/* Includes final UCS2-coded NUL */ + sd->sim_params.absent =0xFF ; + sd->sim_params.alphalen =1 ;/* Includes final UCS2-coded NUL */ + + sd->usim_params.indicators =0xFF ; + sd->usim_params.alphalen =0 ;/* Includes final UCS2-coded NUL */ + sd->client =g_isi_client_create (modem,PN_SMS );if (sd->client ==NULL ) goto nomem;
Quoted 5 lines
drivers/isimodem/debug.c static int isi_sms_probe(struct ofono_sms *sms, unsigned int vendor, · line 1349
Quoted 3 lines
drivers/isimodem/debug.c +2
-1- sd->sim =g_isi_client_create (modem,PN_SIM ); + sd->sim =g_isi_client_create (modem,PN_UICC ); +After this, the driver will no longer work with N900 or the isimodem plugin.
PN_SIM client is created in the UICC client verify callback if it fails, do we not get a response to that callback even if UICC fails ?
Regards
Andreas
Re: [PATCH 16/18] isimodem: sms updated with wgmodem2.5
Hi Andreas,
2011/2/16 Andreas WESTIN <[email protected]>:
Quoted 4 lines
Quoted 1 line
This UICC stuff seems to be leftovers form patch 8/18.
Well they are related to SMS, debug prints. But yes they are also UICC. Do you want them in patch 8 ?
That would be my preference. That is, a patch to bring in the PN_UICC codepoints and debugs, then separate patches for implementations using those new codepoints.
Quoted 2 lines
PN_SIMclient is created in the UICC client verify callback if it fails, do we not get a response to that callback even if UICC fails ?
Ah, right.
Cheers,
Aki
PATCH 17/18 isimodem: CBS for wgmodem2.5
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
set and clear topics support added
--- drivers/isimodem/cbs.c | 425 +++++++++++++++++++++++++++++++++++++++++----- drivers/isimodem/debug.c | 4 + drivers/isimodem/sms.h | 7 +- 3 files changed, 394 insertions(+), 42 deletions(-)
drivers/isimodem/cbs.c +384 -41
@@ -3,6 +3,7 @@* oFono - Open Source Telephony * * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). +* Copyright (C) ST-Ericsson SA 2011. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
@@ -47,12 +48,15 @@struct cbs_data {GIsiClient *client; +uint8_t subscription_nr; };struct cbs_info {uint8_t pdu[88 ]; }; +GIsiClient *pn_sms_client; +static gboolean check_response_status (const GIsiMessage *msg,uint8_t msgid) {uint8_t cause;
@@ -89,18 +93,299 @@ static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid)return FALSE; } +static void reset_buf (char *buf,char *buf_2,int buf_len) +{ +memset (buf,'\0' , buf_len); +memset (buf_2,'\0' , buf_len); +} + +static int get_topics_len (const char *topics) +{ +int i =0 ; +int k =0 ; +int length =0 ; +char buf[6 ]; +char buf_2[6 ]; + +reset_buf (buf, buf_2,6 ); + +while (*topics !='\0' ) { +if (*topics ==',' ) { +reset_buf (buf, buf_2,6 ); + k =0 ; + length++; + }else if (*topics !=',' && *topics !='-' ) { + buf[k] = *topics; + k++; + }else if (*topics =='-' ) { + topics++; + i++; + k =0 ; + +while (*topics !=',' && *topics !='\0' ) { + buf_2[k] = *topics; + topics++; + i++; + k++; + } + + length = length +atoi (buf_2) -atoi (buf) +1 ; + k =0 ; + } + + topics++; + i++; + } + + topics = topics - i; +return length; +} + +static void parse_topics (const char *topics,gint16 *topics_parsed) +{ +int j =0 ; +int k =0 ; +char buf[6 ]; +char buf_2[6 ]; + +reset_buf (buf, buf_2,6 ); + +while (*topics !='\0' ) { +if (*topics !=',' && *topics !='-' ) { + buf[j] = *topics; + j++; + }else if (*topics =='-' ) { + topics++; + j =0 ; + +while (*topics !=',' && *topics !='\0' ) { + buf_2[j] = *topics; + topics++; + j++; + } + +for (j =0 ; j <= (atoi (buf_2) -atoi (buf)); j++) { + topics_parsed[k] =atoi (buf) + j; + topics_parsed[k] =g_ntohs (topics_parsed[k]); + k++; + } + + j =0 ; + }else if (*topics ==',' ) { + topics_parsed[k] =atoi (buf); + topics_parsed[k] =g_ntohs (topics_parsed[k]); +reset_buf (buf, buf_2,6 ); + j =0 ; + k++; + } + + topics++; + } +} + +static void set_topics_resp_cb (const GIsiMessage *msg,void *data) +{ +struct isi_cb_data *cbd = data; +struct cbs_data *cd =ofono_cbs_get_data (cbd->user); +ofono_cbs_set_cb_t cb = cbd->cb; +uint8_t result; +DBG ("" ); + +if (g_isi_msg_error (msg) <0 ) { +DBG ("Error: %s" ,strerror (-g_isi_msg_error (msg))); +return ; + } + +if (g_isi_msg_data_len (msg) <2 ||g_isi_msg_id (msg) != +SMS_CB_ROUTING_RESP ) + goto error; + +g_isi_msg_data_get_byte (msg,1 , &result); + +if (result !=SMS_OK ) + goto error; + +g_isi_msg_data_get_byte (msg,0 , &cd->subscription_nr); + +DBG ("got subscription nr: %d" , cd->subscription_nr); + +CALLBACK_WITH_SUCCESS (cb, cbd->data); +return ; +error: +CALLBACK_WITH_FAILURE (cb, cbd->data); +} +static void isi_set_topics (struct ofono_cbs *cbs,const char *topics,ofono_cbs_set_cb_t cb,void *data) { -DBG ("Not implemented (topics=%s), all topics accepted" , topics); -CALLBACK_WITH_SUCCESS (cb, data); +struct cbs_data *cd =ofono_cbs_get_data (cbs); +struct isi_cb_data *cbd =isi_cb_data_new (cbs, cb, data); +int topics_len =get_topics_len (topics); +gint16 topics_out[topics_len]; +GIsiModem *modem; + +uint8_t msg[] = { +SMS_CB_ROUTING_REQ , +SMS_ROUTING_SET , + cd->subscription_nr, +0x00 ,/*Subscription type*/ +0x00 ,/*Fillers*/ +0x00 , +0x01 ,/*Number of subblocks*/ +0x00 , +0x26 ,/*Subblock*/ +0x00 , + topics_len *2 +6 ,/*Subblock length*/ +0x00 , + topics_len,/*Number of topics*/ + }; +struct iovec iov[2 ] = { + { msg,sizeof (msg) }, + { topics_out,sizeof (topics_out) }, + }; + +if (cbd ==NULL ) +return ; + +if (cd ==NULL ) + goto error; + + modem =g_isi_client_modem (cd->client); + +if (g_isi_modem_version_major (modem) ==2 && +g_isi_modem_version_minor (modem) >=0 ) { +parse_topics (topics, topics_out); + +if (g_isi_client_vsend_with_timeout (cd->client, iov,2 , +CBS_TIMEOUT , set_topics_resp_cb, cbd, g_free)) +return ; + +CALLBACK_WITH_FAILURE (cb, data); + }else { +/* +* TODO: This should probably be put first in +* the function to avoid unecessary initialization +* and allocation. Fix when the version handling +* issue has been solved. +*/ +DBG ("Not implemented (topics=%s), all topics accepted" , topics); +CALLBACK_WITH_SUCCESS (cb, data); + } + +error: +g_free (cbd); +} + +static void clear_topics_resp_cb (const GIsiMessage *msg,void *data) +{ +struct isi_cb_data *cbd = data; +struct cbs_data *cd =ofono_cbs_get_data (cbd->user); +ofono_cbs_set_cb_t cb = cbd->cb; +DBG ("" ); + +if (!check_response_status (msg,SMS_CB_ROUTING_RESP )) + goto error; + + cd->subscription_nr =0 ; +CALLBACK_WITH_SUCCESS (cb, cbd->data); +return ; +error: +CALLBACK_WITH_FAILURE (cb, cbd->data); }static void isi_clear_topics (struct ofono_cbs *cbs,ofono_cbs_set_cb_t cb,void *data) { -DBG ("Not implemented" ); -CALLBACK_WITH_SUCCESS (cb, data); +struct cbs_data *cd =ofono_cbs_get_data (cbs); +struct isi_cb_data *cbd =isi_cb_data_new (cbs, cb, data); +GIsiModem *modem; + +uint8_t msg[] = { +SMS_CB_ROUTING_REQ , +SMS_ROUTING_RELEASE , + cd->subscription_nr,/* Subscription number */ +0x00 ,/* Subscription type */ +0x00 ,/* Fillers */ +0x00 , +0x00 /*No subblocks*/ + }; + +if (cbd ==NULL ) +return ; + +if (cd ==NULL ) + goto error; + + modem =g_isi_client_modem (cd->client); + +if (g_isi_modem_version_major (modem) ==2 && +g_isi_modem_version_minor (modem) >=0 ) { +if (g_isi_client_send_with_timeout (cd->client, msg,sizeof (msg), +CBS_TIMEOUT , clear_topics_resp_cb, + cbd, g_free)) +return ; + +CALLBACK_WITH_FAILURE (cb, data); + }else { +/* +* TODO: This should probably be put first in +* the function to avoid unecessary initialization +* and allocation. Fix when the version handling +* issue has been solved. +*/ +DBG ("Not implemented" ); +CALLBACK_WITH_SUCCESS (cb, data); + } +error: +g_free (cbd); +} + +static void routing_ind_cb (const GIsiMessage *msg,void *data) +{ +struct ofono_cbs *cbs = data; +struct cbs_data *cd =ofono_cbs_get_data (cbs); +struct cbs_info info; +size_t len =sizeof (struct cbs_info ); +GIsiSubBlockIter iter; +size_t subblock_len; +uint8_t sbcount; +uint8_t *pdu_data; + +DBG ("" ); + +if (cd ==NULL || !check_response_status (msg,SMS_CB_ROUTING_IND )) +return ; + +g_isi_msg_data_get_byte (msg,1 , &sbcount); + +for (g_isi_sb_iter_init_full (&iter, msg,2 , TRUE, sbcount); +g_isi_sb_iter_is_valid (&iter); +g_isi_sb_iter_next (&iter)) { + +if (g_isi_sb_iter_get_id (&iter) !=SMS_GSM_CB_MESSAGE ) +continue ; + + subblock_len =g_isi_sb_iter_get_len (&iter) -4 ; + +if (subblock_len > len && +g_isi_sb_iter_get_data (&iter, (void **)&pdu_data,4 )) { +unsigned int i; + +for (i =0 ; i < len; i++) { +if (i <6 )/*account for filler in pos 6*/ + info.pdu[i] = pdu_data[i]; +else + info.pdu[i] = pdu_data[i+1 ]; + } + +DBG ("CBS Message received" ); +ofono_cbs_notify (cbs, info.pdu, len); +return ; + }else { +DBG ("Error reading CBS message" ); +return ; + } + } }static void routing_ntf_cb (const GIsiMessage *msg,void *data)
@@ -131,40 +416,71 @@ static void routing_ntf_cb(const GIsiMessage *msg, void *data)static void routing_resp_cb (const GIsiMessage *msg,void *data) {struct ofono_cbs *cbs = data; + +ofono_cbs_register (cbs); +} + +static void reachable_cb (const GIsiMessage *msg,void *data) +{ +struct ofono_cbs *cbs = data;struct cbs_data *cd =ofono_cbs_get_data (cbs); +uint8_t *new_msg; +GIsiModem *modem; -if (cd ==NULL || !check_response_status (msg,SMS_GSM_CB_ROUTING_RESP )) +if (cd ==NULL )return ; -g_isi_client_ntf_subscribe (cd->client,SMS_GSM_CB_ROUTING_NTF , - routing_ntf_cb, cbs); +ISI_VERSION_DBG (msg); + + modem =g_isi_client_modem (cd->client); + +if (g_isi_modem_version_major (modem) ==2 && +g_isi_modem_version_minor (modem) >=0 ) { +uint8_t t_msg[] = { +SMS_CB_ROUTING_REQ , +SMS_ROUTING_QUERY_ALL , +0x00 ,/* New subscription*/ +0x00 ,/* Subscription type */ +0x00 ,/* Fillers */ +0x00 , +0x00 /* No subblocks*/ + }; + new_msg =g_try_malloc0 (sizeof (t_msg)); +memmove (new_msg, t_msg,sizeof (t_msg)); + }else { +uint8_t t_msg[] = { +SMS_GSM_CB_ROUTING_REQ , +SMS_ROUTING_SET , +SMS_GSM_ROUTING_MODE_ALL , +SMS_CB_NOT_ALLOWED_IDS_LIST , +0x00 ,/* Subject count */ +0x00 ,/* Language count */ +0x00 ,/* CB range */ +0x00 ,/* Subject list MSBS */ +0x00 ,/* Subject list LSBS */ +0x00 /* Languages */ + }; + new_msg =g_try_malloc0 (sizeof (t_msg)); +memmove (new_msg, t_msg,sizeof (t_msg)); + } -ofono_cbs_register (cbs); +g_isi_client_send (cd->client, new_msg,sizeof (msg), + routing_resp_cb, cbs,NULL ); + +g_free (new_msg); }static int isi_cbs_probe (struct ofono_cbs *cbs,unsigned int vendor,void *user) {GIsiModem *modem = user; -struct cbs_data *cd; - -const uint8_t msg[] = { -SMS_GSM_CB_ROUTING_REQ , -SMS_ROUTING_SET , -SMS_GSM_ROUTING_MODE_ALL , -SMS_CB_NOT_ALLOWED_IDS_LIST , -0x00 ,/* Subject count */ -0x00 ,/* Language count */ -0x00 ,/* CB range */ -0x00 ,/* Subject list MSBS */ -0x00 ,/* Subject list LSBS */ -0x00 /* Languages */ - }; + struct cbs_data *cd = g_try_new0(struct cbs_data, 1); - cd = g_try_new0(struct cbs_data, 1);if (cd ==NULL )return -ENOMEM ; + cd->subscription_nr =0 ; + cd->client =g_isi_client_create (modem,PN_SMS );if (cd->client ==NULL ) {g_free (cd);
@@ -173,34 +489,60 @@ static int isi_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,ofono_cbs_set_data (cbs, cd); -if (g_isi_client_send (cd->client, msg,sizeof (msg), - routing_resp_cb, cbs,NULL )) -return 0 ; +g_isi_client_ind_subscribe (cd->client,SMS_CB_ROUTING_IND , + routing_ind_cb, cbs); + +g_isi_client_ntf_subscribe (cd->client,SMS_GSM_CB_ROUTING_NTF , + routing_ntf_cb, cbs); -return -errno; +g_isi_client_verify (cd->client, reachable_cb, cbs,NULL ); + +return 0 ; }static void isi_cbs_remove (struct ofono_cbs *cbs) {struct cbs_data *cd =ofono_cbs_get_data (cbs); -const uint8_t msg[] = { -SMS_GSM_CB_ROUTING_REQ , -SMS_ROUTING_RELEASE , -SMS_GSM_ROUTING_MODE_ALL , -SMS_CB_NOT_ALLOWED_IDS_LIST , -0x00 ,/* Subject count */ -0x00 ,/* Language count */ -0x00 ,/* CB range */ -0x00 ,/* Subject list MSBS */ -0x00 ,/* Subject list LSBS */ -0x00 /* Languages */ - }; - -ofono_cbs_set_data (cbs,NULL ); +uint8_t *msg; +GIsiModem *modem;if (cd ==NULL )return ; + modem =g_isi_client_modem (cd->client); + +if (g_isi_modem_version_major (modem) ==2 && +g_isi_modem_version_minor (modem) >=0 ) { +uint8_t t_msg[] = { +SMS_CB_ROUTING_REQ , +SMS_ROUTING_RELEASE , + cd->subscription_nr,/* Subscription number */ +0x00 ,/* Subscription type */ +0x00 ,/* Fillers */ +0x00 , +0x00 /* No subblocks*/ + }; + msg =g_try_malloc0 (sizeof (t_msg)); +memmove (msg, t_msg,sizeof (t_msg)); + }else { +uint8_t t_msg[] = { +SMS_GSM_CB_ROUTING_REQ , +SMS_ROUTING_RELEASE , +SMS_GSM_ROUTING_MODE_ALL , +SMS_CB_NOT_ALLOWED_IDS_LIST , +0x00 ,/* Subject count */ +0x00 ,/* Language count */ +0x00 ,/* CB range */ +0x00 ,/* Subject list MSBS */ +0x00 ,/* Subject list LSBS */ +0x00 /* Languages */ + }; + msg =g_try_malloc0 (sizeof (t_msg)); +memmove (msg, t_msg,sizeof (t_msg)); + } +ofono_cbs_set_data (cbs,NULL ); + +/* * Send a promiscuous routing release, so as not to hog * resources unnecessarily after being removed.
@@ -209,6 +551,7 @@ static void isi_cbs_remove(struct ofono_cbs *cbs)g_isi_client_destroy (cd->client);g_free (cd); +g_free (msg); }static struct ofono_cbs_driver driver = {
drivers/isimodem/debug.c +4 -0
@@ -449,6 +449,9 @@ const char *sms_message_id_name(enum sms_message_id value)_ (SMS_SETTINGS_UPDATE_RESP );_ (SMS_SETTINGS_READ_REQ );_ (SMS_SETTINGS_READ_RESP ); +_ (SMS_CB_ROUTING_REQ ); +_ (SMS_CB_ROUTING_RESP ); +_ (SMS_CB_ROUTING_IND );_ (SMS_RECEIVED_MSG_REPORT_REQ );_ (SMS_RECEIVED_MSG_REPORT_RESP );_ (SMS_RECEIVE_MESSAGE_REQ );
@@ -473,6 +476,7 @@ const char *sms_subblock_name(enum sms_subblock value)_ (SMS_GSM_TPDU );_ (SMS_GSM_TPDU_25 );_ (SMS_GSM_ROUTE_INFO ); +_ (SMS_GSM_CBS_SUBSCRIPTION );_ (SMS_GSM_PARAMETERS );_ (SMS_COMMON_DATA );_ (SMS_ADDRESS );
drivers/isimodem/sms.h +6 -1
@@ -130,6 +130,9 @@ enum sms_message_id {SMS_SETTINGS_UPDATE_RESP =0x31 ,SMS_SETTINGS_READ_REQ =0x32 ,SMS_SETTINGS_READ_RESP =0x33 , +SMS_CB_ROUTING_REQ =0x34 , +SMS_CB_ROUTING_RESP =0x35 , +SMS_CB_ROUTING_IND =0x36 ,SMS_RECEIVED_MSG_REPORT_REQ =0x3B ,SMS_RECEIVED_MSG_REPORT_RESP =0x3C , SMS_RECEIVE_MESSAGE_REQ = 0x41,
@@ -150,6 +153,7 @@ enum sms_subblock {SMS_GSM_TPDU =0x11 ,SMS_GSM_TPDU_25 =0x001C ,SMS_GSM_ROUTE_INFO =0x0023 , +SMS_GSM_CBS_SUBSCRIPTION =0x002D ,SMS_GSM_PARAMETERS =0x0031 ,SMS_COMMON_DATA =0x80 , SMS_ADDRESS = 0x82,
@@ -160,7 +164,8 @@ enum sms_routing_command {SMS_ROUTING_SET =0x01 ,SMS_ROUTING_SUSPEND =0x02 ,SMS_ROUTING_RESUME =0x03 , -SMS_ROUTING_UPDATE =0x04 +SMS_ROUTING_UPDATE =0x04 , +SMS_ROUTING_QUERY_ALL =0x06 }; enum sms_route_preference {
Signature · 1 line
1.7.3.5
Re: [PATCH 17/18] isimodem: CBS for wgmodem2.5
Hi Andreas,
Quoted 80 lines
drivers/isimodem/cbs.c +80
-0+static void reset_buf (char *buf,char *buf_2,int buf_len) +{ +memset (buf,'\0' , buf_len); +memset (buf_2,'\0' , buf_len); +} + +static int get_topics_len (const char *topics) +{ +int i =0 ; +int k =0 ; +int length =0 ; +char buf[6 ]; +char buf_2[6 ]; + +reset_buf (buf, buf_2,6 ); + +while (*topics !='\0' ) { +if (*topics ==',' ) { +reset_buf (buf, buf_2,6 ); + k =0 ; + length++; + }else if (*topics !=',' && *topics !='-' ) { + buf[k] = *topics; + k++; + }else if (*topics =='-' ) { + topics++; + i++; + k =0 ; + +while (*topics !=',' && *topics !='\0' ) { + buf_2[k] = *topics; + topics++; + i++; + k++; + } + + length = length +atoi (buf_2) -atoi (buf) +1 ; + k =0 ; + } + + topics++; + i++; + } + + topics = topics - i; +return length; +} + +static void parse_topics (const char *topics,gint16 *topics_parsed) +{ +int j =0 ; +int k =0 ; +char buf[6 ]; +char buf_2[6 ]; + +reset_buf (buf, buf_2,6 ); + +while (*topics !='\0' ) { +if (*topics !=',' && *topics !='-' ) { + buf[j] = *topics; + j++; + }else if (*topics =='-' ) { + topics++; + j =0 ; + +while (*topics !=',' && *topics !='\0' ) { + buf_2[j] = *topics; + topics++; + j++; + } + +for (j =0 ; j <= (atoi (buf_2) -atoi (buf)); j++) { + topics_parsed[k] =atoi (buf) + j; + topics_parsed[k] =g_ntohs (topics_parsed[k]); + k++; + } + + j =0 ; + }else if (*topics ==',' ) { + topics_parsed[k] =atoi (buf);
drivers/isimodem/cbs.c static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid) · line 185
Quoted 10 lines
drivers/isimodem/cbs.c +10
-0+ topics_parsed[k] =g_ntohs (topics_parsed[k]); +reset_buf (buf, buf_2,6 ); + j =0 ; + k++; + } + + topics++; + } +} +
Have you thought of adapting cbs_extract_topic_ranges function for all of this somehow?
Regards,
-Denis
Re: [PATCH 17/18] isimodem: CBS for wgmodem2.5
Hi Denis,
Quoted 6 lines · Denis Kenzior
Hi Andreas,
Have you thought of adapting
cbs_extract_topic_rangesfunction for all of this somehow?
Yes we are looking at it now.
Cheers
Andreas
PATCH 18/18 isimodem: initial support for UICC phonebook
In reply to Andreas WestinFrom: Jessica Nilsson <[email protected]>
--- drivers/isimodem/phonebook.c | 1241 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 1210 insertions(+), 31 deletions(-)
drivers/isimodem/phonebook.c +1210 -31
@@ -3,6 +3,7 @@* oFono - Open Source Telephony * * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). +* Copyright (C) ST-Ericsson SA 2011. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
@@ -36,16 +37,40 @@#include <ofono/log.h> #include <ofono/modem.h> #include <ofono/phonebook.h> +#include <ofono/sim.h> #include "util.h" #include "isimodem.h" #include "isiutil.h" #include "sim.h" +#include "simutil.h" #include "debug.h" +#include "uicc.h" -struct pb_data { -GIsiClient *client; -}; +/* File info parameters */ +#define FCP_TEMPLATE 0x62 +#define FCP_FILE_SIZE 0x80 +#define FCP_FILE_DESC 0x82 +#define FCP_FILE_ID 0x83 +#define FCP_FILE_LIFECYCLE 0x8A +#define FCP_FILE_SECURITY_ARR 0x8B +#define FCP_FILE_SECURITY_COMPACT 0x8C +#define FCP_FILE_SECURITY_EXPANDED 0xAB + +#define UNUSED 0xFF + +#define EXT1_CP_SUBADDRESS 1 +#define EXT1_ADDITIONAL_DATA 2 + +#define NAME_SIZE 64 +#define NUMBER_SIZE 256 +#define EMAIL_SIZE 128 +#define EXT_NUMBER_SIZE 24 +#define SNE_SIZE 64 + +/* TON (Type Of Number) See TS 24.008 */ +#define TON_MASK 0x70 +#define TON_INTERNATIONAL 0x10struct read_resp {uint8_t service_type;
@@ -53,6 +78,82 @@ struct read_resp {uint8_t data[]; }; +enum constructed_tag { +TYPE_1_TAG =0xA8 , +TYPE_2_TAG =0xA9 , +TYPE_3_TAG =0xAA +}; + +enum file_type_tag { +TYPE_ADN =0xC0 , +TYPE_IAD =0xC1 , +TYPE_EXT1 =0xC2 , +TYPE_SNE =0xC3 , +TYPE_ANR =0xC4 , +TYPE_PBC =0xC5 , +TYPE_GPR =0xC6 , +TYPE_AAS =0xC7 , +TYPE_GAS =0xC8 , +TYPE_UID =0xC9 , +TYPE_EMAIL =0xCA , +TYPE_CCP1 =0xCB +}; + +struct pb_file_info { +int file_id; +uint8_t file_type; +uint8_t structure; +int file_length; +int record_length; +int record; +gboolean handled; +}; + +struct file_info { +int fileid; +int length; +int structure; +int record_length; +unsigned char access[3 ]; +}; + +struct phonebook_entry { +int entry; +char *name; +char *number; +char *email; +char *anr; +char *sne; +}; + +struct pb_data { +GIsiClient *client; +GIsiClient *primary; +GIsiClient *secondary; +struct ofono_sim_driver *sim_func; +gint pb_entry; +struct pb_file_info pb_reference_file_info; +struct pb_file_info *extension_file_info; +uint8_t ext1_to_type; +uint8_t ext1_to_entry; +}; + +static GSList *pb_files; +static GSList *pb_next; + +static GSList *phonebook_entry_start; +static GSList *phonebook_entry_current; + +static void pb_reference_info_cb (const struct ofono_error *error, +int filelength, +enum ofono_sim_file_structure structure, +int recordlength, +const unsigned char access[3 ], +unsigned char file_status,void *data); +static void pb_content_data_read (struct pb_data *pbd, +struct pb_file_info *file_info, +struct isi_cb_data *cbd); +static gboolean parse_adn (GIsiSubBlockIter *iter,uint16_t *location,char **name,char **number) {
@@ -194,6 +295,405 @@ error:return success; } +static void handle_ext1 (struct pb_data *pbd,const unsigned char *msg); + +static void handle_ext1 (struct pb_data *pbd,const unsigned char *msg) +{ +uint8_t number_length =0 , i, next_extension_record; +static const char digit_to_utf8[] ="0123456789*#pwe\0" ; +struct pb_file_info *next_file =NULL ; + +char *ext_number =g_try_malloc0 (EXT_NUMBER_SIZE ); +if (ext_number !=NULL ) { + number_length = msg[1 ]; +for (i =0 ; i < number_length; i++) { + ext_number[2 * i] = digit_to_utf8[msg[2 + i] &0x0f ]; + ext_number[2 * i +1 ] = + digit_to_utf8[(msg[2 + i] >>4 ) & +0x0f ]; + + } + } + next_extension_record = msg[number_length +2 ]; + +DBG ("Number extension %s number length %d extension_record %d" , + ext_number, + number_length, + next_extension_record); + +/* pb_entry is already incremented & g_slist_nth counts from 0 */ +if (pbd->ext1_to_type ==TYPE_ADN ) { +GSList *list_entry =g_slist_nth (phonebook_entry_start, + pbd->ext1_to_entry - +1 ); +DBG ("Looking for ADN entry %d" , pbd->ext1_to_entry); + +if (list_entry !=NULL ) { +struct phonebook_entry *entry = list_entry->data; + +if (entry !=NULL ) +strcat (entry->number, ext_number); +else if (pbd->ext1_to_type ==TYPE_ANR ) { +GSList *list_entry =g_slist_nth ( + phonebook_entry_start, + pbd->ext1_to_entry -1 ); +DBG ("Looking for ANR entry %d" , + pbd->ext1_to_entry); + +if (list_entry !=NULL ) { +struct phonebook_entry *entry = + list_entry->data; + +if (entry !=NULL ) +strcat (entry->anr, ext_number); + } + } +g_free (ext_number); +/* Check if there is more extension data */ +if (next_extension_record !=UNUSED ) { + next_file = g_try_new0(struct pb_file_info, +1 ); + +if (next_file !=NULL ) { +if (pbd->extension_file_info) { +memmove (next_file, + pbd->extension_file_info, +sizeof (struct pb_file_info )); + }else { + next_file->file_type = +TYPE_EXT1 ; + next_file->file_id = +SIM_EFEXT1_FILEID ; + } + next_file->record = + next_extension_record; + } + } + } + } +} + +static struct pb_file_info *decode_read_response ( +struct pb_file_info *file_info, +const unsigned char *msg, +size_t len, +struct ofono_phonebook *pb) +{ +char *name =NULL ; +char *number =NULL ; +char *email =NULL ; +char *sne =NULL ; +char *anr =NULL ; + +static const char digit_to_utf8[] ="0123456789*#pwe\0" ; + +struct pb_file_info *next_file =NULL ; +int type = file_info->file_type; +struct pb_data *pbd =ofono_phonebook_get_data (pb); + +switch (type) { +case TYPE_ADN :{ +const uint8_t name_length = len -14 ; +const uint8_t number_start = name_length; +uint8_t number_length =0 ; +uint8_t extension_record =UNUSED ; +uint8_t i, prefix; + name =sim_string_to_utf8 (msg, name_length); +/* Length contains also TON&NPI */ + number_length = msg[number_start]; + +if ((number_length !=UNUSED ) && (number_length !=0 )) { + number =g_try_malloc0 (NUMBER_SIZE ); + number_length--; + +if (number) { + prefix =0 ; + +if ((msg[number_start +1 ] &TON_MASK ) + ==TON_INTERNATIONAL ) { + number[0 ] ='+' ; + prefix =1 ; + } + +for (i =0 ; i < number_length; i++) { + + number[2 * i + prefix] = + digit_to_utf8[msg + [number_start + +2 + + i] &0x0f ]; + + number[2 * i +1 + prefix] = + digit_to_utf8[(msg + [number_start + +2 + + i] >>4 ) & +0x0f ]; + } + extension_record = msg[len -1 ]; + } + } +DBG ("ADN name %s, number %s number \ +length %d extension_record %d" , + name, number, number_length, extension_record); + +if (extension_record !=UNUSED ) { + next_file = g_try_new0(struct pb_file_info, 1); + +if (next_file !=NULL ) { +if (pbd->extension_file_info) { +memmove (next_file, + pbd-> + extension_file_info, +sizeof (struct +pb_file_info )); + }else { + next_file->file_type = +TYPE_EXT1 ; + next_file->file_id = +SIM_EFEXT1_FILEID ; + } + + next_file->record = extension_record; + pbd->ext1_to_type =TYPE_ADN ; + pbd->ext1_to_entry = pbd->pb_entry; + } + } + +if (name || number) { +struct phonebook_entry *new_entry = + g_try_new0(struct phonebook_entry, 1); + +if (new_entry !=NULL ) { + new_entry->name = name; + new_entry->number = number; + +DBG ("Creating PB entry %d with \ +name %s and number %s" , + pbd->pb_entry, + new_entry->name, + new_entry->number); + + phonebook_entry_current = +g_slist_insert + (phonebook_entry_start, + new_entry, + pbd->pb_entry); + +if (!phonebook_entry_start) + phonebook_entry_start = + phonebook_entry_current; + + pbd->pb_entry++; + } + } +break ; + } +case TYPE_SNE :{ +uint8_t sne_end =0 ; +const uint8_t sne_length = len -2 ; +uint8_t i =0 ; +uint8_t phonebook_entry_nbr = msg[len -1 ]; + +DBG ("SNE" ); +for (i =0 ; (msg[i] !=UNUSED ) && (i < sne_length); + i++) + ; + + sne_end = i; + sne =sim_string_to_utf8 (msg, sne_length); + +if (sne !=NULL ) { +/* +* GSlist nth counts from 0, +* PB entries from 1 +*/ +GSList *list_entry = +g_slist_nth (phonebook_entry_start, + phonebook_entry_nbr - +1 ); + +DBG ("SNE \'%s\' to PB entry %d" , sne, + phonebook_entry_nbr); + +if (list_entry !=NULL ) { +struct phonebook_entry *entry = + list_entry->data; + +if (entry !=NULL ) { +/* +* If one already exists, +* delete it +*/ +if (entry->sne !=NULL ) +g_free (entry->sne); + +DBG ("Adding SNE to entry %d,\ +name %s" , + phonebook_entry_nbr, + entry->name); + + entry->sne = sne; + }else { +g_free (sne); + } + } + } + +break ; + } +case TYPE_ANR :{ +uint8_t number_length =0 ; +uint8_t extension_record =UNUSED ; +uint8_t aas_record =UNUSED ; +uint8_t i, prefix; +uint8_t phonebook_entry_nbr = msg[len -1 ]; +GSList *list_entry; + +DBG ("ANR" ); +if (msg[0 ] ==UNUSED ) +break ; + + aas_record = msg[0 ]; +/* Length contains also TON&NPI */ + number_length = msg[1 ]; + +if (number_length) { + number_length--; + anr =g_try_malloc0 (NUMBER_SIZE ); + +if (anr !=NULL ) { + prefix =0 ; + +if ((msg[2 ] &TON_MASK ) == +TON_INTERNATIONAL ) { + anr[0 ] ='+' ; + prefix =1 ; + } + +for (i =0 ; i < number_length; i++) { + anr[2 * i + prefix] = + digit_to_utf8[ + msg[3 + i] & +0x0f ]; + anr[2 * i +1 + prefix] = + digit_to_utf8[ + (msg[3 + i] >> +4 ) &0x0f ]; + } + + extension_record = msg[len -3 ]; + } + } + +DBG ("ANR to entry %d number %s number length %d\ +extension_record %d aas %d" , + phonebook_entry_nbr, anr, number_length, + extension_record, aas_record); + +if (extension_record !=UNUSED ) { + next_file = g_try_new0(struct pb_file_info, 1); + +if (next_file !=NULL ) { +if (pbd->extension_file_info) { +memmove (next_file, + pbd-> + extension_file_info, +sizeof (struct +pb_file_info )); + }else { + next_file->file_type = +TYPE_EXT1 ; + next_file->file_id = +SIM_EFEXT1_FILEID ; + } + + next_file->record = extension_record; + pbd->ext1_to_type =TYPE_ANR ; + pbd->ext1_to_entry = + phonebook_entry_nbr; + } + } + +/* GSlist nth counts from 0, PB entries from 1 */ + list_entry = +g_slist_nth (phonebook_entry_start, + phonebook_entry_nbr -1 ); + +if (list_entry !=NULL ) { +struct phonebook_entry *entry = + list_entry->data; + +if (entry !=NULL ) { +/* if one already exists, delete it */ +if (entry->anr) +g_free (entry->anr); + +DBG ("Adding ANR to entry %d, name %s" , + phonebook_entry_nbr, + entry->name); + entry->anr = anr; + } + }else { +g_free (anr); + } + +break ; + } +case TYPE_AAS :{ +DBG ("AAS" ); +break ; + } +case TYPE_EMAIL :{ +uint8_t phonebook_entry_nbr = msg[len -1 ]; + email =sim_string_to_utf8 (msg, len -2 ); + +/* GSlist nth counts from 0, PB entries from 1 */ +if (email !=NULL ) { +GSList *list_entry = +g_slist_nth (phonebook_entry_start, + phonebook_entry_nbr -1 ); + +DBG ("Email \'%s\' to PB entry %d" , email, + phonebook_entry_nbr); +if (list_entry !=NULL ) { +struct phonebook_entry *entry = + list_entry->data; + +/* if one already exists, delete it */ +if (entry !=NULL ) { +if (entry->email) +g_free (entry->email); + +DBG ("Adding email to entry %d,\ +name %s" , + phonebook_entry_nbr, + entry->name); + + entry->email = email; + } + }else { +g_free (email); + } + } + +break ; + } +case TYPE_EXT1 :{ +if (msg[0 ] ==EXT1_ADDITIONAL_DATA ) +handle_ext1 (pbd, msg); +break ; + + } +default :{ +DBG ("Skipping type %02X" , type); +break ; + } + } + +return next_file; +} +static void read_next_entry (GIsiClient *client,uint16_t location,GIsiNotifyFunc notify,void *data) {
@@ -254,50 +754,711 @@ static void read_resp_cb(const GIsiMessage *msg, void *data)g_free (cbd); } +struct pb_file_info *extension_file_info; + +static void pb_adn_sim_data_cb (const struct ofono_error *error, +const unsigned char *sdata, +int length,void *data) +{ +struct isi_cb_data *cbd_outer = data; +struct isi_cb_data *cbd =NULL ; +struct pb_file_info *file_info; +struct ofono_phonebook *pb; +ofono_phonebook_cb_t cb; +struct pb_data *pbd; + +if (cbd_outer ==NULL ) + goto out; + + file_info = cbd_outer->user; + cbd = cbd_outer->data; + +if (cbd ==NULL ) + goto out; + + pb = cbd->user; + cb = cbd->cb; + pbd =ofono_phonebook_get_data (pb); + +if (extension_file_info !=NULL ) + file_info = +decode_read_response (extension_file_info, sdata, + length, pb); +else + file_info =decode_read_response (file_info, sdata, length, pb); + +if (file_info !=NULL ) { +DBG ("Reading extension file %04X, record %d" , + file_info->file_id, file_info->record); + pbd->sim_func->read_file_linear (get_sim (), file_info->file_id, + file_info->record, + file_info->record_length, + pb_adn_sim_data_cb, cbd_outer); + +/* Delete if there is a previous one */ +g_free (extension_file_info); + extension_file_info = file_info; +return ; + }else { +g_free (extension_file_info); + extension_file_info =NULL ; + file_info = cbd_outer->user; + +if (file_info->record < + (file_info->file_length / file_info->record_length)) { + + file_info->record++; +DBG ("Same file, next record %d" , file_info->record); + pbd->sim_func->read_file_linear (get_sim (), + file_info->file_id, + file_info->record, + file_info-> + record_length, + pb_adn_sim_data_cb, + cbd_outer); + }else { +GSList *list_entry = +g_slist_nth (phonebook_entry_start,0 ); +DBG ("All data requested, start vCard creation" ); +g_free (file_info); + +while (list_entry !=NULL ) { +struct phonebook_entry *entry = + list_entry->data; + +if (entry !=NULL ) { +DBG ("vCard:\nname=%s\nnumber=%s\n\ +email=%s\nanr=%s\nsne=%s" , + entry->name, entry->number, + entry->email, entry->anr, + entry->sne); + +ofono_phonebook_entry (pb,-1 , + entry->number, +-1 , + entry->name, +-1 , +NULL , + entry->anr,-1 , + entry->sne, + entry->email, +NULL ,NULL ); +g_free (entry->number); +g_free (entry->name); +g_free (entry->anr); +g_free (entry->sne); +g_free (entry->email); +g_free (entry); + } + + list_entry =g_slist_next (list_entry); + } + +g_slist_free (phonebook_entry_start); +g_slist_free (pb_files); +g_free (cbd_outer); +DBG ("Finally all PB data read" ); +CALLBACK_WITH_SUCCESS (cb, cbd->data); + goto out; + } + } + +return ; +out: +g_free (cbd); +} + +static void pb_adn_sim_info_cb (const struct ofono_error *error, +int filelength, +enum ofono_sim_file_structure structure, +int recordlength, +const unsigned char access[3 ], +unsigned char file_status,void *data) +{ +struct isi_cb_data *cbd = data; +struct ofono_phonebook *pb = cbd->user; +ofono_phonebook_cb_t cb = cbd->cb; +struct pb_data *pbd =ofono_phonebook_get_data (pb); +struct pb_file_info *file_info =NULL ; +struct isi_cb_data *cbd_outer; +int records =0 ; + +if (cbd ==NULL ) + goto error; + + pb = cbd->user; + cb = cbd->cb; + pbd =ofono_phonebook_get_data (pb); + file_info =NULL ; + +if (pbd || error->type !=OFONO_ERROR_TYPE_NO_ERROR || + structure !=OFONO_SIM_FILE_STRUCTURE_FIXED || + pbd->sim_func->read_file_linear ==NULL ) + goto error; + + records = filelength / recordlength; + +if (records ==0 ) + goto error; + + file_info = g_try_new0(struct pb_file_info, 1); + +if (file_info ==NULL ) + goto error; + + file_info->file_id =SIM_EFADN_FILEID ; + file_info->file_type =TYPE_ADN ; + file_info->structure = structure; + file_info->file_length = filelength; + file_info->record_length = recordlength; + file_info->record =1 ; +/* Regenerate cbd (include file_info) */ + cbd_outer =isi_cb_data_new (file_info, cb, cbd); + pbd->sim_func->read_file_linear (get_sim (), + file_info->file_id, + file_info->record, + file_info->record_length, + pb_adn_sim_data_cb, cbd_outer); +return ; +error: + +if (cbd !=NULL ) +CALLBACK_WITH_FAILURE (cb, cbd->data); + +g_free (cbd); +} + +static gboolean is_reading_required (uint8_t file_type) +{ +switch (file_type) { +case TYPE_ADN : +case TYPE_EMAIL : +case TYPE_SNE : +case TYPE_ANR : +return TRUE; +default : +return FALSE; + } +} + +static void pb_content_data_cb (const struct ofono_error *error, +const unsigned char *sdata, +int length,void *data) +{ +struct isi_cb_data *cbd = data; +struct ofono_phonebook *pb; +ofono_phonebook_cb_t cb; +struct pb_data *pbd; +struct pb_file_info *file_info =NULL ; + +if (cbd ==NULL ) + goto out; + + pb = cbd->user; + cb = cbd->cb; + pbd =ofono_phonebook_get_data (pb); + +if (extension_file_info !=NULL ) + file_info =decode_read_response (extension_file_info, sdata, + length, pb); +else + file_info = +decode_read_response (pb_next->data, sdata, length, pb); + +if (file_info !=NULL ) { +DBG ("Reading extension file %04X, record %d, structure %d" , + file_info->file_id, file_info->record, + file_info->structure); +pb_content_data_read (pbd, file_info, cbd); +/* Delete if there is a previous one */ +g_free (extension_file_info); + extension_file_info = file_info; +return ; + }else { +g_free (extension_file_info); + extension_file_info =NULL ; + file_info = pb_next->data; + +if (((file_info->structure == +OFONO_SIM_FILE_STRUCTURE_FIXED ) || + (file_info->structure == +OFONO_SIM_FILE_STRUCTURE_CYCLIC )) + && (file_info->record < + (file_info->file_length / file_info->record_length))) { + + file_info->record++; +DBG ("Same file, next record %d" , file_info->record); + }else { +g_free (file_info); + pb_next =g_slist_next (pb_next); +DBG ("Next file in list" ); + +if (pb_next !=NULL ) { + file_info = pb_next->data; + +while ((pb_next !=NULL ) && + (!is_reading_required ( + file_info->file_type))) { +DBG ("Skipping file type %02X" , + file_info->file_type); +g_free (file_info); + pb_next =g_slist_next (pb_next); + +if (pb_next) + file_info = pb_next->data; + } + } + +if (pb_next ==NULL ) { +GSList *list_entry = +g_slist_nth (phonebook_entry_start,0 ); + +DBG ("All data requested, start vCard creation" ); +while (list_entry !=NULL ) { +struct phonebook_entry *entry = + list_entry->data; + +if (entry !=NULL ) { +DBG ("vCard:\nname=%s\n \ +number=%s\nemail=%s\n \ +anr=%s\nsne=%s" , + entry->name, + entry->number, + entry->email, + entry->anr, + entry->sne); + +ofono_phonebook_entry (pb,-1 , + entry->number, +-1 , + entry->name, +-1 , +NULL , + entry->anr, +-1 , + entry->sne, + entry->email, +NULL , +NULL ); + +g_free (entry->number); +g_free (entry->name); +g_free (entry->anr); +g_free (entry->sne); +g_free (entry->email); +g_free (entry); + } + + list_entry =g_slist_next (list_entry); + } + +g_slist_free (phonebook_entry_start); +g_slist_free (pb_files); +DBG ("Finally all PB data read" ); +CALLBACK_WITH_SUCCESS (cb, cbd->data); + goto out; + } + + file_info = pb_next->data; + } + } + +pb_content_data_read (pbd, file_info, cbd); +return ; +out: +g_free (cbd); +} + +static void pb_content_data_read (struct pb_data *pbd, +struct pb_file_info *file_info, +struct isi_cb_data *cbd) +{ +ofono_phonebook_cb_t cb; + +if (pbd ==NULL || file_info ==NULL || cbd ==NULL ) +return ; + + cb = cbd->cb; +DBG ("Reading content of file type=%02X, file ID=%04X, structure=%d" , + file_info->file_type, file_info->file_id, file_info->structure); + +switch (file_info->structure) { +case OFONO_SIM_FILE_STRUCTURE_FIXED : + +if (pbd->sim_func->read_file_linear ==NULL ) + goto error; + + pbd->sim_func->read_file_linear (get_sim (), file_info->file_id, + file_info->record, + file_info->record_length, + pb_content_data_cb, cbd); +break ; +case OFONO_SIM_FILE_STRUCTURE_CYCLIC : + +if (pbd->sim_func->read_file_cyclic ==NULL ) + goto error; + + pbd->sim_func->read_file_cyclic (get_sim (), file_info->file_id, + file_info->record, + file_info->record_length, + pb_content_data_cb, cbd); +break ; +case OFONO_SIM_FILE_STRUCTURE_TRANSPARENT : + +if (pbd->sim_func->read_file_transparent ==NULL ) + goto error; + + pbd->sim_func->read_file_transparent (get_sim (), + file_info->file_id,0 , + file_info->file_length, + pb_content_data_cb, + cbd); +break ; + } + +return ; +error: +if (cbd !=NULL ) +CALLBACK_WITH_FAILURE (cb, cbd->data); + +} + +static void pb_content_info_cb (const struct ofono_error *error, +int filelength, +enum ofono_sim_file_structure structure, +int recordlength, +const unsigned char access[3 ], +unsigned char file_status,void *data) +{ +struct isi_cb_data *cbd = data; +struct ofono_phonebook *pb; +ofono_phonebook_cb_t cb; +struct pb_data *pbd; +struct pb_file_info *file_info =NULL ; + +if (cbd ==NULL ) + goto error; + + pb = cbd->user; + cb = cbd->cb; + pbd =ofono_phonebook_get_data (pb); + +if (pbd ==NULL ) + goto error; + + file_info = pb_next->data; + +if (file_info ==NULL ) + goto error; + + file_info->structure = structure; + file_info->file_length = filelength; + file_info->record_length = recordlength; + file_info->record =1 ; + +DBG ("File type=%02X, File ID=%04X, Struct=%d, File len=%d, Rec len=%d" , + file_info->file_type, file_info->file_id, file_info->structure, + file_info->file_length, file_info->record_length); + +if (file_info->file_type ==TYPE_EXT1 ) +/* Save for quick access */ + pbd->extension_file_info = file_info; + + pb_next =g_slist_next (pb_next); + +if (pb_next ==NULL ) { +DBG ("All info requested, start content reading" ); + +/* Re-start from beginning */ + pb_next =g_slist_nth (pb_files,0 ); + file_info = pb_next->data; + +DBG ("Calling pb_content_data_read pb=%p, list=%p, type=%02X" , + cbd->user, pb_next, file_info->file_type); + +pb_content_data_read (pbd, file_info, cbd); +return ; + } + + file_info = pb_next->data; + +DBG ("Reading next content info %04X" , file_info->file_id); + pbd->sim_func->read_file_info (get_sim (), file_info->file_id, + pb_content_info_cb, cbd); +return ; +error: + +if (cbd !=NULL ) { +DBG ("Error cbd=%p, pbd=%p, file_info=%p" , cbd, pbd, file_info); +CALLBACK_WITH_FAILURE (cb, cbd->data); + } + +g_free (cbd); +} + +static void pb_reference_data_cb (const struct ofono_error *error, +const unsigned char *sdata, +int length,void *data) +{ +struct isi_cb_data *cbd = data; +struct ofono_phonebook *pb; +ofono_phonebook_cb_t cb; +struct pb_data *pbd; +const unsigned char *ptr = sdata; +int typelen =0 ; +int i =0 ; +int file_id =0 ; +gboolean finished = FALSE; + +if (cbd ==NULL ) + goto error; + + pb = cbd->user; + cb = cbd->cb; + +if (cb ==NULL || pb ==NULL ) + goto out; + + pbd =ofono_phonebook_get_data (pb); + +if (pbd ==NULL ) + goto error; + +while ((ptr < sdata + length) && (finished == FALSE)) { +switch (*ptr) { +case TYPE_1_TAG : +case TYPE_2_TAG : +case TYPE_3_TAG : + typelen = *(ptr +1 ); +DBG ("File type=%02X, len=%d" , *ptr, typelen); + ptr +=2 ; + i =0 ; + +while (i < typelen) { +struct pb_file_info *file_info = + g_try_new0(struct pb_file_info, 1); + file_id = (ptr[i +2 ] <<8 ) + ptr[i +3 ]; + +DBG ("creating file info for File type=%02X,\ +File ID=%04X" , + ptr[i], + file_id); + +if (file_info ==NULL ) + goto error; + + file_info->file_type = ptr[i]; + file_info->file_id = file_id; + pb_files = +g_slist_append (pb_files, + (void *)file_info); + i += ptr[i +1 ] +2 ; + } + + ptr += typelen; +break ; +default : +DBG ("All handled %02x" , *ptr); + finished = TRUE; +break ; + } + } + +if (pbd->pb_reference_file_info.record < + (pbd->pb_reference_file_info.file_length / + pbd->pb_reference_file_info.record_length)) { + pbd->pb_reference_file_info.record++; +DBG ("Next EFpbr record %d" , pbd->pb_reference_file_info.record); + pbd->sim_func->read_file_linear (get_sim (), + pbd->pb_reference_file_info. + file_id, + pbd->pb_reference_file_info. + record, + pbd->pb_reference_file_info. + record_length, + pb_reference_data_cb, cbd); + }else { +struct pb_file_info *file_info; +DBG ("All EFpbr records read" ); + pb_next =g_slist_nth (pb_files,0 ); + +if (pb_next ==NULL ) + goto error; + + file_info = pb_next->data; + +if ((file_info ==NULL ) || !pbd->sim_func) + goto error; + + pbd->sim_func->read_file_info (get_sim (), file_info->file_id, + pb_content_info_cb, cbd); + } + +return ; +error: +if (cbd !=NULL ) +CALLBACK_WITH_FAILURE (cb, cbd->data); +out: +g_free (cbd); +} + +static void pb_reference_info_cb (const struct ofono_error *error, +int filelength, +enum ofono_sim_file_structure structure, +int recordlength, +const unsigned char access[3 ], +unsigned char file_status, +void *data) +{ +struct isi_cb_data *cbd = data; +struct ofono_phonebook *pb; +ofono_phonebook_cb_t cb; +struct pb_data *pbd; +int records =0 ; + +if (cbd ==NULL ) + goto error; + + pb = cbd->user; + cb = cbd->cb; + pbd =ofono_phonebook_get_data (pb); + +if (pbd ==NULL ) + goto error; + +if (error->type !=OFONO_ERROR_TYPE_NO_ERROR ) + goto error; + +if (structure !=OFONO_SIM_FILE_STRUCTURE_FIXED ) + goto error; + +if (pbd->sim_func->read_file_linear ==NULL ) + goto error; + + records = filelength / recordlength; + +if (records ==0 ) + goto error; + +DBG ("EFpbr size %d, record length %d, records %d" , + filelength, recordlength, records); + pbd->pb_reference_file_info.file_id =SIM_EFPBR_FILEID ; + pbd->pb_reference_file_info.file_length = filelength; + pbd->pb_reference_file_info.record_length = recordlength; + pbd->pb_reference_file_info.record =1 ;/* Current record, not amount */ + pbd->pb_reference_file_info.structure =OFONO_SIM_FILE_STRUCTURE_FIXED ; + pbd->sim_func->read_file_linear (get_sim (),SIM_EFPBR_FILEID , +1 , recordlength, + pb_reference_data_cb, cbd); +return ; +error: + +if ((cb !=NULL ) && (cbd !=NULL )) +CALLBACK_WITH_FAILURE (cb, cbd->data); + +g_free (cbd); +} +static void isi_export_entries (struct ofono_phonebook *pb,const char *storage,ofono_phonebook_cb_t cb,void *data) {struct pb_data *pbd =ofono_phonebook_get_data (pb);struct isi_cb_data *cbd =isi_cb_data_new (pb, cb, data); -const uint8_t msg[] = { -SIM_PB_REQ_SIM_PB_READ , -SIM_PB_READ , -2 ,/* number of subblocks */ -0 ,SIM_PB_LOCATION ,/* subblock id */ -0 ,8 ,/* subblock size */ -0 ,SIM_PB_ADN , -0xFF ,0xFF ,/* read first entry in pb */ -0 ,SIM_PB_INFO_REQUEST ,/* subblock id */ -0 ,16 ,/* subblock size */ -4 ,/* number of tags */ -0 ,/* filler */ -0 ,SIM_PB_ADN ,/* tags */ -0 ,SIM_PB_SNE , -0 ,SIM_PB_ANR , -0 ,SIM_PB_EMAIL , -0 ,0 /* filler */ - }; -size_t len =sizeof (msg); -if (cbd ==NULL || pbd ==NULL ||strcmp (storage,"SM" ) !=0 ) +if (cbd ==NULL || pbd ==NULL ) goto error; -if (g_isi_client_send (pbd->client, msg, len, read_resp_cb, cbd,NULL )) -return ; - +if (g_isi_client_resource (pbd->client) ==PN_UICC ) { + pbd->pb_entry =1 ; + pb_files =NULL ; + pb_next =NULL ; + phonebook_entry_current =NULL ; + phonebook_entry_start =NULL ; + +switch (get_app_type ()) { +case UICC_APPL_TYPE_ICC_SIM : +DBG ("SIM application" ); + pbd->sim_func->read_file_info (get_sim (), +SIM_EFADN_FILEID , + pb_adn_sim_info_cb, + cbd); +break ; +case UICC_APPL_TYPE_UICC_USIM : +DBG ("USIM application" ); + pbd->sim_func->read_file_info (get_sim (), +SIM_EFPBR_FILEID , + pb_reference_info_cb, + cbd); +break ; +default : +DBG ("UICC application type not unknown or supported" ); + goto error; +break ; + } + }else { + +const uint8_t msg[] = { +SIM_PB_REQ_SIM_PB_READ , +SIM_PB_READ , +2 ,/* number of subblocks */ +0 ,SIM_PB_LOCATION ,/* subblock id */ +0 ,8 ,/* subblock size */ +0 ,SIM_PB_ADN , +0xFF ,0xFF ,/* read first entry in pb */ +0 ,SIM_PB_INFO_REQUEST ,/* subblock id */ +0 ,16 ,/* subblock size */ +4 ,/* number of tags */ +0 ,/* filler */ +0 ,SIM_PB_ADN ,/* tags */ +0 ,SIM_PB_SNE , +0 ,SIM_PB_ANR , +0 ,SIM_PB_EMAIL , +0 ,0 /* filler */ + }; +size_t len =sizeof (msg); + +if (strcmp (storage,"SM" ) !=0 ) + goto error; + +if (g_isi_client_send (pbd->client, msg, len, read_resp_cb, + cbd,NULL )) +return ; + } +return ; error:CALLBACK_WITH_FAILURE (cb, data);g_free (cbd); } -static void reachable_cb (const GIsiMessage *msg,void *data) +static void primary_reachable_cb (const GIsiMessage *msg,void *data) {struct ofono_phonebook *pb = data; +struct pb_data *pd =ofono_phonebook_get_data (pb);if (g_isi_msg_error (msg) <0 )return ;ISI_VERSION_DBG (msg); + pd->client = pd->primary; + +g_isi_client_destroy (pd->secondary); + +ofono_phonebook_register (pb); +} + +static void secondary_reachable_cb (const GIsiMessage *msg,void *data) +{ +struct ofono_phonebook *pb = data; +struct pb_data *pd =ofono_phonebook_get_data (pb); + +if (g_isi_msg_error (msg) <0 ) +return ; + +ISI_VERSION_DBG (msg); + + pd->client = pd->secondary; + +g_isi_client_destroy (pd->primary);ofono_phonebook_register (pb); }
@@ -312,15 +1473,25 @@ static int isi_phonebook_probe(struct ofono_phonebook *pb, unsigned int vendor,if (data ==NULL )return -ENOMEM ; - data->client =g_isi_client_create (modem,PN_SIM ); -if (data->client ==NULL ) { + data->primary =get_pn_uicc_client (modem,PN_UICC ); +if (data->primary ==NULL ) { +g_free (data); +return -ENOMEM ; + } + + data->sim_func =get_sim_driver_func (); + + data->secondary =g_isi_client_create (modem,PN_SIM ); +if (data->secondary ==NULL ) { +g_isi_client_destroy (data->primary);g_free (data);return -ENOMEM ; }ofono_phonebook_set_data (pb, data); -g_isi_client_verify (data->client, reachable_cb, pb,NULL ); +g_isi_client_verify (data->primary, primary_reachable_cb, pb,NULL ); +g_isi_client_verify (data->secondary, secondary_reachable_cb, pb,NULL );return 0 ; }
@@ -329,12 +1500,20 @@ static void isi_phonebook_remove(struct ofono_phonebook *pb) {struct pb_data *data =ofono_phonebook_get_data (pb); + pb_files =NULL ; + pb_next =NULL ; + phonebook_entry_start =NULL ; + phonebook_entry_current =NULL ; +ofono_phonebook_set_data (pb,NULL );if (data ==NULL )return ; +if (g_isi_client_resource (data->client) ==PN_UICC ) +pn_uicc_client_destroy (data->client); +else +g_isi_client_destroy (data->client); -g_isi_client_destroy (data->client);g_free (data); }
Signature · 1 line
1.7.3.5