Vodafone K3770/K3772-Z modems driver & networking library
Dependencies: Socket USBHostWANDongle lwip-sys lwip
Dependents: VodafoneUSBModemHTTPClientTest VodafoneUSBModemNTPClientTest VodafoneUSBModemSMSTest VodafoneUSBModemUSSDTest ... more
Fork of VodafoneUSBModem_bleedingedge by
This is the driver for the Vodafone K3700 & K3772-Z Dongles:
More details and instructions can be found here.
Revision 12:66dc2c8eba2d, committed 2012-07-11
- Comitter:
- donatien
- Date:
- Wed Jul 11 21:25:03 2012 +0000
- Parent:
- 11:565b2ec40dea
- Child:
- 13:9db45f02a6c1
- Commit message:
- Link Monitoring / Dual serial port support
Changed in this revision
--- a/USBHostWANDongleLib.lib Wed Jul 11 12:47:53 2012 +0000 +++ b/USBHostWANDongleLib.lib Wed Jul 11 21:25:03 2012 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/donatien/code/USBHostWANDongle_bleedingedge/#4394986752db +http://mbed.org/users/donatien/code/USBHostWANDongle_bleedingedge/#d229ebfb85c4
--- a/VodafoneK3770.cpp Wed Jul 11 12:47:53 2012 +0000 +++ b/VodafoneK3770.cpp Wed Jul 11 21:25:03 2012 +0000 @@ -21,7 +21,7 @@ SOFTWARE. */ -#define __DEBUG__ 4 +#define __DEBUG__ 0 #ifndef __MODULE__ #define __MODULE__ "VodafoneK3770.cpp" #endif @@ -32,8 +32,8 @@ VodafoneK3770::VodafoneK3770() : m_dongle(), m_atStream(m_dongle.getSerial(1)), m_pppStream(m_dongle.getSerial(0)), m_at(&m_atStream), -m_sms(&m_at), m_ussd(&m_at), m_ppp(&m_pppStream), -m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false) +m_sms(&m_at), m_ussd(&m_at), m_linkMonitor(&m_at), m_ppp(&m_pppStream), +m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_ussdInit(false), m_linkMonitorInit(false), m_atOpen(false) { } @@ -81,6 +81,7 @@ volatile REGISTERING_STATUS status; }; +#if 0 class COPSProcessor : public IATCommandsProcessor { public: @@ -159,7 +160,7 @@ char apn[24]; volatile bool valid; }; - +#endif int VodafoneK3770::connect(const char* apn, const char* user, const char* password) { @@ -179,6 +180,7 @@ #if USE_ONE_PORT m_smsInit = false; //SMS status reset m_ussdInit = false; //USSD status reset + m_linkMonitorInit = false; //Link monitor status reset #endif ATCommandsInterface::ATResult result; @@ -241,7 +243,7 @@ #endif DBG("Connecting PPP"); - ret = m_ppp.connect("*99#"); + ret = m_ppp.connect(); DBG("Result of connect: Err code=%d", ret); return ret; } @@ -414,6 +416,34 @@ return OK; } +int VodafoneK3770::getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegistrationState, LinkMonitor::BEARER* pBearer) +{ + int ret = init(); + if(ret) + { + return ret; + } + + if(!m_linkMonitorInit) + { + ret = m_linkMonitor.init(); + if(ret) + { + return ret; + } + m_linkMonitorInit = true; + } + + ret = m_linkMonitor.getState(pRssi, pRegistrationState, pBearer); + if(ret) + { + return ret; + } + + return OK; +} + + ATCommandsInterface* VodafoneK3770::getATCommandsInterface() { return &m_at; @@ -452,12 +482,19 @@ #if USE_ONE_PORT DBG("Configuring unsolicited result codes support properly"); - //Configuring port + //Configuring port to enable 3GPP-compliant unsollicited response codes but disable Huawei-specific unsollicited response codes ret = m_at.executeSimple("AT^CURC=0;^PORTSEL=1", NULL); //Huawei-specific, not 3GPP-compliant if(ret != OK) { return NET_PROTOCOL; } + #else + //Configuring port to disable Huawei-specific unsollicited response codes + ret = m_at.executeSimple("AT^CURC=0", NULL); //Huawei-specific, not 3GPP-compliant + if(ret != OK) + { + return NET_PROTOCOL; + } #endif ATCommandsInterface::ATResult result;
--- a/VodafoneK3770.h Wed Jul 11 12:47:53 2012 +0000 +++ b/VodafoneK3770.h Wed Jul 11 21:25:03 2012 +0000 @@ -32,6 +32,7 @@ #include "ip/PPPIPInterface.h" #include "sms/SMSInterface.h" #include "ussd/USSDInterface.h" +#include "link/LinkMonitor.h" /** Vodafone K3770 dongle */ @@ -85,6 +86,14 @@ @return 0 on success, error code on failure */ int sendUSSD(const char* command, char* result, size_t maxLength); + + /** Get link state + @param pRssi pointer to store the current RSSI in dBm, between -51 dBm and -113 dBm if known; -51 dBm means -51 dBm or more; -113 dBm means -113 dBm or less; 0 if unknown + @param pRegistrationState pointer to store the current registration state + @param pBearer pointer to store the current bearer + @return 0 on success, error code on failure + */ + int getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegistrationState, LinkMonitor::BEARER* pBearer); /** Get the ATCommandsInterface instance @return Pointer to the ATCommandsInterface instance @@ -104,6 +113,7 @@ SMSInterface m_sms; USSDInterface m_ussd; + LinkMonitor m_linkMonitor; PPPIPInterface m_ppp; @@ -111,6 +121,7 @@ bool m_ipInit; bool m_smsInit; bool m_ussdInit; + bool m_linkMonitorInit; bool m_atOpen; };
--- a/ip/PPPIPInterface.cpp Wed Jul 11 12:47:53 2012 +0000 +++ b/ip/PPPIPInterface.cpp Wed Jul 11 21:25:03 2012 +0000 @@ -21,7 +21,13 @@ SOFTWARE. */ -#define __DEBUG__ 2 //Maximum verbosity +#define MSISDN "*99#" + +#define CONNECT_CMD "ATD " MSISDN "\x0D" +#define EXPECTED_RESP CONNECT_CMD "\x0D" "\x0A" "CONNECT" "\x0D" "\x0A" +#define OK_RESP + +#define __DEBUG__ 0 //Maximum verbosity #ifndef __MODULE__ #define __MODULE__ "PPPIPInterface.cpp" #endif @@ -65,7 +71,7 @@ return OK; } -/*virtual*/ int PPPIPInterface::connect(const char* msisdn) +/*virtual*/ int PPPIPInterface::connect() { int ret; char buf[32]; @@ -74,31 +80,41 @@ do //Clear buf { - ret = m_pStream->read(buf, &len, 32, 0) > 0 + ret = m_pStream->read((uint8_t*)buf, &len, 32, 0); } while( (ret == OK) && (len > 0) ); - sprintf(buf, "ATD %16s\x0D"); + DBG("Sending %s", CONNECT_CMD); - ret = m_pStream->write(buf, strlen(buf), osWaitForever); + ret = m_pStream->write((uint8_t*)CONNECT_CMD, strlen(CONNECT_CMD), osWaitForever); if( ret != OK ) { return NET_UNKNOWN; } - const char expected = "\x0D\0x0ACONNECT\x0D\0x0A"; - - ret = m_pStream->read(buf, strlen(expected), &len, 3000); - if( ret != OK ) + DBG("Expect %s [len %d]", EXPECTED_RESP, strlen(EXPECTED_RESP)); + + len = 0; + while(len < strlen(EXPECTED_RESP)) { + size_t readLen; + ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(EXPECTED_RESP) - len, 10000); + if( ret != OK ) + { return NET_UNKNOWN; + } + len += readLen; } - if( (len < strlen(expected)) || (memcmp(expected, buf) != 0) ) + buf[len]=0; + + DBG("Got %s[len %d]", buf, len); + + if( memcmp(EXPECTED_RESP, buf, strlen(EXPECTED_RESP)) != 0 ) { //Discard buffer do //Clear buf { - ret = m_pStream->read(buf, &len, 32, 0) > 0 + ret = m_pStream->read((uint8_t*)buf, &len, 32, 0); } while( (ret == OK) && (len > 0) ); return NET_CONN; } @@ -109,7 +125,8 @@ { return NET_INVALID; } - int ret = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this); + + ret = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this); if(ret < 0) { switch(ret)
--- a/ip/PPPIPInterface.h Wed Jul 11 12:47:53 2012 +0000 +++ b/ip/PPPIPInterface.h Wed Jul 11 21:25:03 2012 +0000 @@ -46,7 +46,7 @@ int init(); //Init PPP-specific stuff, create the right bindings, etc int setup(const char* user, const char* pw); //Setup authentication - virtual int connect(const char* msisdn); + virtual int connect(); virtual int disconnect(); private:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/link/LinkMonitor.cpp Wed Jul 11 21:25:03 2012 +0000 @@ -0,0 +1,141 @@ +/* LinkMonitor.cpp */ +/* +Copyright (C) 2012 ARM Limited. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "LinkMonitor.cpp" +#endif + +#include "core/fwk.h" + +#include "LinkMonitor.h" + +#include <cstdio> + +#define DEFAULT_TIMEOUT 10000 + +LinkMonitor::LinkMonitor(ATCommandsInterface* pIf) : m_pIf(pIf), m_rssi(0), m_registrationState(REGISTRATION_STATE_UNKNOWN), m_bearer(BEARER_UNKNOWN) +{ + +} + +int LinkMonitor::init() +{ + return OK; +} + +/*virtual*/ int LinkMonitor::onNewATResponseLine(ATCommandsInterface* pInst, const char* line) +{ + DBG("Line is %s", line); + int v; + if( sscanf(line, "+CREG: %*d,%d", &v) >= 1 ) //Reg state is valid + { + DBG("+CREG %d", v); + switch( v ) + { + case 0: + m_registrationState = REGISTRATION_STATE_UNKNOWN; + break; + case 1: + m_registrationState = REGISTRATION_STATE_HOME_NETWORK; + break; + case 2: + m_registrationState = REGISTRATION_STATE_REGISTERING; + break; + case 3: + m_registrationState = REGISTRATION_STATE_DENIED; + break; + case 4: + m_registrationState = REGISTRATION_STATE_NO_SIGNAL; + break; + case 5: + m_registrationState = REGISTRATION_STATE_ROAMING; + break; + default: + m_registrationState = REGISTRATION_STATE_UNKNOWN; + break; + } + } + else if( sscanf(line, "+COPS: %*d,%*d,\"%*[^\"]\",%d", &v) >= 1 ) + { + DBG("+COPS %d", v); + switch( v ) + { + case 0: + m_bearer = BEARER_GSM; + break; + case 2: + m_bearer = BEARER_UMTS; + break; + case 3: + m_bearer = BEARER_EDGE; + break; + case 4: //HSDPA + case 5: //HSUPA + case 6: //HSDPA + HSUPA + m_bearer = BEARER_HSPA; + break; + case 7: + m_bearer = BEARER_LTE; + break; + case 1: //GSM Compact + default: + m_bearer = BEARER_UNKNOWN; + break; + } + } + else if( sscanf(line, "+CSQ: %d,%*d", &v) >= 1 ) + { + DBG("+CSQ %d", v); + if(v == 99) //Unknown + { + m_rssi = 0; //Unknown + } + else + { + m_rssi = -113 + 2*v; + } + } + return OK; +} + +/*virtual*/ int LinkMonitor::onNewEntryPrompt(ATCommandsInterface* pInst) +{ + return OK; +} + +int LinkMonitor::getState(int* pRssi, REGISTRATION_STATE* pRegistrationState, BEARER* pBearer) +{ + m_rssi = 0; + m_registrationState = REGISTRATION_STATE_UNKNOWN; + m_bearer = BEARER_UNKNOWN; + int ret = m_pIf->execute("AT+CREG=2;+CREG?;+CREG=0;+COPS?;+CSQ", this, NULL, DEFAULT_TIMEOUT); //Configure to get registration info & get it; get signal quality + if(ret != OK) + { + return NET_PROTOCOL; + } + *pRssi = m_rssi; + *pRegistrationState = m_registrationState; + *pBearer = m_bearer; + return OK; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/link/LinkMonitor.h Wed Jul 11 21:25:03 2012 +0000 @@ -0,0 +1,94 @@ +/* LinkMonitor.h */ +/* +Copyright (C) 2012 ARM Limited. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef LINKMONITOR_H_ +#define LINKMONITOR_H_ + +#include "core/fwk.h" + +#include "rtos.h" + +#include "at/ATCommandsInterface.h" + +/** Component to monitor link quality + * + */ +class LinkMonitor : protected IATCommandsProcessor +{ +public: + /** Create LinkMonitor instance + @param pIf Pointer to the ATCommandsInterface instance to use + */ + LinkMonitor(ATCommandsInterface* pIf); + + /** Initialize monitor + */ + int init(); + + /** Registration State + */ + enum REGISTRATION_STATE + { + REGISTRATION_STATE_UNKNOWN, //!< Unknown + REGISTRATION_STATE_REGISTERING, //!< Registering + REGISTRATION_STATE_DENIED, //!< Denied + REGISTRATION_STATE_NO_SIGNAL, //!< No Signal + REGISTRATION_STATE_HOME_NETWORK, //!< Registered on home network + REGISTRATION_STATE_ROAMING //!< Registered on roaming network + }; + + /** Bearer type + */ + enum BEARER + { + BEARER_UNKNOWN, //!< Unknown + BEARER_GSM, //!< GSM (2G) + BEARER_EDGE, //!< EDGE (2.5G) + BEARER_UMTS, //!< UMTS (3G) + BEARER_HSPA, //!< HSPA (3G+) + BEARER_LTE //!< LTE (4G) + }; + + /** Get link state + @param pRssi pointer to store the current RSSI in dBm, between -51 dBm and -113 dBm if known; -51 dBm means -51 dBm or more; -113 dBm means -113 dBm or less; 0 if unknown + @param pRegistrationState pointer to store the current registration state + @param pBearer pointer to store the current bearer + @return 0 on success, error code on failure + */ + int getState(int* pRssi, REGISTRATION_STATE* pRegistrationState, BEARER* pBearer); + +protected: + //IATCommandsProcessor + virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line); + virtual int onNewEntryPrompt(ATCommandsInterface* pInst); + +private: + ATCommandsInterface* m_pIf; + + int m_rssi; + REGISTRATION_STATE m_registrationState; + BEARER m_bearer; + +}; + +#endif /* LINKMONITOR_H_ */
--- a/sms/SMSInterface.cpp Wed Jul 11 12:47:53 2012 +0000 +++ b/sms/SMSInterface.cpp Wed Jul 11 21:25:03 2012 +0000 @@ -21,7 +21,7 @@ SOFTWARE. */ -#define __DEBUG__ 4 +#define __DEBUG__ 0 #ifndef __MODULE__ #define __MODULE__ "SMSInterface.cpp" #endif
--- a/ussd/USSDInterface.cpp Wed Jul 11 12:47:53 2012 +0000 +++ b/ussd/USSDInterface.cpp Wed Jul 11 21:25:03 2012 +0000 @@ -21,7 +21,7 @@ SOFTWARE. */ -#define __DEBUG__ 4 +#define __DEBUG__ 0 #ifndef __MODULE__ #define __MODULE__ "USSDInterface.cpp" #endif