USB Host Library for Sprint Dongles

Dependencies:   Socket USBHostWANDongleSprint lwip-sys lwip

Dependents:   SprintUSBModemWebsocketTest SprintUSBModemHTTPClientTest SprintUSBModemNTPClientTest SprintUSBModemSMSTest ... more

Fork of SprintUSBModem_bleedingedge by Donatien Garnier

Revision:
0:8f57713b2147
Child:
2:f4d9c4ea17f9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SprintUSBModem.cpp	Wed Sep 12 09:34:21 2012 +0000
@@ -0,0 +1,340 @@
+/* SprintUSBModem.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__ "SprintUSBModem.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "SprintUSBModem.h"
+
+SprintUSBModem::SprintUSBModem() : m_dongle(),
+m_atStream(m_dongle.getSerial(1)), m_pppStream(m_dongle.getSerial(0)), m_at(&m_atStream),
+m_sms(&m_at), m_ppp(&m_pppStream), 
+m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false)
+{
+
+}
+
+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;
+};
+
+int SprintUSBModem::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 SprintUSBModem::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 SprintUSBModem::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 SprintUSBModem::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 SprintUSBModem::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* SprintUSBModem::getATCommandsInterface()
+{
+  return &m_at;
+}
+
+int SprintUSBModem::init()
+{
+  if( !m_dongleConnected )
+  {
+    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_SPRINT598U)
+  {
+    INFO("Using a Sprint 598U Dongle");
+  }
+  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;
+}
+
+