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:
ashleymills
Date:
Tue Mar 05 14:54:15 2013 +0000
Parent:
82:ab4d6263f25c
Child:
84:39e28d162195
Commit message:
Added MU509 support

Changed in this revision

VodafoneUSBModem.cpp Show annotated file Show diff for this revision Revisions of this file
at/ATCommandsInterface.cpp Show annotated file Show diff for this revision Revisions of this file
at/ATCommandsInterface.h Show annotated file Show diff for this revision Revisions of this file
serial/usb/USBSerialStream.cpp 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/VodafoneUSBModem.cpp	Tue Jan 29 13:49:23 2013 +0000
+++ b/VodafoneUSBModem.cpp	Tue Mar 05 14:54:15 2013 +0000
@@ -593,10 +593,17 @@
      
      // this modem defaults to sending a delivery receipt to the SM storage area
      // need to disable this for the current library to work in a sensible manner
+     INFO("Disabling SMS delivery receipts"); 
      ret = m_at.executeSimple("at+csmp=1,,0,0",NULL);
      if(ret!=0) {
         return NET_PROTOCOL;
      }
+     INFO("Disabling unsolicitied notifications");
+     ret = m_at.executeSimple("AT^CURC=0", NULL); //Huawei-specific, not 3GPP-compliant
+     if(ret != OK)
+     {
+      return NET_PROTOCOL;
+     } 
   }
   else
   {
--- a/at/ATCommandsInterface.cpp	Tue Jan 29 13:49:23 2013 +0000
+++ b/at/ATCommandsInterface.cpp	Tue Mar 05 14:54:15 2013 +0000
@@ -32,25 +32,34 @@
 #include "ATCommandsInterface.h"
 
 ATCommandsInterface::ATCommandsInterface(IOStream* pStream) :
-   m_pStream(pStream), m_open(false), m_env2AT(), m_AT2Env(), m_processingMtx(),
-   m_processingThread(&ATCommandsInterface::staticCallback, this, (osPriority)AT_THREAD_PRIORITY, 4*192),
-   m_eventsMgmtMtx(), m_eventsProcessingMtx()
+   m_pStream(pStream), // this is the serial interface to the modem
+   m_open(false),      // AT interface is initially in a closed state
+   m_env2AT(),         // send messages from calling functions to AT parsing thread
+   m_AT2Env(),         // send messages from AT parsing thread to calling functions
+   m_processingMtx(),  // mutex for processing thread
+   m_processingThread( // construct processing thread
+      &ATCommandsInterface::staticCallback, // static callback uses this pointer to run process()
+      this,
+      (osPriority)AT_THREAD_PRIORITY,       // normal priority
+      4*192                                 // size of the processing thread
+   ),
+   m_eventsMgmtMtx(),       // mutex for managing events
+   m_eventsProcessingMtx()  // mutex for processing events
 {
-  memset(m_eventsHandlers, 0, MAX_AT_EVENTS_HANDLERS * sizeof(IATEventsHandler*));
-
-  m_processingMtx.lock();
+   // zero the memory for the event handler pointers
+   memset(m_eventsHandlers, 0, MAX_AT_EVENTS_HANDLERS * sizeof(IATEventsHandler*));
+   m_processingMtx.lock();
 }
 
-//Open connection to AT Interface in order to execute command & register/unregister events
-int ATCommandsInterface::open()
-{
-  if( m_open )
-  {
+// open connection to AT Interface in order to execute command & register/unregister events
+int ATCommandsInterface::open() {
+  if( m_open ) {
     WARN("AT interface is already open");
     return OK;
   }
   DBG("Opening AT interface");
-  //Start processing
+  
+  // start processing
   m_processingThread.signal_set(AT_SIG_PROCESSING_START);
 
   m_processingMtx.unlock();
@@ -62,7 +71,7 @@
   return OK;
 }
 
-//Initialize AT link & start events processing
+// initialize AT link & start events processing
 int ATCommandsInterface::init()
 {
   DBG("Sending ATZ E1 V1");
@@ -70,7 +79,8 @@
   //Lock transaction mutex
   m_transactionMtx.lock();
   
-  //Should we flush m_pStream at this point ???
+  // should we flush m_pStream at this point ???
+  // ash - it would do no harm so we should, incase some pending crap arrives
   int err;
   int tries = 5;
   do
@@ -121,6 +131,7 @@
   m_processingThread.signal_set(AT_SIG_PROCESSING_STOP);
   //m_stopSphre.release();
 
+  // ash - don't know why he sends this as it is never used XXX
   int* msg = m_env2AT.alloc(osWaitForever);
   *msg = AT_STOP;
   m_env2AT.put(msg); //Used to unstall the process if needed
@@ -157,7 +168,7 @@
 
   //Lock transaction mutex
   m_transactionMtx.lock();
-  
+  DBG("ATCommandsInterface::execute");
   disableEvents(); //Disable unsollicited result codes
   int ret = executeInternal(command, pProcessor, pResult, timeout);
   enableEvents(); //Re-enable unsollicited result codes whatever the result of the command is
@@ -244,6 +255,7 @@
   m_pStream->abortRead(); //This is thread-safe
 
   //Wait for a result (get result message)
+  DBG("Timeout: %d",timeout);
   evt = m_AT2Env.get(timeout);
 
   if(evt.status != osEventMail)
@@ -264,7 +276,7 @@
       evt = m_AT2Env.get(osWaitForever);
       msgResult = *((int*) evt.value.p);
       m_AT2Env.free((int*)evt.value.p);
-    } while(msgResult != AT_TIMEOUT);  
+    } while(msgResult != AT_TIMEOUT  );  
 
     WARN("Command returned no message");
     return NET_TIMEOUT;
@@ -296,6 +308,7 @@
   //Block on serial read or incoming command
   DBG("Trying to read a new line from stream");
   int ret = m_pStream->waitAvailable(); //This can be aborted
+
   size_t readLen = 0;
   if(ret == OK)
   {
@@ -310,7 +323,7 @@
 
   if( ret == NET_INTERRUPTED ) //It is worth checking readLen as data might have been read even though the read was interrupted
   {
-    DBG("Read was interrupted");
+    DBG("Read was interrupted with %d chars read",readLen);
     return NET_INTERRUPTED; //0 chars were read
   }
   else if(readLen == 0)
@@ -573,7 +586,7 @@
       {
         WARN("Previous command not processed!");
       }
-      DBG("Sending pending command");
+      DBG("Sending pending command %s (%d)",m_transactionCommand,strlen(m_transactionCommand));
       m_pStream->write((uint8_t*)m_transactionCommand, strlen(m_transactionCommand), osWaitForever);
       char cr = CR;
       m_pStream->write((uint8_t*)&cr, 1, osWaitForever); //Carriage return line terminator
@@ -581,6 +594,7 @@
     }
     else //Timeout
     {
+      DBG("Timeout message received");
       //Acknowledge
       int* msg = m_AT2Env.alloc(osWaitForever);
       *msg = AT_TIMEOUT;
@@ -740,6 +754,7 @@
 //This will be called on initialization & after the execution of a command
 void ATCommandsInterface::enableEvents()
 {
+  DBG("Trying to enable events");
   //Advertize this to events handlers
   m_eventsMgmtMtx.lock();
   for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot
@@ -750,10 +765,13 @@
       //Enable this kind of events
       if(m_eventsHandlers[i]->getEventsEnableCommand() != NULL)
       {
+        DBG("Enabling events for handler %d",i);
         int ret = executeInternal(m_eventsHandlers[i]->getEventsEnableCommand(), this, NULL); //Execute enable command
         if(ret)
         {
-          WARN("Events enabling command failed");
+          WARN("Events enabling command failed: %d",ret);
+        } else {
+           DBG("Enabled events");
         }
       }
     }
--- a/at/ATCommandsInterface.h	Tue Jan 29 13:49:23 2013 +0000
+++ b/at/ATCommandsInterface.h	Tue Mar 05 14:54:15 2013 +0000
@@ -139,7 +139,7 @@
   char m_inputBuf[AT_INPUT_BUF_SIZE]; // Stores characters received from the modem.
   int m_inputPos; // Current position of fill pointer in the input buffer.
 
-  Mutex m_transactionMtx;
+  Mutex m_transactionMtx; // used to lock access to the serial stream sending AT commands
 
   // These are RTOS queues, concurrent access protected. In this case both only contain an integer.
   Mail<int,1> m_env2AT; // used by calling function to inform processing thread of events
@@ -147,8 +147,8 @@
 
   IATEventsHandler* m_eventsHandlers[MAX_AT_EVENTS_HANDLERS]; // all registered events handlers
 
-  Mutex m_processingMtx;
-  Thread m_processingThread;
+  Mutex m_processingMtx; // not sure why you need a lock for the processing thread, as nobody else accesses it
+  Thread m_processingThread; // this is the at parsing thread, i.e the function process()
 
   Mutex m_eventsMgmtMtx; // locks access to event handler management (adding/removing handlers)
   Mutex m_eventsProcessingMtx; //Lock events use within the processing thread
--- a/serial/usb/USBSerialStream.cpp	Tue Jan 29 13:49:23 2013 +0000
+++ b/serial/usb/USBSerialStream.cpp	Tue Mar 05 14:54:15 2013 +0000
@@ -17,6 +17,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+
+
 #define __DEBUG__ 0
 #ifndef __MODULE__
 #define __MODULE__ "USBSerialStream.cpp"
@@ -28,6 +30,29 @@
 
 #include "USBSerialStream.h"
 
+// XXX ashley's debug 
+void printBuffer(uint8_t* buf, int len, bool readIn) {
+  
+  if(len<0) {
+     return;
+  }
+  
+  if(readIn) {
+     printf("Read(%d): '",len);
+  } else {
+     printf("Writing(%d): '",len);
+  }
+  for(int i=0; i<len; i++) {
+     if(buf[i]==0x0a) {
+        putchar('N');
+     } else if(buf[i]==0x0d) {
+        putchar('R');
+     } else {
+        putchar(buf[i]);
+     }
+  }
+  printf("'\r\n");
+}
 
 USBSerialStream::USBSerialStream(IUSBHostSerial& serial) : m_serial(serial), m_serialTxFifoEmpty(true),
 m_availableSphre(1), m_spaceSphre(1), m_inBuf()
@@ -46,6 +71,7 @@
 //0 for non-blocking (returns immediately), -1 for infinite blocking
 /*virtual*/ int USBSerialStream::read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout/*=osWaitForever*/)
 {
+  uint8_t *bufPointerCopy = buf;
   DBG("Trying to read at most %d chars", maxLength);
   int ret = waitAvailable(timeout);
   if(ret)
@@ -56,7 +82,8 @@
   int a = available(); //Prevent macro issues
   int readLen = MIN( a, maxLength );
   *pLength = readLen;
-
+  
+  
   setupReadableISR(false);
   while(readLen--)
   {
@@ -64,7 +91,8 @@
     buf++;
   }
   setupReadableISR(true);
-  DBG("Read %d chars successfully", *pLength);
+  //printBuffer(bufPointerCopy,*pLength,true); // XXX
+  
   return OK;
 }
 
@@ -130,9 +158,12 @@
   m_availableSphre.release(); //Force exiting the waiting state
 }
 
+
+
 //0 for non-blocking (returns immediately), -1 for infinite blocking
 /*virtual*/ int USBSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=-1*/)
 {
+  //printBuffer(buf,length,false); // XXX
   DBG("Trying to write %d chars", length);
   do
   {
@@ -160,7 +191,6 @@
     }
     setupWriteableISR(true);
   } while(length);
-
   DBG("Write successful");
   return OK;
 }
--- a/sms/SMSInterface.cpp	Tue Jan 29 13:49:23 2013 +0000
+++ b/sms/SMSInterface.cpp	Tue Mar 05 14:54:15 2013 +0000
@@ -33,6 +33,7 @@
 
 SMSInterface::SMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL)
 {
+  DBG("registering sms");
   m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
 }
 
@@ -240,8 +241,9 @@
   }
   else if(m_state == SMS_GET_HDR_RECEIVED)
   {
-    DBG("Message: %s", line);
+    
     size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 );
+    DBG("Message: %s (%d)", line, cpyLen);
     std::memcpy( m_msg, line, cpyLen );
     m_msg[cpyLen] = '\0';
     m_state = SMS_CMD_PROCESSED;
@@ -356,7 +358,6 @@
   {
     return; //Not supported
   }
-  
 
   DBG("Unsollicited result code: %s - %s", atCode, evt);
 
--- a/ussd/USSDInterface.cpp	Tue Jan 29 13:49:23 2013 +0000
+++ b/ussd/USSDInterface.cpp	Tue Mar 05 14:54:15 2013 +0000
@@ -17,7 +17,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#define __DEBUG__ 0
+#define __DEBUG__ 4
 #ifndef __MODULE__
 #define __MODULE__ "USSDInterface.cpp"
 #endif
@@ -34,6 +34,7 @@
 USSDInterface::USSDInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_responseMtx(), m_responseSphre(1), m_result(NULL), m_maxResultLength(0)
 {
   m_responseSphre.wait(0); //Take ownership of the semaphore
+  DBG("events handler reg ussd");
   m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
 }
 
@@ -45,7 +46,7 @@
 
 int USSDInterface::send(const char* command, char* result, size_t maxLength)
 {
-  if (strlen(command) > 20) //Prevent buffer overflow
+  if (strlen(command) > 20) //Prevent buffer overflow XXX shouldn't this be 19 as the AT+CUSD=1,"" is 12
   {
     return NET_TOOSMALL;
   }
@@ -188,6 +189,7 @@
     return;
   }
   size_t cpyLen = MIN( pEnd - pStart, m_maxResultLength - 1 );
+  DBG("cpyLen: %d",cpyLen);
   memcpy((void*)m_result, pStart, cpyLen);
   m_result[cpyLen] = '\0';
   DBG("Got USSD response: %s", m_result);