u-blox USB modems (GSM and CDMA)

Dependencies:   CellularUSBModem

Dependents:   C027_CANInterfaceComm C027_ModemTransparentUSBCDC_revb UbloxModemHTTPClientTest C027_HTTPClientTest ... more

Legacy Networking Libray

This is an mbed 2 networking library. For an mbed OS 5 compatible library, please see:

Import libraryC027Interface

Socket interface for C027Interface. Implements the NetworkSocketAPI

Files at this revision

API Documentation at this revision

Comitter:
bogdanm
Date:
Thu Oct 17 13:06:33 2013 +0300
Parent:
0:328d98dd5c78
Child:
2:4be5e62433b1
Commit message:
Initial release of the UbloxUSBModem library

Changed in this revision

UbloxCDMAModemInitializer.cpp Show annotated file Show diff for this revision Revisions of this file
UbloxCDMAModemInitializer.h Show annotated file Show diff for this revision Revisions of this file
UbloxGSMModemInitializer.cpp Show annotated file Show diff for this revision Revisions of this file
UbloxGSMModemInitializer.h Show annotated file Show diff for this revision Revisions of this file
UbloxUSBCDMAModem.cpp Show annotated file Show diff for this revision Revisions of this file
UbloxUSBCDMAModem.h Show annotated file Show diff for this revision Revisions of this file
UbloxUSBGSMModem.cpp Show annotated file Show diff for this revision Revisions of this file
UbloxUSBGSMModem.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbloxCDMAModemInitializer.cpp	Thu Oct 17 13:06:33 2013 +0300
@@ -0,0 +1,110 @@
+/* Copyright (c) 2010-2012 mbed.org, MIT License
+*
+* 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__ 4
+#ifndef __MODULE__
+#define __MODULE__ "UbloxCDMAModemInitializer.cpp"
+#endif
+
+#include "core/dbg.h"
+
+#include <stdint.h>
+
+#include "UbloxCDMAModemInitializer.h"
+
+uint16_t UbloxCDMAModemInitializer::getMSDVid()
+{
+    return 0x05C6;
+}
+uint16_t UbloxCDMAModemInitializer::getMSDPid()
+{
+    return 0x0000;    //No MSD mode (presumably)
+}
+
+uint16_t UbloxCDMAModemInitializer::getSerialVid()
+{
+    return 0x05C6;
+}
+uint16_t UbloxCDMAModemInitializer::getSerialPid()
+{
+    return 0x9004;
+}
+
+bool UbloxCDMAModemInitializer::switchMode(USBDeviceConnected* pDev)
+{
+    return true;
+}
+
+int UbloxCDMAModemInitializer::getSerialPortCount()
+{
+    return 2;
+}
+
+/*virtual*/ void UbloxCDMAModemInitializer::setVidPid(uint16_t vid, uint16_t pid)
+{
+    m_currentSerialIntf = 0;
+    m_currentEndpoint = 0;
+}
+
+/*virtual*/ bool UbloxCDMAModemInitializer::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+    DBG("Interface #%d; Class:%02x; SubClass:%02x; Protocol:%02x", intf_nb, intf_class, intf_subclass, intf_protocol);
+
+    if( intf_class == 0xFF ) {
+        if( m_currentSerialIntf == 0 || m_currentSerialIntf == 1) {
+            m_serialIntfMap[m_currentSerialIntf++] = intf_nb;
+            return true;
+        }
+        m_currentSerialIntf++;
+    }
+
+    return false;
+}
+
+/*virtual*/ bool UbloxCDMAModemInitializer::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    DBG("USBEndpoint on Interface #%d; Type:%d; Direction:%d Current %d", intf_nb, type, dir, m_currentEndpoint);
+    if(type == BULK_ENDPOINT) {
+        if( intf_nb == 1 || intf_nb == 0) {
+            m_currentEndpoint++;
+            return true;
+        } else {
+            m_currentEndpoint++;
+        }
+    }
+
+		/*
+    if(type == INTERRUPT_ENDPOINT) {
+        if( intf_nb == 1) {
+            m_currentEndpoint++;
+            return true;
+        } else {
+            m_currentEndpoint++;
+        }
+    }
+		*/
+		
+    return false;
+}
+
+
+/*virtual*/ int UbloxCDMAModemInitializer::getType()
+{
+    return WAN_DONGLE_TYPE_UBLOXC200;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbloxCDMAModemInitializer.h	Thu Oct 17 13:06:33 2013 +0300
@@ -0,0 +1,63 @@
+/* Copyright (c) 2010-2012 mbed.org, MIT License
+*
+* 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 UBLOXCDMAMODEMINITIALIZER_H
+#define UBLOXCDMAMODEMINITIALIZER_H
+
+#include <stdint.h>
+
+#include "WANDongleInitializer.h"
+#include "USBHost.h"
+#include "IUSBEnumerator.h"
+
+enum
+{
+  WAN_DONGLE_TYPE_UBLOXC200
+};
+
+class UbloxCDMAModemInitializer : public WANDongleInitializer
+{
+public:
+    UbloxCDMAModemInitializer(USBHost* pHost);
+    
+    virtual uint16_t getMSDVid();
+    virtual uint16_t getMSDPid();
+    
+    virtual uint16_t getSerialVid();
+    virtual uint16_t getSerialPid();
+    
+    virtual bool switchMode(USBDeviceConnected* pDev);
+    
+    virtual int getSerialPortCount();
+    
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+    
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+    
+    virtual int getType();
+    
+private:
+
+  int m_currentSerialIntf;
+  int m_currentEndpoint;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbloxGSMModemInitializer.cpp	Thu Oct 17 13:06:33 2013 +0300
@@ -0,0 +1,131 @@
+/* Copyright (c) 2010-2012 mbed.org, MIT License
+*
+* 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.
+*/
+
+#include "UbloxGSMModemInitializer.h"
+#include "core/dbg.h"
+
+#define __DEBUG__ 0
+#ifndef __MODULE__
+#define __MODULE__ "UbloxGSMModemInitializer.cpp"
+#endif
+
+//-----------------------------------------------------------------------
+// mamm, u-blox Modem
+//-----------------------------------------------------------------------
+
+UbloxGSMModemInitializer::UbloxGSMModemInitializer(USBHost* pHost) : WANDongleInitializer(pHost)
+{
+  
+}
+
+uint16_t UbloxGSMModemInitializer::getMSDVid()      { return 0x1546; }
+uint16_t UbloxGSMModemInitializer::getMSDPid()      { return 0x0000; }
+
+uint16_t UbloxGSMModemInitializer::getSerialVid()   { return 0x1546; }
+uint16_t UbloxGSMModemInitializer::getSerialPid()   { return 0x1102; }
+
+bool UbloxGSMModemInitializer::switchMode(USBDeviceConnected* pDev)
+{
+  for (int i = 0; i < pDev->getNbIntf(); i++)
+  {
+    if (pDev->getInterface(i)->intf_class == MSD_CLASS)
+    {
+      USBEndpoint* pEp = pDev->getEndpoint(i, BULK_ENDPOINT, OUT);
+      if ( pEp != NULL ) 
+      {
+        ERR("MSD descriptor found on device %p, intf %d", (void *)pDev, i);
+      }
+    }  
+  }
+  return false;
+}
+
+#define UBX_SERIALCOUNT 7 
+
+int UbloxGSMModemInitializer::getSerialPortCount()
+{
+  return UBX_SERIALCOUNT;
+}
+
+/*virtual*/ void UbloxGSMModemInitializer::setVidPid(uint16_t vid, uint16_t pid)
+{
+    if( (vid == getSerialVid() ) && ( pid == getSerialPid() ) )
+    {
+      m_hasSwitched = true;
+      m_currentSerialIntf = 0;
+      m_endpointsToFetch = UBX_SERIALCOUNT*2;
+    }
+    else
+    {
+      m_hasSwitched = false;
+      m_endpointsToFetch = 1;
+    }
+}
+
+/*virtual*/ bool UbloxGSMModemInitializer::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+  if( m_hasSwitched )
+  {
+    DBG("Interface #%d; Class:%02x; SubClass:%02x; Protocol:%02x", intf_nb, intf_class, intf_subclass, intf_protocol);
+    if( intf_class == 0x0A )
+    {
+      if( (m_currentSerialIntf == 0) || (m_currentSerialIntf == 1) )
+      {
+        m_serialIntfMap[m_currentSerialIntf++] = intf_nb;
+        return true;
+      }
+      m_currentSerialIntf++;
+    }
+  }
+  else
+  {
+    if( (intf_nb == 0) && (intf_class == MSD_CLASS) )
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+/*virtual*/ bool UbloxGSMModemInitializer::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+  if( m_hasSwitched )
+  {
+    DBG("USBEndpoint on Interface #%d; Type:%d; Direction:%d", intf_nb, type, dir);
+    if( (type == BULK_ENDPOINT) && m_endpointsToFetch )
+    {
+      m_endpointsToFetch--;
+      return true;
+    }
+  }
+  else
+  {
+    if( (type == BULK_ENDPOINT) && (dir == OUT) && m_endpointsToFetch )
+    {
+      m_endpointsToFetch--;
+      return true;
+    }
+  }
+  return false;
+}
+
+/*virtual*/ int UbloxGSMModemInitializer::getType()
+{
+  return WAN_DONGLE_TYPE_UBX;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbloxGSMModemInitializer.h	Thu Oct 17 13:06:33 2013 +0300
@@ -0,0 +1,63 @@
+/* Copyright (c) 2010-2012 mbed.org, MIT License
+*
+* 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 UBLOXGSMMODEMINITIALIZER_H
+#define UBLOXGSNMODEMINITIALIZER_H
+
+#include "WANDongleInitializer.h"
+
+enum
+{
+  WAN_DONGLE_TYPE_UBX
+};
+
+//-----------------------------------------------------------------------
+// mamm, u-blox Modem
+//-----------------------------------------------------------------------
+
+class UbloxGSMModemInitializer : public WANDongleInitializer
+{
+public:
+    UbloxGSMModemInitializer(USBHost* pHost);
+    
+    virtual uint16_t getMSDVid();
+    virtual uint16_t getMSDPid();
+    
+    virtual uint16_t getSerialVid();
+    virtual uint16_t getSerialPid();
+    
+    virtual bool switchMode(USBDeviceConnected* pDev);
+    
+    virtual int getSerialPortCount();
+    
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+    
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+    
+    virtual int getType();
+
+private:
+
+  bool m_hasSwitched;
+  int m_currentSerialIntf;
+  int m_endpointsToFetch;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbloxUSBCDMAModem.cpp	Thu Oct 17 13:06:33 2013 +0300
@@ -0,0 +1,398 @@
+/* UbloxUSBCDMAModem.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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__ 4
+#ifndef __MODULE__
+#define __MODULE__ "UbloxUSBCDMAModem.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "UbloxUSBCDMAModem.h"
+#include "UbloxCDMAModemInitializer.h"
+#include "USBHost.h"
+
+#define USE_ONE_PORT 1
+
+UbloxUSBCDMAModem::UbloxUSBCDMAModem(PinName powerGatingPin /*= NC*/, bool powerGatingOnWhenPinHigh /* = true*/, int serial /* 0 */) : m_dongle(),
+m_stream(m_dongle.getSerial(serial)), 
+m_at(&m_stream),
+m_sms(&m_at), m_ppp(&m_stream, DEFAULT_MSISDN_CDMA),
+m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false),
+m_powerGatingPin(powerGatingPin), m_powerGatingOnWhenPinHigh(powerGatingOnWhenPinHigh)
+{
+  USBHost* host = USBHost::getHostInst();
+  m_dongle.addInitializer(new UbloxCDMAModemInitializer(host));
+  if( m_powerGatingPin != NC )
+  {
+    power(false); //Dongle will have to be powered on manually
+  }
+}
+
+class CSSProcessor : public IATCommandsProcessor
+{
+public:
+  CSSProcessor() : status(STATUS_REGISTERING)
+  {
+
+  }
+  enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK };
+  REGISTERING_STATUS getStatus()
+  {
+    return status;
+  }
+private:
+  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+  {
+    char b;
+		char bc[3] = "";
+		int sid = 99999; 
+		
+    //if( sscanf(line, "%*d, %c", &r) == 1 )
+    if(sscanf(line, "%*s %c,%2s,%d", &b,bc,&sid)==3)
+		{
+				if(strcmp("Z", bc) == 0)
+					status = STATUS_REGISTERING;
+				else
+					status = STATUS_OK;
+    }
+    return OK;
+  }
+  virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+  {
+    return OK;
+  }
+  volatile REGISTERING_STATUS status;
+};
+
+int UbloxUSBCDMAModem::connect(const char* apn, const char* user, const char* password)
+{
+  if( !m_ipInit )
+  {
+    m_ipInit = true;
+    m_ppp.init();
+  }
+  m_ppp.setup(user, password);
+
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  #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;
+
+  if(apn != NULL)
+  {
+    char cmd[48];
+    sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
+    ret = m_at.executeSimple(cmd, &result);
+    DBG("Result of command: Err code=%d", ret);
+    DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+    DBG("APN set to %s", apn);
+  }
+
+
+  //Connect
+  DBG("Connecting");
+  #if USE_ONE_PORT
+  m_at.close(); // Closing AT parser
+  m_atOpen = false; //Will need to be reinitialized afterwards
+  #endif
+
+  DBG("Connecting PPP");
+
+  ret = m_ppp.connect();
+  DBG("Result of connect: Err code=%d", ret);
+  return ret;
+}
+
+
+int UbloxUSBCDMAModem::disconnect()
+{
+  DBG("Disconnecting from PPP");
+  int ret = m_ppp.disconnect();
+  if(ret)
+  {
+    ERR("Disconnect returned %d, still trying to disconnect", ret);
+  }
+
+  //Ugly but leave dongle time to recover
+  Thread::wait(500);
+
+  #if USE_ONE_PORT
+  ATCommandsInterface::ATResult result;
+  DBG("Starting AT thread");
+  ret = m_at.open();
+  if(ret)
+  {
+    return ret;
+  }
+  #endif
+
+  DBG("Trying to hangup");
+
+  #if 0 //Does not appear to work
+  int tries = 10;
+  do
+  {
+    ret = m_at.executeSimple("+++", &result, 1000);
+    DBG("Result of command: Err code=%d\n", ret);
+    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+  } while(tries-- && ret);
+  if(!ret)
+  {
+    ret = m_at.executeSimple("ATH", &result);
+    DBG("Result of command: Err code=%d\n", ret);
+    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+  }
+  #endif
+
+  #if USE_ONE_PORT
+  //Reinit AT parser
+  ret = m_at.init();
+  DBG("Result of command: Err code=%d\n", ret);
+  if(ret)
+  {
+    m_at.close(); // Closing AT parser
+    DBG("AT Parser closed, could not complete disconnection");
+    return NET_TIMEOUT;
+  }
+
+  #if 0
+  m_at.close(); // Closing AT parser
+  DBG("AT Parser closed");
+  #endif
+  #endif
+  return OK;
+}
+
+int UbloxUSBCDMAModem::sendSM(const char* number, const char* message)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_smsInit)
+  {
+    ret = m_sms.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_smsInit = true;
+  }
+
+  ret = m_sms.send(number, message);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+int UbloxUSBCDMAModem::getSM(char* number, char* message, size_t maxLength)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_smsInit)
+  {
+    ret = m_sms.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_smsInit = true;
+  }
+
+  ret = m_sms.get(number, message, maxLength);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+int UbloxUSBCDMAModem::getSMCount(size_t* pCount)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_smsInit)
+  {
+    ret = m_sms.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_smsInit = true;
+  }
+
+  ret = m_sms.getCount(pCount);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+ATCommandsInterface* UbloxUSBCDMAModem::getATCommandsInterface()
+{
+  return &m_at;
+}
+
+int UbloxUSBCDMAModem::power(bool enable)
+{
+  if( m_powerGatingPin == NC )
+  {
+    return NET_INVALID; //A pin name has not been provided in the constructor
+  }
+
+  if(!enable) //Will force components to re-init
+  {
+    cleanup();
+  }
+  
+  DigitalOut powerGatingOut(m_powerGatingPin);
+  powerGatingOut = m_powerGatingOnWhenPinHigh?enable:!enable;
+
+  return OK;
+}
+
+bool UbloxUSBCDMAModem::power()
+{
+  if( m_powerGatingPin == NC )
+  {
+    return true; //Assume power is always on 
+  }
+  
+  DigitalOut powerGatingOut(m_powerGatingPin);
+  return m_powerGatingOnWhenPinHigh?powerGatingOut:!powerGatingOut;
+}
+
+int UbloxUSBCDMAModem::init()
+{
+  if( !m_dongleConnected )
+  {
+    if(!power())
+    {
+      //Obviously cannot initialize the dongle if it is disconnected...
+      ERR("Power is off");
+      return NET_INVALID;
+    }
+    m_dongleConnected = true;
+    while( !m_dongle.connected() )
+    {
+      m_dongle.tryConnect();
+      Thread::wait(100);
+    }
+  }
+
+  if(m_atOpen)
+  {
+    return OK;
+  }
+
+  DBG("Starting AT thread if needed");
+  int ret = m_at.open();
+  if(ret)
+  {
+    return ret;
+  }
+
+  DBG("Sending initialisation commands");
+  ret = m_at.init();
+  if(ret)
+  {
+    return ret;
+  }
+
+ if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOXC200)
+  {
+    INFO("Using a UBLOX C200 Dongle");
+  }
+  else
+  {
+    WARN("Using an Unknown Dongle");
+  }
+
+  ATCommandsInterface::ATResult result;
+
+  //Wait for network registration
+  CSSProcessor cssProcessor;
+  do
+  {
+    DBG("Waiting for network registration");
+    ret = m_at.execute("AT+CSS?", &cssProcessor, &result);
+    DBG("Result of command: Err code=%d\n", ret);
+    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+    if(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING)
+    {
+      Thread::wait(3000);
+    }
+  } while(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING);
+
+  m_atOpen = true;
+
+  return OK;
+}
+
+int UbloxUSBCDMAModem::cleanup()
+{
+  if(m_ppp.isConnected())
+  {
+    WARN("Data connection is still open"); //Try to encourage good behaviour from the user
+    m_ppp.disconnect(); 
+  }
+  
+  m_smsInit = false;
+//  m_linkMonitorInit = false;
+  //We don't reset m_ipInit as PPPIPInterface::init() only needs to be called once
+  
+  if(m_atOpen)
+  {
+    m_at.close();
+    m_atOpen = false;
+  }
+  
+  m_dongle.disconnect();
+  m_dongleConnected = false;
+  
+  return OK;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbloxUSBCDMAModem.h	Thu Oct 17 13:06:33 2013 +0300
@@ -0,0 +1,117 @@
+/* UbloxUSBCDMAModem.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 UBLOXUSBCDMAMODEM_H_
+#define UBLOXUSBCDMAMODEM_H_
+
+#include "core/fwk.h"
+
+#include "WANDongle.h"
+#include "at/ATCommandsInterface.h"
+#include "USBSerialStream.h"
+#include "ip/PPPIPInterface.h"
+#include "sms/CDMASMSInterface.h"
+
+/** u-blox LISA-C200 modem
+ */
+class UbloxUSBCDMAModem
+{
+public:
+  /** Create Sprint USB Modem (Sierra Wireless 598U) API instance
+      @param powerGatingPin Optional pin commanding a power gating transistor on the modem's power line 
+      @param powerGatingOnWhenPinHigh true if the pin needs to be high to power the dongle, defaults to true
+   */
+  UbloxUSBCDMAModem(PinName powerGatingPin = NC, bool powerGatingOnWhenPinHigh = true, int serial = 0);
+
+  //Internet-related functions
+
+  /** Open a 3G internet connection
+      @return 0 on success, error code on failure
+  */
+  int connect(const char* apn = NULL, const char* user = NULL, const char* password = NULL);
+
+  /** Close the internet connection
+     @return 0 on success, error code on failure
+  */
+  int disconnect();
+
+
+  /** Send a SM
+     @param number The receiver's phone number
+     @param message The message to send
+     @return 0 on success, error code on failure
+   */
+  int sendSM(const char* number, const char* message);
+
+
+  /** Receive a SM
+     @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the sapce for the null-terminating char)
+     @param message Pointer to a buffer to store the the incoming message
+     @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+     @return 0 on success, error code on failure
+   */
+  int getSM(char* number, char* message, size_t maxLength);
+
+  /** Get the number of SMs in the incoming box
+     @param pCount pointer to store the number of unprocessed SMs on
+     @return 0 on success, error code on failure
+   */
+  int getSMCount(size_t* pCount);
+
+  /** Get the ATCommandsInterface instance
+     @return Pointer to the ATCommandsInterface instance
+   */
+  ATCommandsInterface* getATCommandsInterface();
+
+  /** Switch power on or off
+    In order to use this function, a pin name must have been entered in the constructor
+    @param enable true to switch the dongle on, false to switch it off
+    @return 0 on success, error code on failure
+  */
+  int power(bool enable);
+
+protected:
+  bool power();
+  
+  int init();
+  int cleanup();
+
+private:
+  WANDongle m_dongle;
+  
+  USBSerialStream m_stream;
+  
+  ATCommandsInterface m_at;
+  
+  CDMASMSInterface m_sms;
+  
+  PPPIPInterface m_ppp;
+
+  bool m_dongleConnected;
+  bool m_ipInit;
+  bool m_smsInit;
+  bool m_atOpen;
+  
+  PinName m_powerGatingPin;
+  bool m_powerGatingOnWhenPinHigh;
+};
+
+
+#endif /* UBLOXUSBCDMAMODEM_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbloxUSBGSMModem.cpp	Thu Oct 17 13:06:33 2013 +0300
@@ -0,0 +1,605 @@
+/* UbloxUSBGSMModem.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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__ 3
+#ifndef __MODULE__
+#define __MODULE__ "UbloxUSBGSMModem.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "UbloxUSBGSMModem.h"
+#include "UbloxGSMModemInitializer.h"
+#include "USBHost.h"
+
+UbloxUSBGSMModem::UbloxUSBGSMModem(PinName powerGatingPin /*= NC*/, bool powerGatingOnWhenPinHigh /* = true*/) :
+   m_dongle(),                              // Construct WANDongle: USB interface with two serial channels to the modem (USBSerialStream objects)
+   m_atStream(m_dongle.getSerial(1)),       // AT commands are sent down one serial channel.
+   m_pppStream(m_dongle.getSerial(0)),      // PPP connections are managed via another serial channel.
+   m_at(&m_atStream),                       // Construct ATCommandsInterface with the AT serial channel
+   m_sms(&m_at),                            // Construct SMSInterface with the ATCommandsInterface
+   m_ussd(&m_at),                           // Construct USSDInterface with the ATCommandsInterface
+   m_linkMonitor(&m_at),                    // Construct LinkMonitor with the ATCommandsInterface
+   m_ppp(&m_pppStream, DEFAULT_MSISDN_GSM), // Construct PPPIPInterface with the PPP serial channel
+   m_dongleConnected(false),                // Dongle is initially not ready for anything
+   m_ipInit(false),                         // PPIPInterface connection is initially down
+   m_smsInit(false),                        // SMSInterface starts un-initialised
+   m_ussdInit(false),                       // USSDInterface starts un-initialised 
+   m_linkMonitorInit(false),                // LinkMonitor subsystem starts un-initialised
+   m_atOpen(false),                         // ATCommandsInterface starts in a closed state
+   m_powerGatingPin(powerGatingPin),        // set power gating pin
+   m_powerGatingOnWhenPinHigh(powerGatingOnWhenPinHigh) // set state semantics for power gating pin
+{
+  USBHost* host = USBHost::getHostInst();
+  m_dongle.addInitializer(new UbloxGSMModemInitializer(host));
+  if( m_powerGatingPin != NC )
+  {
+    power(false); //Dongle will have to be powered on manually
+  }
+}
+
+class CREGProcessor : public IATCommandsProcessor
+{
+public:
+  CREGProcessor() : status(STATUS_REGISTERING)
+  {
+
+  }
+  enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK, STATUS_FAILED };
+  REGISTERING_STATUS getStatus()
+  {
+    return status;
+  }
+private:
+  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+  {
+    int r;
+    if( sscanf(line, "+CREG: %*d,%d", &r) == 1 )
+    {
+      switch(r)
+      {
+      case 1:
+      case 5:
+        status = STATUS_OK;
+        break;
+      case 0:
+      case 2:
+        status = STATUS_REGISTERING;
+        break;
+      case 3:
+      default:
+        status = STATUS_FAILED;
+        break;
+      }
+    }
+    return OK;
+  }
+  virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+  {
+    return OK;
+  }
+  volatile REGISTERING_STATUS status;
+};
+
+#if 0
+class COPSProcessor : public IATCommandsProcessor
+{
+public:
+  COPSProcessor() : valid(false)
+  {
+    network[0] = '\0';
+    apn[0] = '\0';
+    bearer[0] = '\0';
+  }
+  char* getNetwork()
+  {
+    return network;
+  }
+  char* getAPN()
+  {
+    return apn;
+  }
+  char* getBearer()
+  {
+    return bearer;
+  }
+  bool isValid()
+  {
+    return valid;
+  }
+private:
+  virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+  {
+    int networkId;
+    int bearerId;
+    int s = sscanf(line, "+COPS: %*d,%*d,\"%d\",%d", &networkId, &bearerId);
+    if( s == 2 )
+    {
+      switch(networkId)
+      {
+      case 23415:
+        strcpy(network, "Vodafone UK");
+        strcpy(apn, "pp.vodafone.co.uk");
+        valid = true;
+        break;
+      case 20810:
+        strcpy(network, "SFR FR");
+        strcpy(apn, "websfr");
+        valid = true;
+        break;
+      default:
+        break;
+      }
+    }
+    else
+    {
+      return OK;
+    }
+    switch(bearerId)
+    {
+    case 0: strcpy(bearer, "GSM"); break;
+    case 1: strcpy(bearer, "GSM Compact"); break;
+    case 2: strcpy(bearer, "UTRAN"); break;
+    case 3: strcpy(bearer, "GSM w/EGPRS"); break;
+    case 4: strcpy(bearer, "UTRAN w/HSDPA"); break;
+    case 5: strcpy(bearer, "UTRAN w/HSUPA"); break;
+    case 6: strcpy(bearer, "UTRAN w/HSDPA and HSUPA"); break;
+    case 7: strcpy(bearer, "E-UTRAN"); break;
+
+    default:
+      break;
+    }
+    return OK;
+  }
+  virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+  {
+    return OK;
+  }
+  char network[24];
+  char bearer[24];
+  char apn[24];
+  volatile bool valid;
+};
+#endif
+
+int UbloxUSBGSMModem::connect(const char* apn, const char* user, const char* password)
+{
+  if( !m_ipInit )
+  {
+    m_ipInit = true;
+    m_ppp.init();
+  }
+  m_ppp.setup(user, password);
+
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  #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;
+
+  #if 0
+  //Get network info & select corresponding APN
+  COPSProcessor copsProcessor;
+  DBG("Get network info & select APN from DB");
+  ret = m_at.execute("AT+COPS=,2;+COPS?", &copsProcessor, &result); //Configure to get operator's info in numeric code & get operator's id
+  DBG("Result of command: Err code=%d", ret);
+  DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+
+  if(!copsProcessor.isValid())
+  {
+    WARN("Connected to an unknown network, try to connect with default parameters");
+    DBG("Connected with %s", copsProcessor.getBearer());
+  }
+  else
+  {
+    DBG("Connected to %s with %s", copsProcessor.getNetwork(), copsProcessor.getBearer());
+    char cmd[48];
+    int tries = 3;
+    sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", copsProcessor.getAPN());
+    do //Try 3 times because for some reasons it can fail with the K3772-Z dongle
+    {
+      ret = m_at.executeSimple(cmd, &result);
+      DBG("Result of command: Err code=%d", ret);
+    } while(ret && --tries);
+    DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+    DBG("APN set to %s", copsProcessor.getAPN());
+  }
+  #else
+  if(apn != NULL)
+  {
+    char cmd[48];
+    int tries = 30;
+    sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
+    do //Try 30 times because for some reasons it can fail *a lot* with the K3772-Z dongle
+    {
+      ret = m_at.executeSimple(cmd, &result);
+      DBG("Result of command: Err code=%d", ret);
+      if(ret)
+      {
+        Thread::wait(500);
+      }
+    } while(ret && --tries);
+    DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+    DBG("APN set to %s", apn);
+  }
+  #endif
+
+
+  //Connect
+  DBG("Connecting");
+  #if 0
+  ret = m_at.executeSimple("ATDT *99#", &result);
+  DBG("Result of command: Err code=%d", ret);
+  DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+  #endif
+  #if USE_ONE_PORT
+  m_at.close(); // Closing AT parser
+  m_atOpen = false; //Will need to be reinitialized afterwards
+  #endif
+
+  #if 0
+  DBG("AT Parser closed");
+  if( (ret!=NET_MOREINFO) || (result.result != ATCommandsInterface::ATResult::AT_CONNECT))
+  {
+    ERR("Could not connect");
+    return ret; //Could not connect
+  }
+  #endif
+  DBG("Connecting PPP");
+
+  ret = m_ppp.connect();
+  DBG("Result of connect: Err code=%d", ret);
+  return ret;
+}
+
+
+int UbloxUSBGSMModem::disconnect()
+{
+  DBG("Disconnecting from PPP");
+  int ret = m_ppp.disconnect();
+  if(ret)
+  {
+    ERR("Disconnect returned %d, still trying to disconnect", ret);
+  }
+
+  //Ugly but leave dongle time to recover
+  Thread::wait(500);
+
+  #if USE_ONE_PORT
+  ATCommandsInterface::ATResult result;
+  DBG("Starting AT thread");
+  ret = m_at.open();
+  if(ret)
+  {
+    return ret;
+  }
+  #endif
+
+  DBG("Trying to hangup");
+
+  #if 0 //Does not appear to work
+  int tries = 10;
+  do
+  {
+    ret = m_at.executeSimple("+++", &result, 1000);
+    DBG("Result of command: Err code=%d\n", ret);
+    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+  } while(tries-- && ret);
+  if(!ret)
+  {
+    ret = m_at.executeSimple("ATH", &result);
+    DBG("Result of command: Err code=%d\n", ret);
+    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+  }
+  #endif
+
+  #if USE_ONE_PORT
+  //Reinit AT parser
+  ret = m_at.init();
+  DBG("Result of command: Err code=%d\n", ret);
+  if(ret)
+  {
+    m_at.close(); // Closing AT parser
+    DBG("AT Parser closed, could not complete disconnection");
+    return NET_TIMEOUT;
+  }
+
+  #if 0
+  m_at.close(); // Closing AT parser
+  DBG("AT Parser closed");
+  #endif
+  #endif
+  return OK;
+}
+
+int UbloxUSBGSMModem::sendSM(const char* number, const char* message)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_smsInit)
+  {
+    ret = m_sms.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_smsInit = true;
+  }
+
+  ret = m_sms.send(number, message);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+int UbloxUSBGSMModem::getSM(char* number, char* message, size_t maxLength)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_smsInit)
+  {
+    ret = m_sms.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_smsInit = true;
+  }
+
+  ret = m_sms.get(number, message, maxLength);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+int UbloxUSBGSMModem::getSMCount(size_t* pCount)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_smsInit)
+  {
+    ret = m_sms.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_smsInit = true;
+  }
+
+  ret = m_sms.getCount(pCount);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+int UbloxUSBGSMModem::sendUSSD(const char* command, char* result, size_t maxLength)
+{
+  int ret = init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(!m_ussdInit)
+  {
+    ret = m_ussd.init();
+    if(ret)
+    {
+      return ret;
+    }
+    m_ussdInit = true;
+  }
+
+  ret = m_ussd.send(command, result, maxLength);
+  if(ret)
+  {
+    return ret;
+  }
+
+  return OK;
+}
+
+int UbloxUSBGSMModem::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* UbloxUSBGSMModem::getATCommandsInterface()
+{
+  return &m_at;
+}
+
+int UbloxUSBGSMModem::power(bool enable)
+{
+  if( m_powerGatingPin == NC )
+  {
+    return NET_INVALID; //A pin name has not been provided in the constructor
+  }
+
+  if(!enable) //Will force components to re-init
+  {
+    cleanup();
+  }
+  
+  DigitalOut powerGatingOut(m_powerGatingPin);
+  powerGatingOut = m_powerGatingOnWhenPinHigh?enable:!enable;
+
+  return OK;
+}
+
+bool UbloxUSBGSMModem::power()
+{
+  if( m_powerGatingPin == NC )
+  {
+    return true; //Assume power is always on 
+  }
+  
+  DigitalOut powerGatingOut(m_powerGatingPin);
+  return m_powerGatingOnWhenPinHigh?powerGatingOut:!powerGatingOut;
+}
+
+int UbloxUSBGSMModem::init()
+{
+  if( !m_dongleConnected )
+  {
+    if(!power())
+    {
+      //Obviously cannot initialize the dongle if it is disconnected...
+      ERR("Power is off");
+      return NET_INVALID;
+    }
+    m_dongleConnected = true;
+    while( !m_dongle.connected() )
+    {
+      m_dongle.tryConnect();
+      Thread::wait(10);
+    }
+  }
+
+  if(m_atOpen)
+  {
+    return OK;
+  }
+  
+  DBG("Starting AT thread if needed");
+  int ret = m_at.open();
+  if(ret)
+  {
+    return ret;
+  }
+  
+  DBG("Sending initialisation commands");
+  ret = m_at.init();
+  if(ret)
+  {
+    return ret;
+  }
+
+  if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBX)
+  {
+    INFO("Using a u-blox LISA-U");
+  }
+  else
+  {
+    WARN("Using an Unknown Dongle");
+  }
+
+  ATCommandsInterface::ATResult result;
+
+  //Wait for network registration
+  CREGProcessor cregProcessor;
+  do
+  {
+    DBG("Waiting for network registration");
+    ret = m_at.execute("AT+CREG?", &cregProcessor, &result);
+    DBG("Result of command: Err code=%d\n", ret);
+    DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+    if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING)
+    {
+      Thread::wait(3000);
+    }
+  } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING);
+  if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED)
+  {
+    ERR("Registration denied");
+    return NET_AUTH;
+  }
+
+  m_atOpen = true;
+
+  return OK;
+}
+
+int UbloxUSBGSMModem::cleanup()
+{
+  if(m_ppp.isConnected())
+  {
+    WARN("Data connection is still open"); //Try to encourage good behaviour from the user
+    m_ppp.disconnect(); 
+  }
+  
+  m_smsInit = false;
+  m_ussdInit = false;
+  m_linkMonitorInit = false;
+  //We don't reset m_ipInit as PPPIPInterface::init() only needs to be called once
+  
+  if(m_atOpen)
+  {
+    m_at.close();
+    m_atOpen = false;
+  }
+  
+  m_dongle.disconnect();
+  m_dongleConnected = false;
+  
+  return OK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbloxUSBGSMModem.h	Thu Oct 17 13:06:33 2013 +0300
@@ -0,0 +1,154 @@
+/* VodafoneUSBModem.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * 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 UBLOXUSBGSMMODEM_H_
+#define UBLOXUSBGSMMODEM_H_
+
+#include "core/fwk.h"
+
+#include "WANDongle.h"
+#include "at/ATCommandsInterface.h"
+#include "serial/usb/USBSerialStream.h"
+#include "ip/PPPIPInterface.h"
+#include "sms/GSMSMSInterface.h"
+#include "ussd/USSDInterface.h"
+#include "link/LinkMonitor.h"
+
+/** u-blox WCDMA modem (LISA-U200)
+ */
+class UbloxUSBGSMModem
+{
+public:
+  /** Create u-blox API instance
+      @param powerGatingPin Optional pin commanding a power gating transistor on the modem's power line 
+      @param powerGatingOnWhenPinHigh true if the pin needs to be high to power the dongle, defaults to true
+   */
+  UbloxUSBGSMModem(PinName powerGatingPin = NC, bool powerGatingOnWhenPinHigh = true);
+
+  //Internet-related functions
+
+  /** Open a 3G internet connection
+      @return 0 on success, error code on failure
+  */
+  int connect(const char* apn = NULL, const char* user = NULL, const char* password = NULL);
+
+  /** Close the internet connection
+     @return 0 on success, error code on failure
+  */
+  int disconnect();
+
+
+  /** Send a SM
+     @param number The receiver's phone number
+     @param message The message to send
+     @return 0 on success, error code on failure
+   */
+  int sendSM(const char* number, const char* message);
+
+
+  /** Receive a SM
+     @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the sapce for the null-terminating char)
+     @param message Pointer to a buffer to store the the incoming message
+     @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+     @return 0 on success, error code on failure
+   */
+  int getSM(char* number, char* message, size_t maxLength);
+
+  /** Get the number of SMs in the incoming box
+     @param pCount pointer to store the number of unprocessed SMs on
+     @return 0 on success, error code on failure
+   */
+  int getSMCount(size_t* pCount);
+
+  /** Send a USSD command & wait for its result
+    @param command The command to send
+    @param result Buffer in which to store the result
+    @param maxLength Maximum result length that can be stored in buffer (including null-terminating character)
+    @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
+   */
+  ATCommandsInterface* getATCommandsInterface();
+  
+  /** Switch power on or off
+    In order to use this function, a pin name must have been entered in the constructor
+    @param enable true to switch the dongle on, false to switch it off
+    @return 0 on success, error code on failure
+  */
+  int power(bool enable);
+
+protected:
+  bool power(); //< Turn power to USB dongle ON.
+
+  /** Initialise dongle.
+   * The following actions are performed:
+   * 1) Power up
+   * 2) Establish USB connection to dongle
+   * 3) Start AT interface thread
+   * 4) Wait for network registration
+   */
+  int init();
+  
+  /** De-initialise dongle.
+   * The following actions are performed:
+   * 1) Tear down PPP session
+   * 2) Set SMS,USSD, and LinkMonitor subsystems to un-initialised
+   * 3) Close the AT commands interface
+   * 4) Tear down the USB connection to dongle
+   */
+  int cleanup();
+
+private:
+  WANDongle m_dongle;          //< Interface to USB connected WAN dongle
+  
+  USBSerialStream m_atStream;  //< Serial interface to AT channel on modem
+  USBSerialStream m_pppStream; //< Serial interface to PPP channel on modem
+  
+  ATCommandsInterface m_at;    //< Interface to AT commands processing
+  
+  GSMSMSInterface m_sms;       //< Interface to SMS manager (send/receive etc)
+  USSDInterface m_ussd;        //< Interface to USSD manager (send etc)
+  LinkMonitor m_linkMonitor;   //< Interface to link monitor (RSSI)
+  
+  PPPIPInterface m_ppp;        //< Interface to PPP conection manager (IP assignment etc)
+
+  bool m_dongleConnected; //< Is the dongle physically connected (does the USB stack respond)? true/false
+  bool m_ipInit;          //< Has PPIPInterface object (m_ppp) been initialised? true/false
+  bool m_smsInit;         //< Has SMSInterface object (m_sms) been initialised? true/false
+  bool m_ussdInit;        //< Has USSDInterface object (m_ussd) been initialised? true/false
+  bool m_linkMonitorInit; //< Has LinkMonitor object (m_linkMonitor) been initialised? true/false
+  bool m_atOpen;          //< Is the interface to the ATCommandsInterface open? true/false
+  
+  PinName m_powerGatingPin;        //< Pin which toggles power gating
+  bool m_powerGatingOnWhenPinHigh; //< Semantics of power gating (whether high or low toggles power gating)
+};
+
+
+#endif /* UBLOXMODEM_H_ */