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 Donatien Garnier

This is the driver for the Vodafone K3700 & K3772-Z Dongles:

K3770

More details and instructions can be found here.

Files at this revision

API Documentation at this revision

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

USBHostWANDongleLib.lib Show annotated file Show diff for this revision Revisions of this file
VodafoneK3770.cpp Show annotated file Show diff for this revision Revisions of this file
VodafoneK3770.h Show annotated file Show diff for this revision Revisions of this file
ip/PPPIPInterface.cpp Show annotated file Show diff for this revision Revisions of this file
ip/PPPIPInterface.h Show annotated file Show diff for this revision Revisions of this file
link/LinkMonitor.cpp Show annotated file Show diff for this revision Revisions of this file
link/LinkMonitor.h Show annotated file Show diff for this revision Revisions of this file
sms/SMSInterface.cpp Show annotated file Show diff for this revision Revisions of this file
ussd/USSDInterface.cpp Show annotated file Show diff for this revision Revisions of this file
--- 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