RE: ConnectionContext on Nokia 6760s-1
Hi Claudio, > Hi, > > We have tried to attach an Nokia 6760s-1, for using it like 3G modem. > Ofono manages correctly the mobile phone creating /isiusb0/ > and /isiusb0/context1 and i think it uses the isi modem driver. > > Next we have activated the pdp context, but it returns the following > dbus exception > > org.ofono.Error.NotAttached GPRS is not attached This basically means that oFono thinks the modem is not attached to the GPRS service. Did you set the modem online before trying this (e.g. by running the online-modem script from the test directory)? > is it possible to use the nokia phone as 3G modem? Should be possible, although it may be that the driver needs minor modifications for 6760. Depends on the ISI interface versions of the modem firmware. If it won't work, you can set the OFONO_ISI_DEBUG and OFONO_ISI_TRACE environment variables to get more verbose logging. We'd need the full log output to check what is going wrong. Br, MikaL ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
Re: [PATCH 3/3] gprs.c: add list contexts for emulator
Hi Bertrand, On 03/22/2011 10:17 AM, Aygon, Bertrand wrote: > Hi Denis, > >>> Thanks Denis for your feedback. >>> The idea behind this code is to propose the complete support of the >>> usual AT+CGDCONT in the emulator. I think the best solution might be to >>> stick on contexts exposed over DBus, but this could lead to problems >>> like : a context is delete throught the DBus interface... how to handle >>> this change in the AT emulator, and avoid the use of the deleted context ? >> >> Personally I'm not convinced CGDCONT management is even a good idea. >> The typical usecase is for DUN clients to send a CGDCONT string, but >> this can simply be accepted and ignored (for instance). > > We are not looking at DUN only, but to the 'global' AT Emulator, that will be > used during GCF/PTCRB certification. I know exactly what you want this for. > During certification, a lot of test require to set some GPRS context with > specific parameters. And this cannot go 'directly' to the modem, without > going through AP, because the test would not be relevant, or worse will > failed, due to disconnect between oFono and modem. > And I know this as well ;) However, I'm still not convinced. oFono simply works differently and you will encounter too many problems doing it this way. I listed some of them out already... >> Just overwriting oFono's context store is not a good idea anyway as you >> lose certain valuable information. For instance whether this context is >> used for internet (and ConnMan should pay attention to it) or it is used >> for mms, etc. >> >> It is also possible for the dial up client to provide context details >> that are identical to a context already defined in oFono. In which case >> those details should be used instead (for the reasons outlined in the >> previous paragraph) > > So from my point of view, all context must be in sync, in oFono side and > modem side. The reality is doing so is pretty much a bad idea from a technical point of view. So sounds like you're in for some fun ;) Regards, -Denis ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
RE: [PATCH 3/3] gprs.c: add list contexts for emulator
Hi Denis, >> Thanks Denis for your feedback. >> The idea behind this code is to propose the complete support of the >> usual AT+CGDCONT in the emulator. I think the best solution might be to >> stick on contexts exposed over DBus, but this could lead to problems >> like : a context is delete throught the DBus interface... how to handle >> this change in the AT emulator, and avoid the use of the deleted context ? > >Personally I'm not convinced CGDCONT management is even a good idea. >The typical usecase is for DUN clients to send a CGDCONT string, but >this can simply be accepted and ignored (for instance). We are not looking at DUN only, but to the 'global' AT Emulator, that will be used during GCF/PTCRB certification. During certification, a lot of test require to set some GPRS context with specific parameters. And this cannot go 'directly' to the modem, without going through AP, because the test would not be relevant, or worse will failed, due to disconnect between oFono and modem. >Just overwriting oFono's context store is not a good idea anyway as you >lose certain valuable information. For instance whether this context is >used for internet (and ConnMan should pay attention to it) or it is used >for mms, etc. > >It is also possible for the dial up client to provide context details >that are identical to a context already defined in oFono. In which case >those details should be used instead (for the reasons outlined in the >previous paragraph) So from my point of view, all context must be in sync, in oFono side and modem side. Regards, Bertrand. - Intel Corporation SAS (French simplified joint stock company) Registered headquarters: "Les Montalets"- 2, rue de Paris, 92196 Meudon Cedex, France Registration Number: 302 456 199 R.C.S. NANTERRE Capital: 4,572,000 Euros This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies. ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
Re: [PATCH 3/3] gprs.c: add list contexts for emulator
Hi Olivier, Gentle reminder not to top-post on this mailing list. On 03/22/2011 05:49 AM, Olivier Guiter wrote: > Thanks Denis for your feedback. > The idea behind this code is to propose the complete support of the > usual AT+CGDCONT in the emulator. I think the best solution might be to > stick on contexts exposed over DBus, but this could lead to problems > like : a context is delete throught the DBus interface... how to handle > this change in the AT emulator, and avoid the use of the deleted context ? Personally I'm not convinced CGDCONT management is even a good idea. The typical usecase is for DUN clients to send a CGDCONT string, but this can simply be accepted and ignored (for instance). Just overwriting oFono's context store is not a good idea anyway as you lose certain valuable information. For instance whether this context is used for internet (and ConnMan should pay attention to it) or it is used for mms, etc. It is also possible for the dial up client to provide context details that are identical to a context already defined in oFono. In which case those details should be used instead (for the reasons outlined in the previous paragraph) Regards, -Denis ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
ConnectionContext on Nokia 6760s-1
Hi, We have tried to attach an Nokia 6760s-1, for using it like 3G modem. Ofono manages correctly the mobile phone creating /isiusb0/ and /isiusb0/context1 and i think it uses the isi modem driver. Next we have activated the pdp context, but it returns the following dbus exception org.ofono.Error.NotAttached GPRS is not attached The log of ofono are: ofonod[2441]: drivers/isimodem/ussd.c:ussd_ind_cb() type: 5 SS_GSM_USSD_END, dcs: 0x0f, len: 125 ofonod[2441]: src/ussd.c:ofono_ussd_notify() status: 2 TERMINATED, state: 0 IDLE ofonod[2441]: drivers/isimodem/ussd.c:ussd_ind_cb() type: 5 SS_GSM_USSD_END, dcs: 0x00, len: 0 ofonod[2441]: src/ussd.c:ofono_ussd_notify() status: 2 TERMINATED, state: 0 IDLE is it possible to use the nokia phone as 3G modem? Note: We attached the phone through usb cable, indicating PC Suite as interaction mode. regs -- claudio Degioanni ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 2/2] simapplication: Add a new SIM applet dedicated to BIP commands
--- src/simapplication.cpp | 161 src/simapplication.h |2 + 2 files changed, 163 insertions(+), 0 deletions(-) diff --git a/src/simapplication.cpp b/src/simapplication.cpp index 14fa8c0..e4e93ae 100644 --- a/src/simapplication.cpp +++ b/src/simapplication.cpp @@ -291,6 +291,7 @@ const QString DemoSimApplication::getName() #define MainMenu_Timers 16 #define MainMenu_Refresh17 #define MainMenu_LocalInfo 18 +#define MainMenu_BIP19 #define SportsMenu_Chess1 #define SportsMenu_Painting 2 @@ -349,6 +350,12 @@ const QString DemoSimApplication::getName() #define LocalInfoMenu_Time 1 #define LocalInfoMenu_Lang 2 +#define BIPMenu_OpenChannel 1 +#define BIPMenu_CloseChannel 2 +#define BIPMenu_ReceiveData 3 +#define BIPMenu_SendData 4 +#define BIPMenu_GetChannelStatus 5 + enum SendSMSMenuItems { SendSMS_Unpacked = 1, SendSMS_Packed, @@ -448,6 +455,10 @@ void DemoSimApplication::mainMenu() item.setLabel( "Provide Local Information" ); items += item; +item.setIdentifier( MainMenu_BIP ); +item.setLabel( "BIP commands" ); +items += item; + cmd.setMenuItems( items ); command( cmd, 0, 0 ); @@ -590,6 +601,12 @@ void DemoSimApplication::mainMenuSelection( int id ) } break; +case MainMenu_BIP: +{ +sendBIPMenu(); +} +break; + default: { // Don't know what this item is, so just re-display the main menu. @@ -2351,3 +2368,147 @@ void DemoSimApplication::localInfoMenu( const QSimTerminalResponse& resp ) endSession(); } } + +void DemoSimApplication::BIPMenu( const QSimTerminalResponse& resp ) +{ +QSimCommand cmd; + +if ( resp.result() == QSimTerminalResponse::Success ) { +switch ( resp.menuItem() ) { + +case BIPMenu_OpenChannel: +{ + QByteArray bearerDesc; + QByteArray uti; + QByteArray destAddress; + QByteArray apn; + + bearerDesc += 0x02; + bearerDesc += 0x03; + bearerDesc += 0x04; + bearerDesc += 0x03; + bearerDesc += 0x04; + bearerDesc += 0x1F; + bearerDesc += 0x02; + + uti += 0x01; + uti += 0xAD; + uti += 0x9C; + + destAddress += 0x21; + destAddress += 0x01; + destAddress += 0x01; + destAddress += 0x01; + destAddress += 0x01; + + apn += 0x06; + apn += 0x54; + apn += 0x65; + apn += 0x73; + apn += 0x74; + apn += 0x47; + apn += 0x70; + apn += 0x02; + apn += 0x72; + apn += 0x73; + + cmd.setType( QSimCommand::OpenChannel ); +cmd.setQualifier( QSimCommand::OpenchannelImmediate ); +cmd.setText("Open ID"); +cmd.setBearerDesc(bearerDesc); +cmd.setBufferSize(1400); +cmd.setApn(apn); +cmd.setUserLogin("UserLog"); +cmd.setUserPassword("UserPwd"); +cmd.setUti(uti); +cmd.setDestAddress(destAddress); +command( cmd, this, SLOT(sendBIPMenu()) ); +} +break; + +case BIPMenu_ReceiveData: +{ + cmd.setType( QSimCommand::ReceiveData ); +cmd.setDestinationDevice( QSimCommand::Channel1 ); +cmd.setText("Receive Data 1"); +cmd.setDataLength(200); +command( cmd, this, SLOT(sendBIPMenu()) ); +} +break; + +case BIPMenu_SendData: +{ + QByteArray data; + + data += 0x01; + data += 0x02; + data += 0x03; + data += 0x04; + data += 0x05; + + cmd.setType( QSimCommand::SendData ); +cmd.setDestinationDevice( QSimCommand::Channel1 ); +cmd.setText("Send Data 1"); +cmd.addExtensionField( 0x36, data ); +command( cmd, this, SLOT(sendBIPMenu()) ); +} +break; + +case BIPMenu_CloseChannel: +{ + cmd.setType( QSimCommand::CloseChannel ); + cmd.setDestinationDevice( QSimCommand::Channel1 ); + cmd.setText("Close ID 1"); + command( cmd, this, SLOT(sendBIPMenu()) ); +} +break; + +case BIPMenu_GetChannelStatus: +{ + cmd.setType( QSimCommand::GetChannelStatus ); + command( cmd, this, SLOT(sendBIPMenu(
[PATCH 1/2] qsimcommand: Add properties and TLV builders to support BIP commands
--- src/qsimcommand.cpp | 201 +-- src/qsimcommand.h | 34 + 2 files changed, 228 insertions(+), 7 deletions(-) diff --git a/src/qsimcommand.cpp b/src/qsimcommand.cpp index ecdf43f..46b633f 100644 --- a/src/qsimcommand.cpp +++ b/src/qsimcommand.cpp @@ -69,6 +69,8 @@ public: timerId = 0; device = -1; qualifier = 0; +bufferSize = 0; +dataLength = 0; } QSimCommandPrivate( QSimCommandPrivate *other ) { @@ -102,6 +104,15 @@ public: device = other->device; qualifier = other->qualifier; extensionData = other->extensionData; +bearerDesc = other->bearerDesc; +bufferSize = other->bufferSize; +dataLength = other->dataLength; +apn = other->apn; +uti = other->uti; +userLogin = other->userLogin; +userPassword = other->userPassword; +destAddress = other->destAddress; +localAddress = other->localAddress; } bool flag( int bit ) const @@ -165,7 +176,15 @@ public: int device; int qualifier; QByteArray extensionData; - +QByteArray bearerDesc; +ushort bufferSize; +uint dataLength; +QByteArray apn; +QByteArray uti; +QString userLogin; +QString userPassword; +QByteArray destAddress; +QByteArray localAddress; }; @@ -612,7 +631,7 @@ QSimMenuItem& QSimMenuItem::operator=( const QSimMenuItem & value ) \enum QSimCommand::Device This enum defines the source or destination device for a SIM command, according to 3GPP TS 11.14, section 12.7. - +\ \value Keypad Keypad device \value Display Display device \value Earpiece Earpiece device @@ -2202,6 +2221,86 @@ void QSimCommand::setTimerId( int id ) dwrite()->timerId = id; } +ushort QSimCommand::bufferSize() const +{ +return d->bufferSize; +} + +void QSimCommand::setBufferSize( ushort value ) +{ +dwrite()->bufferSize = value; +} + +uint QSimCommand::dataLength() const +{ +return d->dataLength; +} + +void QSimCommand::setDataLength( uint value ) +{ +dwrite()->dataLength = value; +} + +QString QSimCommand::userLogin() const +{ +return d->userLogin; +} + +void QSimCommand::setUserLogin( const QString& value ) +{ +dwrite()->userLogin = value; +} + +QString QSimCommand::userPassword() const +{ +return d->userPassword; +} + +void QSimCommand::setUserPassword( const QString& value ) +{ +dwrite()->userPassword = value; +} + +QByteArray QSimCommand::uti() const +{ +return d->uti; +} + +void QSimCommand::setUti( const QByteArray& value ) +{ +dwrite()->uti = value; +} + +QByteArray QSimCommand::bearerDesc() const +{ +return d->bearerDesc; +} + +void QSimCommand::setBearerDesc( const QByteArray& value ) +{ +dwrite()->bearerDesc = value; +} + +QByteArray QSimCommand::destAddress() const +{ +return d->destAddress; +} + +void QSimCommand::setDestAddress( const QByteArray& value ) +{ +dwrite()->destAddress = value; +} + +QByteArray QSimCommand::apn() const +{ +return d->apn; +} + +void QSimCommand::setApn( const QByteArray& value ) +{ +dwrite()->apn = value; +} + /*! Copy the QSimCommand object \a value. */ @@ -3045,6 +3144,62 @@ void _qtopiaphone_writeTimerValue( QByteArray& data, uint value ) } #define writeTimerValue _qtopiaphone_writeTimerValue +// Write a Bearer description field. +static void writeBearerDesc( QByteArray& data, const QByteArray& bearerDesc ) +{ +if ( !bearerDesc.isEmpty() ) { +data += (char)0x35; +writeBerLength( data, bearerDesc.length() ); +data += bearerDesc; +} +} + +// Write a Network Access Name field as specified in TS 23.003 +static void writeApn( QByteArray& data, const QByteArray& apn ) +{ +if ( !apn.isEmpty() ) { + data += (char)0x47; + writeBerLength( data, apn.length() ); + data += apn; +} +} + +// Write a Buffer size field. +static void writeBufferSize( QByteArray& data, ushort size ) +{ + if ( size ) { + data += 0x39; + data += 0x02; + data += (char)(size >> 8); + data += (char)size; + } +} + +// Write a data length field. +static void writeDataLength( QByteArray& data, uint value ) +{ + data += 0x37; + data += 0x01; + data += (char) value; +} + +static void writeUti( QByteArray& data, const QByteArray& uti ) +{ + if ( !uti.isEmpty() ) { + data += (char)0x3C; + writeBerLength( data, uti.length() ); + data += uti; + } +} + +static void writeOtherAddress( QByteArray& data, const QByteArray& otherAddress ) +{ + if ( !otherAddress.isEmpty() ) { + data += (char)0x3E; + writeBerLength( data, otherAddress.length() ); + data += otherAddress; + } +} /*! \enum QSimCommand::ToPduOptions This enu
[PATCH 0/2] Extend Phonesim to support BIP commands
Philippe Nunes (2): qsimcommand: Add properties and TLV builders to support BIP commands simapplication: Add a new SIM applet dedicated to BIP commands src/qsimcommand.cpp| 201 ++-- src/qsimcommand.h | 34 src/simapplication.cpp | 161 ++ src/simapplication.h |2 + 4 files changed, 391 insertions(+), 7 deletions(-) ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 6/6] test-stk-menu: Add support for BIP commands
--- test/test-stk-menu | 22 ++ 1 files changed, 22 insertions(+), 0 deletions(-) diff --git a/test/test-stk-menu b/test/test-stk-menu index 639fe77..85b9a0b 100755 --- a/test/test-stk-menu +++ b/test/test-stk-menu @@ -170,6 +170,18 @@ class StkAgent(dbus.service.Object): return False @dbus.service.method("org.ofono.SimToolkitAgent", + in_signature="sy", out_signature="b") + def ConfirmOpenChannel(self, info, icon): + print "Open channel confirmation: (%s)" % (info) + print "Icon: (%d)" % (icon) + key = raw_input("Enter Confirmation (y, n):") + + if key == 'y': + return True + else: + return False + + @dbus.service.method("org.ofono.SimToolkitAgent", in_signature="", out_signature="") def Cancel(self): print "Cancel" @@ -198,6 +210,16 @@ class StkAgent(dbus.service.Object): print "Text: %s" % (text) print "Icon: %d" % (icon) + @dbus.service.method("org.ofono.SimToolkitAgent", + in_signature="sy", out_signature="") + def DisplayChannelActivity(self, text, icon): + print "Channel activity (%s)" % (text) + print "Icon: (%d)" % (icon) + key = raw_input("Press 't' to terminate the session ") + + if key == 't': + raise EndSession("User wishes to terminate session") + def property_changed(name, value): print "SimToolKit property: %s changed to '%s'" % (name, value) -- 1.7.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 3/6] stk: Introduce BIP command handlers
--- src/stk.c | 307 + 1 files changed, 307 insertions(+), 0 deletions(-) diff --git a/src/stk.c b/src/stk.c index 68b6240..d224360 100644 --- a/src/stk.c +++ b/src/stk.c @@ -79,6 +79,9 @@ struct ofono_stk { __ofono_sms_sim_download_cb_t sms_pp_cb; void *sms_pp_userdata; + struct stk_channel channel; + struct stk_channel_data rx_buffer; + struct stk_channel_data tx_buffer; }; struct envelope_op { @@ -2548,6 +2551,285 @@ static gboolean handle_command_launch_browser(const struct stk_command *cmd, return FALSE; } +static void confirm_open_channel_cb(enum stk_agent_result result, + gboolean confirm, + void *user_data) +{ + struct ofono_stk *stk = user_data; + unsigned char no_cause[] = { 0x00 }; + struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE }; + struct stk_response rsp; + + stk->respond_on_exit = FALSE; + + switch (result) { + case STK_AGENT_RESULT_TERMINATE: + send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED); + return; + + case STK_AGENT_RESULT_TIMEOUT: + confirm = FALSE; + /* Fall through */ + + case STK_AGENT_RESULT_OK: + if (confirm) + break; + /* Fall through */ + + default: + memset(&rsp, 0, sizeof(rsp)); + ADD_ERROR_RESULT(rsp.result, STK_RESULT_TYPE_TERMINAL_BUSY, + no_cause); + + if (stk_respond(stk, &rsp, stk_command_cb)) + stk_command_cb(&failure, stk); + + return; + } + + /* +* TODO +* setup the channel +*/ + + /* For now, return "Command beyond terminal's capabilities" */ + send_simple_response(stk, STK_RESULT_TYPE_NOT_CAPABLE); +} + +static gboolean handle_command_open_channel(const struct stk_command *cmd, + struct stk_response *rsp, + struct ofono_stk *stk) +{ + const struct stk_command_open_channel *oc = &cmd->open_channel; + char *alpha_id; + int err; + + /* Don't ask for user confirmation if AID is a null data object*/ + if (oc->alpha_id && strlen(oc->alpha_id) == 0) { + /* +* TODO +* setup the channel +*/ + + /* For now, return "Command beyond terminal's capabilities" */ + rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE; + return TRUE; + } + + alpha_id = dbus_apply_text_attributes(oc->alpha_id ? oc->alpha_id : "", + &oc->text_attr); + if (alpha_id == NULL) { + rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD; + return TRUE; + } + + err = stk_agent_confirm_open_channel(stk->current_agent, alpha_id, + &oc->icon_id, + confirm_open_channel_cb, + stk, NULL, stk->timeout * 1000); + g_free(alpha_id); + + if (err < 0) { + unsigned char no_cause_result[] = { 0x00 }; + + /* +* We most likely got an out of memory error, tell SIM +* to retry +*/ + ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_TERMINAL_BUSY, + no_cause_result); + return TRUE; + } + + stk->respond_on_exit = TRUE; + stk->cancel_cmd = stk_request_cancel; + + return FALSE; +} + +static void channel_activity_cb(enum stk_agent_result result, void *user_data) +{ + struct ofono_stk *stk = user_data; + + if (result == STK_AGENT_RESULT_TERMINATE) { + stk->respond_on_exit = FALSE; + send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED); + } +} + +static gboolean handle_command_close_channel(const struct stk_command *cmd, + struct stk_response *rsp, + struct ofono_stk *stk) +{ + const struct stk_command_close_channel *cc = &cmd->close_channel; + char *alpha_id; + int err; + + /* +* Don't inform the user about the link closing phase if AID is +* a null data object +* */ + if (cc->alpha_id && strlen(cc->alpha_id) == 0) + goto close; + + alpha_id = dbus_apply_text_attributes(cc->alpha_id ? cc->alpha_id : "", + &cc->text_attr); + if (alpha_id == NULL) { + rsp->result.type = STK
[PATCH 5/6] stkutil: Complete the TLV parsing/builder to support BIP commands
--- src/stkutil.c | 300 + src/stkutil.h | 141 +++ 2 files changed, 402 insertions(+), 39 deletions(-) diff --git a/src/stkutil.c b/src/stkutil.c index c64cb7a..b03dfb4 100644 --- a/src/stkutil.c +++ b/src/stkutil.c @@ -1264,8 +1264,22 @@ static gboolean parse_dataobj_bearer_description( data = comprehension_tlv_iter_get_data(iter); bd->type = data[0]; - bd->len = len - 1; - memcpy(bd->pars, data + 1, bd->len); + + if (bd->type == STK_BEARER_TYPE_GPRS_UTRAN) { + if (len < 7) + return FALSE; + + bd->parameters.gprs.precedence = data[1]; + bd->parameters.gprs.delay = data[2]; + bd->parameters.gprs.reliability = data[3]; + bd->parameters.gprs.peak = data[4]; + bd->parameters.gprs.mean = data[5]; + bd->parameters.gprs.pdp_type = data[6]; + return TRUE; + } + + bd->parameters.other.len = len - 1; + memcpy(bd->parameters.other.pars, data + 1, bd->parameters.other.len); return TRUE; } @@ -1356,7 +1370,11 @@ static gboolean parse_dataobj_other_address( data = comprehension_tlv_iter_get_data(iter); oa->type = data[0]; - memcpy(&oa->addr, data + 1, len - 1); + + if (oa->type == STK_ADDRESS_IPV4) + memcpy(&oa->addr.ipv4, data + 1, 4); + else + memcpy(&oa->addr.ipv6, data + 1, 16); return TRUE; } @@ -1604,16 +1622,33 @@ static gboolean parse_dataobj_esn(struct comprehension_tlv_iter *iter, static gboolean parse_dataobj_network_access_name( struct comprehension_tlv_iter *iter, void *user) { - struct stk_network_access_name *nan = user; + struct stk_network_access_name *apn = user; const unsigned char *data; unsigned int len = comprehension_tlv_iter_get_length(iter); + size_t label_size; - if (len == 0) + if ((len == 0) || (len > 100)) return FALSE; data = comprehension_tlv_iter_get_data(iter); - nan->len = len; - memcpy(nan->name, data, len); + /* +* As specified in TS 23 003 Section 9 +* The APN consists of one or more labels. Each label is coded as +* a one octet length field followed by that number of octets coded +* as 8 bit ASCII characters +*/ + + while (len) { + label_size = *data; + data++; + strncat((char *)apn->name, (char *)data, label_size); + data += label_size; + len -= label_size + 1; + if (len) + strcat((char *)apn->name, "."); + } + + apn->len = strlen((const char *)apn->name); return TRUE; } @@ -3274,7 +3309,68 @@ static enum stk_command_parse_result parse_launch_browser( STK_DATA_OBJECT_TYPE_INVALID); } -/* TODO: parse_open_channel */ +static void destroy_open_channel(struct stk_command *command) +{ + g_free(command->open_channel.alpha_id); + g_free(command->open_channel.text_usr); + g_free(command->open_channel.text_passwd); +} + +static enum stk_command_parse_result parse_open_channel( + struct stk_command *command, + struct comprehension_tlv_iter *iter) +{ + struct stk_command_open_channel *obj = &command->open_channel; + enum stk_command_parse_result status; + + if (command->qualifier >= 0x08) + return STK_PARSE_RESULT_DATA_NOT_UNDERSTOOD; + + if (command->src != STK_DEVICE_IDENTITY_TYPE_UICC) + return STK_PARSE_RESULT_DATA_NOT_UNDERSTOOD; + + if (command->dst != STK_DEVICE_IDENTITY_TYPE_TERMINAL) + return STK_PARSE_RESULT_DATA_NOT_UNDERSTOOD; + + command->destructor = destroy_open_channel; + + /* +* parse the Open Channel data objects related to packet data service +* bearer +*/ + status = parse_dataobj(iter, + STK_DATA_OBJECT_TYPE_ALPHA_ID, 0, + &obj->alpha_id, + STK_DATA_OBJECT_TYPE_ICON_ID, 0, + &obj->icon_id, + STK_DATA_OBJECT_TYPE_BEARER_DESCRIPTION, + DATAOBJ_FLAG_MANDATORY | DATAOBJ_FLAG_MINIMUM, + &obj->bearer_desc, + STK_DATA_OBJECT_TYPE_BUFFER_SIZE, + DATAOBJ_FLAG_MANDATORY | DATAOBJ_FLAG_MINIMUM, + &obj->buf_size, + STK_DATA_OBJECT_TYPE_NETWORK_ACCESS_NAME, 0, + &obj->network_name, + STK_DATA_OBJECT_TYPE_OTHER_ADDRESS, 0, +
[PATCH 2/6] stk-api.txt: Describe new d-bus APIs related to BIP commands.
--- doc/stk-api.txt | 27 ++- 1 files changed, 26 insertions(+), 1 deletions(-) diff --git a/doc/stk-api.txt b/doc/stk-api.txt index 529c734..772e4ce 100644 --- a/doc/stk-api.txt +++ b/doc/stk-api.txt @@ -96,6 +96,7 @@ Methods byte RequestSelection(string title, byte icon_id, an error given below. Possible Errors: [service].Error.SimToolkit.GoBack +[service].Error.SimToolkit.EndSession Implementation notes: @@ -111,6 +112,7 @@ Methods byte RequestSelection(string title, byte icon_id, cleared prior to the display of this text. Possible Errors: [service].Error.SimToolkit.GoBack +[service].Error.SimToolkit.EndSession [service].Error.SimToolkit.Busy Implementation notes: @@ -154,6 +156,7 @@ Methods byte RequestSelection(string title, byte icon_id, should be opaque. Possible Errors: [service].Error.SimToolkit.GoBack +[service].Error.SimToolkit.EndSession Implementation notes: @@ -171,6 +174,7 @@ Methods byte RequestSelection(string title, byte icon_id, are expected. Possible Errors: [service].Error.SimToolkit.GoBack +[service].Error.SimToolkit.EndSession string RequestKey(string alpha, byte icon_id) @@ -179,6 +183,7 @@ Methods byte RequestSelection(string title, byte icon_id, for the request. Possible Errors: [service].Error.SimToolkit.GoBack +[service].Error.SimToolkit.EndSession string RequestDigit(string alpha, byte icon_id) @@ -186,12 +191,14 @@ Methods byte RequestSelection(string title, byte icon_id, expected. Possible Errors: [service].Error.SimToolkit.GoBack +[service].Error.SimToolkit.EndSession boolean RequestConfirmation(string alpha, byte icon_id) Asks the agent to get confirmation from the user. Possible Errors: [service].Error.SimToolkit.GoBack +[service].Error.SimToolkit.EndSession boolean ConfirmCallSetup(string information, byte icon_id) @@ -245,6 +252,7 @@ Methods byte RequestSelection(string title, byte icon_id, Possible Errors: [service].Error.SimToolkit.EndSession void DisplayActionInformation(string text, byte icon_id) + [noreply] Supplies a text string and/or icon concerning the current activity in the terminal and UICC. The @@ -260,6 +268,23 @@ Methodsbyte RequestSelection(string title, byte icon_id, confirmation message to oFono and then should open the launch browser with the given url. + boolean ConfirmOpenChannel(string information, byte icon_id) + + Asks the agent to request user to confirm the channel + set-up. + + Possible Errors: [service].Error.SimToolkit.EndSession + + void DisplayChannelActivity(string text, byte icon_id) + + Supplies a text string and/or icon concerning the + current activity linked to the channel set-up. The + text should be displayed to the user on screen + until the call is canceled using Cancel() or until the + user decides to end the session. + + Possible Errors: [service].Error.SimToolkit.EndSession + void Cancel() [noreply] Asks the agent to cancel any ongoing operation in @@ -270,6 +295,6 @@ Methods byte RequestSelection(string title, byte icon_id, void Release() [noreply] Agent is being released, possibly because of oFono - terminating, SimToolkit interface torn down or modem + terminating, SimToolkit interface turn down or modem off. If the agent is registered as a global agent, no UnregisterAgent call is expected. -- 1.7.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 4/6] stkagent: Add new methods to support the BIP commands
--- src/stkagent.c | 129 src/stkagent.h | 17 +++ 2 files changed, 146 insertions(+), 0 deletions(-) diff --git a/src/stkagent.c b/src/stkagent.c index 2395182..bae788c 100644 --- a/src/stkagent.c +++ b/src/stkagent.c @@ -1081,3 +1081,132 @@ int stk_agent_confirm_launch_browser(struct stk_agent *agent, const char *text, return 0; } + +static void confirm_open_channel_cb(DBusPendingCall *call, void *data) +{ + struct stk_agent *agent = data; + stk_agent_confirmation_cb cb = agent->user_cb; + DBusMessage *reply = dbus_pending_call_steal_reply(call); + enum stk_agent_result result; + gboolean remove_agent; + dbus_bool_t confirm; + + if (check_error(agent, reply, + ALLOWED_ERROR_TERMINATE, &result) == -EINVAL) { + remove_agent = TRUE; + goto error; + } + + if (result != STK_AGENT_RESULT_OK) { + cb(result, FALSE, agent->user_data); + goto done; + } + + if (dbus_message_get_args(reply, NULL, + DBUS_TYPE_BOOLEAN, &confirm, + DBUS_TYPE_INVALID) == FALSE) { + ofono_error("Can't parse the reply to ConfirmOpenChannel()"); + remove_agent = TRUE; + goto error; + } + + cb(result, confirm, agent->user_data); + + CALLBACK_END(); +} + +int stk_agent_confirm_open_channel(struct stk_agent *agent, const char *text, + const struct stk_icon_id *icon, + stk_agent_confirmation_cb cb, + void *user_data, + ofono_destroy_func destroy, int timeout) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + + agent->msg = dbus_message_new_method_call(agent->bus, agent->path, + OFONO_SIM_APP_INTERFACE, + "ConfirmOpenChannel"); + if (agent->msg == NULL) + return -ENOMEM; + + dbus_message_append_args(agent->msg, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_BYTE, &icon->id, + DBUS_TYPE_INVALID); + + if (dbus_connection_send_with_reply(conn, agent->msg, &agent->call, + timeout) == FALSE || + agent->call == NULL) + return -EIO; + + agent->user_cb = cb; + agent->user_data = user_data; + agent->user_destroy = destroy; + + dbus_pending_call_set_notify(agent->call, confirm_open_channel_cb, + agent, NULL); + + return 0; +} + +static void channel_activity_cb(DBusPendingCall *call, void *data) +{ + struct stk_agent *agent = data; + stk_agent_channel_activity_cb cb = agent->user_cb; + DBusMessage *reply = dbus_pending_call_steal_reply(call); + enum stk_agent_result result; + gboolean remove_agent; + + if (check_error(agent, reply, + ALLOWED_ERROR_TERMINATE, &result) == -EINVAL) { + remove_agent = TRUE; + goto error; + } + + if (dbus_message_get_args(reply, NULL, DBUS_TYPE_INVALID) == FALSE) { + ofono_error("Can't parse the reply to DisplayChannelActivity()" + ); + remove_agent = TRUE; + goto error; + } + + cb(result, agent->user_data); + goto done; + + CALLBACK_END(); +} + +int stk_agent_display_channel_activity(struct stk_agent *agent, + const char *text, + const struct stk_icon_id *icon, + stk_agent_channel_activity_cb cb, + void *user_data, + ofono_destroy_func destroy) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + + agent->msg = dbus_message_new_method_call(agent->bus, agent->path, + OFONO_SIM_APP_INTERFACE, + "DisplayChannelActivity"); + if (agent->msg == NULL) + return -ENOMEM; + + dbus_message_append_args(agent->msg, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_BYTE, &icon->id, + DBUS_TYPE_INVALID); + + if (dbus_connection_send_with_reply(conn, agent->msg, &agent->call, + 0) == FALSE || + agent->
[PATCH 0/6] Introduction of BIP commands (STK classe 'e')
The following set of patches introduces the preliminary support of the BIP commands: - Open channel - Close channel - Receive data - Send data - Get channel status Next step is precisely the channel setup (through a connman plugin) and the Rx/Tx data buffer management. Philippe Nunes (6): test-stkutil: Add unit tests for BIP commands stk-api.txt: Describe new d-bus APIs related to BIP commands. stk: Introduce BIP command handlers stkagent: Add new methods to support the BIP commands stkutil: Complete the TLV parsing/builder to support BIP commands test-stk-menu: Add support for BIP commands doc/stk-api.txt | 27 ++- src/stk.c | 307 + src/stkagent.c | 129 ++ src/stkagent.h | 17 + src/stkutil.c | 300 - src/stkutil.h | 141 ++- test/test-stk-menu | 22 + unit/test-stkutil.c | 1201 ++- 8 files changed, 2087 insertions(+), 57 deletions(-) ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 1/6] test-stkutil: Add unit tests for BIP commands
--- unit/test-stkutil.c | 1201 ++- 1 files changed, 1184 insertions(+), 17 deletions(-) diff --git a/unit/test-stkutil.c b/unit/test-stkutil.c index aa62aac..99c2112 100644 --- a/unit/test-stkutil.c +++ b/unit/test-stkutil.c @@ -470,6 +470,65 @@ static void check_provisioning_file_references(GSList *command, g_assert(test[i].len == 0); } +/* Defined in TS 102.223 Section 8.52 */ +static void check_bearer_desc(const struct stk_bearer_description *command, + const struct stk_bearer_description *test) +{ + g_assert(command->type == test->type); + + if (test->type == STK_BEARER_TYPE_GPRS_UTRAN) { + + check_common_byte(command->parameters.gprs.precedence, + test->parameters.gprs.precedence); + check_common_byte(command->parameters.gprs.delay, + test->parameters.gprs.delay); + check_common_byte(command->parameters.gprs.reliability, + test->parameters.gprs.reliability); + check_common_byte(command->parameters.gprs.peak, + test->parameters.gprs.peak); + check_common_byte(command->parameters.gprs.mean, + test->parameters.gprs.mean); + check_common_byte(command->parameters.gprs.pdp_type, + test->parameters.gprs.pdp_type); + return; + } else { + g_assert(command->parameters.other.len == + test->parameters.other.len); + g_assert(g_mem_equal(command->parameters.other.pars, + test->parameters.other.pars, + test->parameters.other.len)); + } +} + +/* Defined in TS 102.223 Section 8.53 */ +static inline void check_channel_data( + const struct stk_common_byte_array *command, + const struct stk_common_byte_array *test) +{ + check_common_byte_array(command, test); +} + +/* Defined in TS 102.223 Section 8.58 */ +static inline void check_other_address( + const struct stk_other_address *command, + const struct stk_other_address *test) +{ + check_common_byte(command->type, test->type); + + if (test->type == STK_ADDRESS_IPV4) + g_assert(command->addr.ipv4 == test->addr.ipv4); + else + g_assert(g_mem_equal(command->addr.ipv6, test->addr.ipv6, 16)); +} + +/* Defined in TS 102.223 Section 8.59 */ +static void check_uicc_te_interface(const struct stk_uicc_te_interface *command, + const struct stk_uicc_te_interface *test) +{ + check_common_byte(command->protocol, test->protocol); + g_assert(command->port == test->port); +} + /* Defined in TS 102.223 Section 8.60 */ static inline void check_aid(const struct stk_aid *command, const struct stk_aid *test) @@ -477,6 +536,15 @@ static inline void check_aid(const struct stk_aid *command, g_assert(g_mem_equal(command->aid, test->aid, test->len)); } +/* Defined in TS 102.223 Section 8.70 */ +static inline void check_network_access_name( + const struct stk_network_access_name *command, + const struct stk_network_access_name *test) +{ + g_assert(command->len == test->len); + g_assert(g_mem_equal(command->name, test->name, test->len)); +} + /* Defined in TS 102.223 Section 8.71 */ static inline void check_cdma_sms_tpdu( const struct stk_common_byte_array *command, @@ -16913,6 +16981,662 @@ static void test_launch_browser(gconstpointer data) stk_command_free(command); } +struct open_channel_test { + const unsigned char *pdu; + unsigned int pdu_len; + unsigned char qualifier; + char *alpha_id; + struct stk_icon_id icon_id; + struct stk_bearer_description bearer_desc; + unsigned short buf_size; + struct stk_network_access_name network_name; + struct stk_other_address local_addr; + char *text_usr; + char *text_passwd; + struct stk_uicc_te_interface uti; + struct stk_other_address data_dest_addr; + struct stk_text_attribute text_attr; + struct stk_frame_id frame_id; +}; + +static unsigned char open_channel_211[] = { 0xD0, 0x36, 0x81, 0x03, 0x01, 0x40, + 0x01, 0x82, 0x02, 0x81, 0x82, + 0x35, 0x07, 0x02, 0x03, 0x04, + 0x03, 0x04, 0x1F, 0x02, 0x39, + 0x02, 0x05, 0x78, 0x0D, 0x08, + 0xF4, 0x55, 0x73, 0x65, 0x72,
[PATCH v3] netreg: add +COPS support for HFP emulator
--- src/network.c | 79 + 1 files changed, 68 insertions(+), 11 deletions(-) diff --git a/src/network.c b/src/network.c index 2d0a9f8..7df6786 100644 --- a/src/network.c +++ b/src/network.c @@ -1693,6 +1693,13 @@ void ofono_netreg_driver_unregister(const struct ofono_netreg_driver *d) g_drivers = g_slist_remove(g_drivers, (void *) d); } +static void emulator_remove_handler(struct ofono_atom *atom, void *data) +{ + struct ofono_emulator *em = __ofono_atom_get_data(atom); + + ofono_emulator_remove_handler(em, data); +} + static void netreg_unregister(struct ofono_atom *atom) { struct ofono_netreg *netreg = __ofono_atom_get_data(atom); @@ -1707,6 +1714,9 @@ static void netreg_unregister(struct ofono_atom *atom) __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP, notify_emulator_strength, GINT_TO_POINTER(0)); + __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP, + emulator_remove_handler, "+COPS"); + __ofono_modem_remove_atom_watch(modem, netreg->hfp_watch); __ofono_watchlist_free(netreg->status_watches); @@ -1890,21 +1900,65 @@ static void sim_spn_spdi_changed(int id, void *userdata) sim_spn_read_cb, netreg); } -static void emulator_hfp_watch(struct ofono_atom *atom, - enum ofono_atom_watch_condition cond, - void *data) +static void emulator_cops_cb(struct ofono_emulator *em, + struct ofono_emulator_request *req, void *userdata) +{ + struct ofono_netreg *netreg = userdata; + struct ofono_error result; + int val; + char name[17]; + char buf[32]; + + result.error = 0; + + switch (ofono_emulator_request_get_type(req)) { + case OFONO_EMULATOR_REQUEST_TYPE_SET: + ofono_emulator_request_next_number(req, &val); + if (val != 3) + goto fail; + + ofono_emulator_request_next_number(req, &val); + if (val != 0) + goto fail; + + result.type = OFONO_ERROR_TYPE_NO_ERROR; + ofono_emulator_send_final(em, &result); + break; + + case OFONO_EMULATOR_REQUEST_TYPE_QUERY: + strncpy(name, get_operator_display_name(netreg), 16); + name[16] = '\0'; + sprintf(buf, "+COPS: %d,0,\"%s\"", netreg->mode, name); + ofono_emulator_send_info(em, buf, TRUE); + result.type = OFONO_ERROR_TYPE_NO_ERROR; + ofono_emulator_send_final(em, &result); + break; + + default: +fail: + result.type = OFONO_ERROR_TYPE_FAILURE; + ofono_emulator_send_final(em, &result); + }; +} + +static void emulator_hfp_init(struct ofono_atom *atom, void *data) { struct ofono_netreg *netreg = data; - struct ofono_modem *modem = __ofono_atom_get_modem(netreg->atom); + struct ofono_emulator *em = __ofono_atom_get_data(atom); - if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) { - __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP, - notify_emulator_status, - GINT_TO_POINTER(netreg->status)); - __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP, - notify_emulator_strength, + notify_emulator_status(atom, GINT_TO_POINTER(netreg->status)); + notify_emulator_strength(atom, GINT_TO_POINTER(netreg->signal_strength)); - } + + ofono_emulator_add_handler(em, "+COPS", emulator_cops_cb, data, NULL); +} + +static void emulator_hfp_watch(struct ofono_atom *atom, + enum ofono_atom_watch_condition cond, + void *data) +{ + if (cond == OFONO_ATOM_WATCH_CONDITION_REGISTERED) + emulator_hfp_init(atom, data); } void ofono_netreg_register(struct ofono_netreg *netreg) @@ -1968,6 +2022,9 @@ void ofono_netreg_register(struct ofono_netreg *netreg) netreg->hfp_watch = __ofono_modem_add_atom_watch(modem, OFONO_ATOM_TYPE_EMULATOR_HFP, emulator_hfp_watch, netreg, NULL); + + __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP, + emulator_hfp_init, netreg); } void ofono_netreg_remove(struct ofono_netreg *netreg) -- 1.7.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
Re: [PATCH 3/3] gprs.c: add list contexts for emulator
Thanks Denis for your feedback. The idea behind this code is to propose the complete support of the usual AT+CGDCONT in the emulator. I think the best solution might be to stick on contexts exposed over DBus, but this could lead to problems like : a context is delete throught the DBus interface... how to handle this change in the AT emulator, and avoid the use of the deleted context ? Olivier On 03/22/2011 03:06 AM, Denis Kenzior wrote: Hi Olivier, On 03/21/2011 08:45 AM, Olivier Guiter wrote: --- src/gprs.c | 26 -- 1 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/gprs.c b/src/gprs.c index 04432c3..06d52f3 100644 --- a/src/gprs.c +++ b/src/gprs.c @@ -2863,11 +2863,31 @@ static void provision_contexts(struct ofono_gprs *gprs, const char *mcc, __ofono_gprs_provision_free_settings(settings, count); } +static void ofono_gprs_list_contexts(struct ofono_emulator *em, void *userdata) +{ + struct ofono_gprs *gprs = userdata; + GSList *l; + char buf[256]; + + struct pri_context *ctx; + + for (l = gprs->contexts; l; l = l->next) { + ctx = l->data; + + snprintf(buf, 255, "+CGDCONT: %d,\"%s\",\"%s\"", + ctx->id, gprs_proto_to_string(ctx->context.proto), + ctx->context.apn); So you're mixing concepts here a bit. gprs.c has two maps: - pid_map - cid_map and two ids: - pri_context::id - ofono_gprs_primary_context::cid Roughly speaking the cid_map lets us pick a context id that maps 1:1 to the modem driver. Hence the use of ofono_gprs_set_cid_range. Basically the driver tells us the valid range of context ids and oFono picks the rest. For an AT modem the driver can simply use the cid picked by oFono in activate_primary callback. Internally oFono has another idmap for tracking unique ids for contexts and ensuring some sane limit on their number. This is managed by pid_map and pri_context::id. The code you have right now would use the pid_map ids... + ofono_emulator_send_info(em, buf, FALSE); + } +} + /* Process the usual AT+CGDCONT command */ static void cgdcont_cb(struct ofono_emulator *em, struct ofono_emulator_request *req, void *userdata) { + struct ofono_gprs *gprs = userdata; + struct idmap *cid = gprs->cid_map; struct ofono_error result; char buf[256]; @@ -2876,7 +2896,8 @@ static void cgdcont_cb(struct ofono_emulator *em, switch (ofono_emulator_request_get_type(req)) { case OFONO_EMULATOR_REQUEST_TYPE_SUPPORT: /* TODO: check additionnal parameters */ - snprintf(buf, 255, "+CGDCONT: (1-2),\"IP\",,,(0-2),(0,1,2,3,4)"); + snprintf(buf, 255, "+CGDCONT: (1-%d),\"IP\",,,(0-2),(0,1,2,3,4)", + idmap_get_size(cid)); , but use the size of the cid_map in the CGDCONT=? implementation below. These sizes are highly unlikely to match. However, this brings up a more fundamental question from me. What do you actually want to expose here? Do you want the emulator to be able to view / edit contexts exposed over D-Bus? Or is it enough to simply fake all this and maintain the cgdcont list in memory for each emulator instance? ofono_emulator_send_info(em, buf, FALSE); result.type = OFONO_ERROR_TYPE_NO_ERROR; ofono_emulator_send_final(em,&result); @@ -2888,7 +2909,8 @@ static void cgdcont_cb(struct ofono_emulator *em, break; case OFONO_EMULATOR_REQUEST_TYPE_QUERY: - result.type = OFONO_ERROR_TYPE_FAILURE; + ofono_gprs_list_contexts(em, gprs); + result.type = OFONO_ERROR_TYPE_NO_ERROR; ofono_emulator_send_final(em,&result); break; case OFONO_EMULATOR_REQUEST_TYPE_SET: Regards, -Denis ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 6/6] emulator: add ppp_suspend() CB and register it
--- src/emulator.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/src/emulator.c b/src/emulator.c index c84f0a9..c1ceb36 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -99,6 +99,15 @@ static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user_data) g_at_server_resume(em->server); } +static void ppp_suspend(gpointer user_data) +{ + struct ofono_emulator *em = user_data; + + DBG(""); + + g_at_server_resume(em->server); +} + static gboolean setup_ppp(gpointer user_data) { struct ofono_emulator *em = user_data; @@ -126,6 +135,7 @@ static gboolean setup_ppp(gpointer user_data) g_at_ppp_set_connect_function(em->ppp, ppp_connect, em); g_at_ppp_set_disconnect_function(em->ppp, ppp_disconnect, em); + g_at_ppp_set_suspend_function(em->ppp, ppp_suspend, em); return FALSE; } -- 1.7.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 5/6] gatppp: add g_at_ppp_set_suspend_function() definition
--- gatchat/gatppp.c |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c index 993b5ea..9df6b8e 100644 --- a/gatchat/gatppp.c +++ b/gatchat/gatppp.c @@ -467,6 +467,14 @@ void g_at_ppp_set_debug(GAtPPP *ppp, GAtDebugFunc func, gpointer user_data) ppp->debug_data = user_data; } +void g_at_ppp_set_suspend_function(GAtPPP *ppp, GAtSuspendFunc func, gpointer user_data) +{ + if (ppp == NULL) + return; + + g_at_hdlc_set_suspend_function(ppp->hdlc, func, user_data); +} + void g_at_ppp_shutdown(GAtPPP *ppp) { if (ppp->phase == PPP_PHASE_DEAD || ppp->phase == PPP_PHASE_TERMINATION) -- 1.7.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 4/6] gatppp: add g_at_ppp_set_suspend_function() prototype
--- gatchat/gatppp.h |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/gatchat/gatppp.h b/gatchat/gatppp.h index fb5de4c..7835d1f 100644 --- a/gatchat/gatppp.h +++ b/gatchat/gatppp.h @@ -61,6 +61,8 @@ void g_at_ppp_set_connect_function(GAtPPP *ppp, GAtPPPConnectFunc callback, void g_at_ppp_set_disconnect_function(GAtPPP *ppp, GAtPPPDisconnectFunc func, gpointer user_data); void g_at_ppp_set_debug(GAtPPP *ppp, GAtDebugFunc func, gpointer user_data); +void g_at_ppp_set_suspend_function(GAtPPP *ppp, GAtSuspendFunc func, + gpointer user_data); void g_at_ppp_shutdown(GAtPPP *ppp); void g_at_ppp_ref(GAtPPP *ppp); void g_at_ppp_unref(GAtPPP *ppp); -- 1.7.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 1/6] gat: add GAtSuspendFunc CB typedef
--- gatchat/gat.h |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/gatchat/gat.h b/gatchat/gat.h index ddf8695..f067389 100644 --- a/gatchat/gat.h +++ b/gatchat/gat.h @@ -32,6 +32,7 @@ typedef void (*GAtDisconnectFunc)(gpointer user_data); typedef void (*GAtReceiveFunc)(const unsigned char *data, gsize size, gpointer user_data); typedef void (*GAtDebugFunc)(const char *str, gpointer user_data); +typedef void (*GAtSuspendFunc)(gpointer user_data); #ifdef __cplusplus } -- 1.7.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH 3/6] gathdlc: add mechansim to detect '+++' escape sequence
--- gatchat/gathdlc.c | 114 + 1 files changed, 114 insertions(+), 0 deletions(-) diff --git a/gatchat/gathdlc.c b/gatchat/gathdlc.c index 7c45454..21e4533 100644 --- a/gatchat/gathdlc.c +++ b/gatchat/gathdlc.c @@ -50,6 +50,13 @@ #define HDLC_FCS(fcs, c) crc_ccitt_byte(fcs, c) +/* Amount of fiftieths of second to detect '+++'. + * Range is 0 to 0xff. + */ +#define ESC_TIME 0x32 + +#define GUARD_TIMEOUTS 1000/* Pause time before and after '+++' sequence */ + struct _GAtHDLC { gint ref_count; GAtIO *io; @@ -68,6 +75,12 @@ struct _GAtHDLC { gboolean in_read_handler; gboolean destroyed; gboolean no_carrier_detect; + GAtSuspendFunc suspend_func; + gpointer suspend_data; + guint cmpt; + guint suspend_timeout; + guint pause_timeout; + gboolean paused; }; static void hdlc_record(int fd, gboolean in, guint8 *data, guint16 length) @@ -130,6 +143,47 @@ guint32 g_at_hdlc_get_recv_accm(GAtHDLC *hdlc) return hdlc->recv_accm; } +void g_at_hdlc_set_suspend_function(GAtHDLC *hdlc, GAtSuspendFunc func, + gpointer user_data) +{ + if (hdlc == NULL) + return; + + hdlc->suspend_func = func; + hdlc->suspend_data = user_data; +} + +static gboolean paused_timeout_cb(gpointer user_data) +{ + GAtHDLC *hdlc = user_data; + + hdlc->paused = TRUE; + + return FALSE; +} + +static gboolean susp_timeout_cb(gpointer user_data) +{ + GAtHDLC *hdlc = user_data; + + hdlc->cmpt = 0; + + return FALSE; +} + +static gboolean hdlc_suspend(gpointer user_data) +{ + GAtHDLC *hdlc = user_data; + + g_at_io_set_write_handler(hdlc->io, NULL, NULL); + g_at_io_set_read_handler(hdlc->io, NULL, NULL); + + if (hdlc->suspend_func) + hdlc->suspend_func(hdlc->suspend_data); + + return FALSE; +} + static void new_bytes(struct ring_buffer *rbuf, gpointer user_data) { GAtHDLC *hdlc = user_data; @@ -142,6 +196,13 @@ static void new_bytes(struct ring_buffer *rbuf, gpointer user_data) hdlc->in_read_handler = TRUE; + /* +* We delete the the paused_timeout_cb or hdlc_suspend as soons as +* we read a data. +*/ + if (hdlc->pause_timeout > 0) + g_source_remove(hdlc->pause_timeout); + while (pos < len) { /* * We try to detect NO CARRIER conditions here. We @@ -153,6 +214,21 @@ static void new_bytes(struct ring_buffer *rbuf, gpointer user_data) hdlc->decode_offset == 0 && *buf == '\r') break; + /* +* If there was no character for 1 second we try to detect +* the '+' character to suspend data call if 3 '+' are +* detected in less than 20 * ESC_TIME milliseconds. +*/ + if (*buf == '+' && hdlc->paused) { + if (hdlc->cmpt == 0) + hdlc->suspend_timeout = g_timeout_add (20 * ESC_TIME, + susp_timeout_cb, hdlc); + hdlc->cmpt++; + } else { + hdlc->cmpt = 0; + hdlc->paused = FALSE; + } + if (hdlc->decode_escape == TRUE) { unsigned char val = *buf ^ HDLC_TRANS; @@ -190,6 +266,9 @@ static void new_bytes(struct ring_buffer *rbuf, gpointer user_data) } } + if (hdlc->cmpt == 3) + goto suspend; + out: ring_buffer_drain(rbuf, pos); @@ -197,6 +276,37 @@ out: if (hdlc->destroyed) g_free(hdlc); + + /* +* If there were no data pause for GUARD_TIMEOUTS ms, +* we try again to check it. +*/ + if (!hdlc->paused) + hdlc->pause_timeout = g_timeout_add (GUARD_TIMEOUTS, + paused_timeout_cb, + hdlc); + + return; + +suspend: + /* +* If the suspend timeout still exists, +* delete it. +*/ + if (hdlc->suspend_timeout > 0) + g_source_remove(hdlc->suspend_timeout); + + /* +* Restart the counter and reset the ring buffer. +*/ + hdlc->cmpt = 0; + ring_buffer_reset(rbuf); + + /* +* Wait for another pause of GUARD_TIMEOUTS ms before returning to command mode. +*/ + hdlc->paused = FALSE; + hdlc->pause_timeout = g_timeout_add (GUARD_TIMEOUTS, hdlc_suspend, hdlc); } GAtHDLC *g_at_hdlc_new_from_io(GAtIO *io) @@ -245,6 +355,10 @@ GAtHDLC *g_at_hdlc_new_from_io(GAtIO *io) hdlc->io = g_at_io_ref(io); g_at_io_set_read_handl
[PATCH 2/6] gathdlc: add g_at_hdlc_set_suspend_function() prototype
--- gatchat/gathdlc.h |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/gatchat/gathdlc.h b/gatchat/gathdlc.h index 95c389e..158f27f 100644 --- a/gatchat/gathdlc.h +++ b/gatchat/gathdlc.h @@ -57,6 +57,9 @@ GAtIO *g_at_hdlc_get_io(GAtHDLC *hdlc); void g_at_hdlc_set_no_carrier_detect(GAtHDLC *hdlc, gboolean detect); +void g_at_hdlc_set_suspend_function(GAtHDLC *hdlc, GAtSuspendFunc func, + gpointer user_data); + #ifdef __cplusplus } #endif -- 1.7.1 ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
[PATCH v2 0/6] Time Independent Escape Sequence implementation
This set of patch will implement the escape sequence detection implementation: +++ The length is fixed by the guard timeouts. The length to detect +++ sequence is fixed by the escape time. Guillaume Zajac (6): gat: add GAtSuspendFunc CB typedef gathdlc: add g_at_hdlc_set_suspend_function() prototype gathdlc: add mechansim to detect '+++' escape sequence gatppp: add g_at_ppp_set_suspend_function() prototype gatppp: add g_at_ppp_set_suspend_function() definition emulator: add ppp_suspend() CB and register it gatchat/gat.h |1 + gatchat/gathdlc.c | 111 + gatchat/gathdlc.h |3 + gatchat/gatppp.c |8 gatchat/gatppp.h |2 + src/emulator.c| 10 + 6 files changed, 135 insertions(+), 0 deletions(-) ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono
Re: [PATCH 3/6] gathdlc: add mechanism to detect ppp suspension from DUN client.
Hi Denis, On 21/03/2011 19:57, Denis Kenzior wrote: Hi Guillaume, On 03/21/2011 09:17 AM, Guillaume Zajac wrote: Hi Denis, On 17/03/2011 21:13, Denis Kenzior wrote: Hi Guillaume, On 03/15/2011 04:19 AM, Guillaume Zajac wrote: --- gatchat/gathdlc.c | 58 + 1 files changed, 58 insertions(+), 0 deletions(-) http://en.wikipedia.org/wiki/Time_Independent_Escape_Sequence If you really want to do this, then lets do this properly, including the guard timeouts. Regards, -Denis I noticed also this guard timeouts after having sent the set of patches. I will send a 2nd version of patches. However I can't test the "+++" sequence with telnet because it is adding some '\r' '\n' characters when I do do "+++" then "Enter". I could try to filter those characters but it would add some specific code for telnet test case. I have tried to modifiy gsmdial to send "+++" 5 seconds after the 2 ppp devices have been set up for instance. I have implemented a g_at_ppp_send_escape_sequence() function to send it. (this function directly writes on the GIOChannel) Then the GAtChat is resumed and an ATH0 is sent. Should I commit first the test case over gsmdial and then commit the escape sequence detection mechanism? The order doesn't matter, but it would be nice to have all of this in the same patch series for context. That way the entire series can be applied and tested in one go. You might have to do a bit more work than just sending +++ to the IOChannel. For instance you might need to shutdown I/O coming from the TUN device so as not to overflow the GAtHDLC write queue. So perhaps a proper g_at_ppp_suspend and g_at_chat_send_command_mode_escape() is needed. Thanks for the info, I will commit first my version 2 of the escape sequence detection mechanism. Then, I will find a proper way to reproduce the suspend mechanism with gsmdial. Kind regards, Guillaume ___ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono