Implementation of 3G USB Modem Huawei E372
Revision 2:61ac95f0af72, committed 2015-04-14
- Comitter:
- clemounet
- Date:
- Tue Apr 14 13:27:07 2015 +0000
- Parent:
- 1:fbf17fb09581
- Commit message:
- .up (working)
Changed in this revision
--- a/ATCommandsInterface.cpp Fri Feb 20 17:15:55 2015 +0000 +++ b/ATCommandsInterface.cpp Tue Apr 14 13:27:07 2015 +0000 @@ -17,7 +17,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "dbg.h" +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "ATCommandsInterface.cpp" +#endif +#include "MyDebug.h" + #include <cstdio> //#include <cstring> //For memset, strstr... @@ -38,10 +43,10 @@ { if( m_open ) { - USB_WARN("AT interface is already open"); + WARN("AT interface is already open"); return OK; } - USB_DBG("Opening AT interface"); + DBG("Opening AT interface"); //Start processing m_processingThread.signal_set(AT_SIG_PROCESSING_START); @@ -60,34 +65,34 @@ } m_eventsMtx.unlock(); - USB_DBG("AT interface opened"); + DBG("AT interface opened"); return OK; } //Initialize AT link -int ATCommandsInterface::init() +int ATCommandsInterface::init(const char *atInitSeq) { - USB_DBG("Sending ATZ E1 V1"); + DBG("Sending %s",atInitSeq); //Should we flush m_pStream at this point ??? int err; int tries = 5; do { - err = executeSimple("ATZ E1 V1", NULL, 3000); //Enable echo and verbosity + err = executeSimple(atInitSeq, NULL, 3000); //Enable echo and verbosity if(err && tries) { - USB_WARN("No response, trying again"); + WARN("No response, trying again"); Thread::wait(1000); //Give dongle time to recover } } while(err && tries--); if( err ) { - USB_ERR("Sending ATZ E1 V1 returned with err code %d", err); + ERR("Sending %s returned with err code %d", atInitSeq, err); return err; } - USB_DBG("AT interface initialized"); + DBG("AT interface initialized"); return OK; } @@ -97,11 +102,11 @@ { if( !m_open ) { - USB_WARN("AT interface is already closed"); + WARN("AT interface is already closed"); return OK; } - USB_DBG("Closing AT interface"); + DBG("Closing AT interface"); //Stop processing m_processingThread.signal_set(AT_SIG_PROCESSING_STOP); @@ -127,7 +132,7 @@ } m_eventsMtx.unlock(); - USB_DBG("AT interface closed"); + DBG("AT interface closed"); return OK; } @@ -143,10 +148,10 @@ int ATCommandsInterface::execute(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout/*=1000*/) { - USB_DBG("Executing command %s", command); + DBG("Executing command %s", command); if(!m_open) { - USB_WARN("Interface is not open!"); + WARN("Interface is not open!"); return NET_INVALID; } @@ -159,7 +164,7 @@ if(evt.status == osEventMail) { m_AT2Env.free((int*)evt.value.p); - USB_WARN("Previous result discarded"); + WARN("Previous result discarded"); } //Send params to the process routine @@ -175,14 +180,14 @@ Thread::wait(100); //FIXME find stg else - USB_DBG("Sending command ready signal to AT thread & aborting current blocking read operation"); + DBG("Sending command ready signal to AT thread & aborting current blocking read operation"); //Produce command ready signal int* msg = m_env2AT.alloc(osWaitForever); *msg = AT_CMD_READY; m_env2AT.put(msg); - USB_DBG("Trying to enter abortRead()"); + DBG("Trying to enter abortRead()"); //Unlock process routine (abort read) m_pStream->abortRead(); //This is thread-safe @@ -196,15 +201,15 @@ *msg = AT_TIMEOUT; m_env2AT.put(msg); - USB_DBG("Trying to enter abortRead()"); + DBG("Trying to enter abortRead()"); //Unlock process routine (abort read) m_pStream->abortRead(); //This is thread-safe - USB_WARN("Command returned no message"); + WARN("Command returned no message"); m_transactionMtx.unlock(); return NET_TIMEOUT; } - USB_DBG("Command returned with message %d", *msg); + DBG("Command returned with message %d", *msg); m_AT2Env.free((int*)evt.value.p); @@ -216,10 +221,10 @@ int ret = ATResultToReturnCode(m_transactionResult); if(ret != OK) { - USB_WARN("Command returned AT result %d with code %d", m_transactionResult.result, m_transactionResult.code); + WARN("Command returned AT result %d with code %d", m_transactionResult.result, m_transactionResult.code); } - USB_DBG("Command returned successfully"); + DBG("Command returned successfully"); //Unlock transaction mutex m_transactionMtx.unlock(); @@ -265,7 +270,7 @@ static bool lineDetected = false; //Block on serial read or incoming command - USB_DBG("Trying to read a new line from stream"); + 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) @@ -276,33 +281,33 @@ { m_inputPos+=readLen; m_inputBuf[m_inputPos] = '\0'; //Add null terminating character to ease the use of str* functions - USB_DBG("In buffer: [%s]", m_inputBuf); + DBG("In buffer: [%s]", m_inputBuf); } if( ret == NET_INTERRUPTED ) //It is worth checking readLen as data might have been read even though the read was interrupted { - USB_DBG("Read was interrupted"); + DBG("Read was interrupted"); return NET_INTERRUPTED; //0 chars were read } else if(readLen == 0) { - USB_DBG("Nothing read"); + DBG("Nothing read"); return OK; //0 chars were read } - USB_DBG("Trying to process incoming line"); + DBG("Trying to process incoming line"); bool lineProcessed = false; do { lineProcessed = false; //Reset flag - USB_DBG("New iteration"); + DBG("New iteration"); //Look for a new line if(!lineDetected) { - USB_DBG("No line detected yet"); + DBG("No line detected yet"); //Try to look for a starting CRLF char* crPtr = strchr(m_inputBuf, CR); /* @@ -318,7 +323,7 @@ */ if(crPtr != NULL) { - USB_DBG("CR char found"); + DBG("CR char found"); #if 0 //Discard all preceding characters (can do nothing if m_inputBuf == crPtr) @@ -338,24 +343,24 @@ //At this point we can check whether this is the end of a preceding line or the beginning of a new one if(m_inputBuf[2] != CR) { - USB_DBG("Beginning of new line found"); + DBG("Beginning of new line found"); //Beginning of a line lineDetected = true; //Move to next state-machine step } else { //End of an unprocessed line - USB_WARN("End of unprocessed line"); + WARN("End of unprocessed line"); } //In both cases discard CRLF - USB_DBG("Discarding CRLF"); + DBG("Discarding CRLF"); memmove(m_inputBuf, m_inputBuf + 2, (m_inputPos + 1) - 2); //Move null-terminating char as well m_inputPos = m_inputPos - 2; //Adjust m_inputPos } else { //This is completely unexpected, discard the CR char to try to recover good state - USB_WARN("Unexpected %c char (%02d code) found after CR char", m_inputBuf[1]); + WARN("Unexpected %c char (%02d code) found after CR char", m_inputBuf[1]); memmove(m_inputBuf, m_inputBuf + 1, (m_inputPos + 1) - 1); //Move null-terminating char as well m_inputPos = m_inputPos - 1; //Adjust m_inputPos } @@ -366,7 +371,7 @@ { int crPos = crPtr - m_inputBuf; int lfOff = 0; //Offset for LF if present - USB_DBG("New line found (possible echo of command)"); + DBG("New line found (possible echo of command)"); //This is the end of line //Replace m_inputBuf[crPos] with null-terminating char m_inputBuf[crPos] = '\0'; @@ -394,14 +399,14 @@ memmove(m_inputBuf, m_inputBuf + crPos + lfOff + 1, (m_inputPos + 1) - (crPos + lfOff + 1)); //Move null-terminating char as well m_inputPos = m_inputPos - (crPos + lfOff + 1); //Adjust m_inputPos } - USB_DBG("One line was successfully processed"); + DBG("One line was successfully processed"); lineProcessed = true; //Line was processed with success lineDetected = false; //Search now for a new line } } else if(m_inputBuf[0] == LF) //If there is a remaining LF char from the previous line, discard it { - USB_DBG("Discarding single LF char"); + DBG("Discarding single LF char"); memmove(m_inputBuf, m_inputBuf + 1, (m_inputPos + 1) - 1); //Move null-terminating char as well m_inputPos = m_inputPos - 1; //Adjust m_inputPos } @@ -410,7 +415,7 @@ //Look for the end of line if(lineDetected) { - USB_DBG("Looking for end of line"); + DBG("Looking for end of line"); //Try to look for a terminating CRLF char* crPtr = strchr(m_inputBuf, CR); /* @@ -428,7 +433,7 @@ if(crPtr != NULL) { - USB_DBG("CR char found"); + DBG("CR char found"); int crPos = crPtr - m_inputBuf; //To determine the sequence we need at least 2 chars if(m_inputPos - crPos >= 2) @@ -436,7 +441,7 @@ //Look for a LF char next to the CR char if(m_inputBuf[crPos + 1] == LF) { - USB_DBG("End of new line found"); + DBG("End of new line found"); //This is the end of line //Replace m_inputBuf[crPos] with null-terminating char m_inputBuf[crPos] = '\0'; @@ -458,13 +463,13 @@ m_inputPos = m_inputPos - (crPos + 2); //Adjust m_inputPos } - USB_DBG("One line was successfully processed"); + DBG("One line was successfully processed"); lineProcessed = true; //Line was processed with success } else { //This is completely unexpected, discard all chars till the CR char to try to recover good state - USB_WARN("Unexpected %c char (%02d code) found in incoming line", m_inputBuf[crPos + 1]); + WARN("Unexpected %c char (%02d code) found in incoming line", m_inputBuf[crPos + 1]); memmove(m_inputBuf, m_inputBuf + crPos + 1, (m_inputPos + 1) - (crPos + 1)); //Move null-terminating char as well m_inputPos = m_inputPos - (crPos + 1); //Adjust m_inputPos } @@ -473,7 +478,7 @@ } else if(greaterThanPtr != NULL) { - USB_DBG("> char found"); + DBG("> char found"); int gdPos = greaterThanPtr - m_inputBuf; //To determine the sequence we need at least 2 chars if(m_inputPos - gdPos >= 2) @@ -499,13 +504,13 @@ return ret; } - USB_DBG("One line was successfully processed"); + DBG("One line was successfully processed"); lineProcessed = true; //Line was processed with success } else { //This is completely unexpected, discard all chars till the GD char to try to recover good state - USB_WARN("Unexpected %c char (%02d code) found in incoming line", m_inputBuf[gdPos + 1]); + WARN("Unexpected %c char (%02d code) found in incoming line", m_inputBuf[gdPos + 1]); memmove(m_inputBuf, m_inputBuf + gdPos + 1, (m_inputPos + 1) - (gdPos + 1)); //Move null-terminating char as well m_inputPos = m_inputPos - (gdPos + 1); //Adjust m_inputPos } @@ -521,12 +526,12 @@ //Discard everything m_inputPos = 0; m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer - USB_WARN("Incoming buffer is too short to process incoming line"); + WARN("Incoming buffer is too short to process incoming line"); //Look for a new line lineDetected = false; } - USB_DBG("Processed every full incoming lines"); + DBG("Processed every full incoming lines"); return OK; } @@ -534,7 +539,7 @@ int ATCommandsInterface::trySendCommand() { osEvent evt = m_env2AT.get(0); - USB_DBG("status = %d, msg = %d", evt.status, evt.value.p); + DBG("status = %d, msg = %d", evt.status, evt.value.p); if(evt.status == osEventMail) { int* msg = (int*) evt.value.p; @@ -542,9 +547,9 @@ { if(m_transactionState != IDLE) { - USB_WARN("Previous command not processed!"); + WARN("Previous command not processed!"); } - USB_DBG("Sending pending command"); + DBG("Sending pending command"); 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 @@ -561,14 +566,14 @@ int ATCommandsInterface::processReadLine() { - USB_DBG("Processing read line [%s]", m_inputBuf); + DBG("Processing read line [%s]", m_inputBuf); //The line is stored in m_inputBuf if(m_transactionState == COMMAND_SENT) { //If the command has been sent, checks echo to see if it has been received properly if( strcmp(m_transactionCommand, m_inputBuf) == 0 ) { - USB_DBG("Command echo received"); + DBG("Command echo received"); //If so, it means that the following lines will only be solicited results m_transactionState = READING_RESULT; return OK; @@ -613,7 +618,7 @@ //The following lines can either be a command response or a result code (OK / ERROR / CONNECT / +CME ERROR: %s / +CMS ERROR: %s) if(strcmp("OK", m_inputBuf) == 0) { - USB_DBG("OK result received"); + DBG("OK result received"); m_transactionResult.code = 0; m_transactionResult.result = ATResult::AT_OK; m_transactionState = IDLE; @@ -624,7 +629,7 @@ } else if(strcmp("ERROR", m_inputBuf) == 0) { - USB_DBG("ERROR result received"); + DBG("ERROR result received"); m_transactionResult.code = 0; m_transactionResult.result = ATResult::AT_ERROR; m_transactionState = IDLE; @@ -635,7 +640,7 @@ } else if(strncmp("CONNECT", m_inputBuf, 7 /*=strlen("CONNECT")*/) == 0) //Result can be "CONNECT" or "CONNECT %d", indicating baudrate { - USB_DBG("CONNECT result received"); + DBG("CONNECT result received"); m_transactionResult.code = 0; m_transactionResult.result = ATResult::AT_CONNECT; m_transactionState = IDLE; @@ -646,7 +651,7 @@ } else if(strcmp("COMMAND NOT SUPPORT", m_inputBuf) == 0) //Huawei-specific, not normalized { - USB_DBG("COMMAND NOT SUPPORT result received"); + DBG("COMMAND NOT SUPPORT result received"); m_transactionResult.code = 0; m_transactionResult.result = ATResult::AT_ERROR; m_transactionState = IDLE; @@ -658,7 +663,7 @@ else if(strstr(m_inputBuf, "+CME ERROR:") == m_inputBuf) //Mobile Equipment Error { std::sscanf(m_inputBuf + 12 /* =strlen("+CME ERROR: ") */, "%d", &m_transactionResult.code); - USB_DBG("+CME ERROR: %d result received", m_transactionResult.code); + DBG("+CME ERROR: %d result received", m_transactionResult.code); m_transactionResult.result = ATResult::AT_CME_ERROR; m_transactionState = IDLE; int* msg = m_AT2Env.alloc(osWaitForever); @@ -669,7 +674,7 @@ else if(strstr(m_inputBuf, "+CMS ERROR:") == m_inputBuf) //SIM Error { std::sscanf(m_inputBuf + 13 /* =strlen("+CME ERROR: ") */, "%d", &m_transactionResult.code); - USB_DBG("+CMS ERROR: %d result received", m_transactionResult.code); + DBG("+CMS ERROR: %d result received", m_transactionResult.code); m_transactionResult.result = ATResult::AT_CMS_ERROR; m_transactionState = IDLE; int* msg = m_AT2Env.alloc(osWaitForever); @@ -679,7 +684,7 @@ } else { - USB_DBG("Unprocessed result received: '%s'", m_inputBuf); + DBG("Unprocessed result received: '%s'", m_inputBuf); //Must call transaction processor to complete line processing int ret = m_pTransactionProcessor->onNewATResponseLine(this, m_inputBuf); //Here sendData can be called return ret; @@ -691,12 +696,12 @@ int ATCommandsInterface::processEntryPrompt() { - USB_DBG("Calling prompt handler"); + DBG("Calling prompt handler"); int ret = m_pTransactionProcessor->onNewEntryPrompt(this); //Here sendData can be called if( ret != NET_MOREINFO ) //A new prompt is expected { - USB_DBG("Sending break character"); + DBG("Sending break character"); //Send CTRL+Z (break sequence) to exit prompt char seq[2] = {BRK, 0x00}; sendData(seq); @@ -710,11 +715,11 @@ { //m_inputBuf is cleared at this point (and MUST therefore be empty) int dataLen = strlen(data); - USB_DBG("Sending raw string of length %d", dataLen); + DBG("Sending raw string of length %d", dataLen); int ret = m_pStream->write((uint8_t*)data, dataLen, osWaitForever); if(ret) { - USB_WARN("Could not write to stream (returned %d)", ret); + WARN("Could not write to stream (returned %d)", ret); return ret; } @@ -726,7 +731,7 @@ int ret = m_pStream->read((uint8_t*)m_inputBuf, &readLen, MIN(dataLen - dataPos, AT_INPUT_BUF_SIZE - 1), osWaitForever); //Make sure we do not read more than needed otherwise it could break the parser if(ret) { - USB_WARN("Could not read from stream (returned %d)", ret); + WARN("Could not read from stream (returned %d)", ret); m_inputPos = 0; //Reset input buffer state m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer return ret; @@ -735,7 +740,7 @@ if( memcmp(m_inputBuf, data + dataPos, readLen) != 0 ) { //Echo does not match output - USB_WARN("Echo does not match output"); + WARN("Echo does not match output"); m_inputPos = 0; //Reset input buffer state m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer return NET_DIFF; @@ -746,7 +751,7 @@ } while(dataPos < dataLen); - USB_DBG("String sent successfully"); + DBG("String sent successfully"); m_inputPos = 0; //Reset input buffer state m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer @@ -783,14 +788,14 @@ void ATCommandsInterface::process() //Processing thread { - USB_DBG("AT Thread started"); + DBG("AT Thread started"); while(true) { - USB_DBG("AT Processing on hold"); + DBG("AT Processing on hold"); m_processingThread.signal_wait(AT_SIG_PROCESSING_START); //Block until the process is started m_processingMtx.lock(); - USB_DBG("AT Processing started"); + DBG("AT Processing started"); //First of all discard buffer int ret; size_t readLen; @@ -801,13 +806,13 @@ m_inputPos = 0; //Clear input buffer do { - USB_DBG("Trying to read a new line"); + DBG("Trying to read a new line"); tryReadLine(); - USB_DBG("Trying to send a pending command"); + DBG("Trying to send a pending command"); trySendCommand(); } while( m_processingThread.signal_wait(AT_SIG_PROCESSING_STOP, 0).status != osEventSignal ); //Loop until the process is interrupted m_processingMtx.unlock(); - USB_DBG("AT Processing stopped"); + DBG("AT Processing stopped"); } }
--- a/ATCommandsInterface.h Fri Feb 20 17:15:55 2015 +0000 +++ b/ATCommandsInterface.h Tue Apr 14 13:27:07 2015 +0000 @@ -20,7 +20,7 @@ #ifndef ATCOMMANDSINTERFACE_H_ #define ATCOMMANDSINTERFACE_H_ -#include "core/fwk.h" +#include "fwk.h" #include "rtos.h" #define MAX_AT_EVENTS_HANDLERS 4 @@ -75,7 +75,7 @@ int open(); //Initialize AT link - int init(); + int init(const char *atInitSeq = "ATZ E1 V1"); //Close connection int close();
--- a/HuaweiUSBModemInitializer.cpp Fri Feb 20 17:15:55 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ - -#include "dbg.h" -#include "HuaweiUSBModemInitializer.h" - -// switch string => "55 53 42 43 00 00 00 00 00 00 00 00 00 00 00 11 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00" -static uint8_t huawei_E372_switch_packet[] = { - 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 -}; - -HuaweiE372USBModemInitializer::HuaweiE372USBModemInitializer(USBHost *h): WANDongleInitializer(h) { - -} - -bool HuaweiE372USBModemInitializer::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 ) { - USB_DBG("MSD descriptor found on device %p, intf %d, will now try to switch into serial mode", (void *)pDev, i); - m_pHost->bulkWrite(pDev, pEp, huawei_E372_switch_packet, 31); - return true; - } - } - } - return false; -} - USBEndpoint* HuaweiE372USBModemInitializer::getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx) { - return pDev->getEndpoint(serialPortNumber, BULK_ENDPOINT, tx ? OUT : IN, 0); -} - -void HuaweiE372USBModemInitializer::setVidPid(uint16_t vid, uint16_t pid) { - if( (vid == getSerialVid()) && (pid == getSerialPid()) ) { - m_hasSwitched = true; - m_currentSerialIntf = 0; - m_endpointsToFetch = 4*2; - } else { - m_hasSwitched = false; - m_endpointsToFetch = 1; - } -} - -bool HuaweiE372USBModemInitializer::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) { - if( m_hasSwitched ) { - USB_DBG("Interface #%d; Class:%02x; SubClass:%02x; Protocol:%02x", intf_nb, intf_class, intf_subclass, intf_protocol); - if( intf_class == VENDSPEC_CLASS ) { - // The first 4 Interfaces are parsable. - if( m_currentSerialIntf <4 ) { - m_currentSerialIntf++; - return true; - } - m_currentSerialIntf++; - } - } else { - // The first 2 Interface are parsable. - if( ((intf_nb == 0) || (intf_nb == 1)) && (intf_class == MSD_CLASS) ) { - return true; - } - } - return false; -} - -bool HuaweiE372USBModemInitializer::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) {//Must return true if the endpoint will be used - if( m_hasSwitched ) { - USB_DBG("USBEndpoint on Inteface #%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; -}
--- a/HuaweiUSBModemInitializer.h Fri Feb 20 17:15:55 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ - - -#ifndef HUAWEI_USB_BMODEM_INITIALIZER_H -#define HUAWEI_USB_BMODEM_INITIALIZER_H - -#include "mbed.h" -#include "USBHost/USBHost3GModule/WANDongleInitializer.h" - -// For the moment we have only one key -class HuaweiE372USBModemInitializer: public WANDongleInitializer{ -public: - HuaweiE372USBModemInitializer(USBHost *h); - virtual uint16_t getMSDVid() { return 0x12D1; } - virtual uint16_t getMSDPid() { return 0x1505; } - virtual uint16_t getSerialVid() { return 0x12D1; } - virtual uint16_t getSerialPid() { return 0x14ac; } - virtual bool switchMode(USBDeviceConnected* pDev) ; - virtual USBEndpoint* getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx); - virtual int getSerialPortCount() { return 4; } - 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() { return WAN_DONGLE_TYPE_HUAWEI_E372; } - virtual uint8_t getSerialIntf(int index) { return index; } -private: - bool m_hasSwitched; - int m_currentSerialIntf; - int m_endpointsToFetch; -}; - -#endif \ No newline at end of file
--- a/IPInterface.cpp Fri Feb 20 17:15:55 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* IPInterface.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. - */ - -#include "core/fwk.h" - -#include "IPInterface.h" - -#include <cstring> //For strcpy - - -IPInterface::IPInterface() : m_connected(false) -{ - -} - -/*virtual*/ IPInterface::~IPInterface() -{ - -} - -void IPInterface::registerAsDefaultInterface() //First come, first served -{ - s_pDefaultInterface = this; -} - -void IPInterface::unregisterAsDefaultInterface() //Must be called before inst is destroyed to avoid invalid ptr fault -{ - s_pDefaultInterface = NULL; -} - -/*static*/ IPInterface* IPInterface::getDefaultInterface() //For use by TCP, UDP sockets library -{ - return s_pDefaultInterface; -} - -/*static*/ IPInterface* IPInterface::s_pDefaultInterface = NULL; - - -char* IPInterface::getIPAddress() //Get IP Address as a string ('a.b.c.d') -{ - if(isConnected()) - { - return m_ipAddr; - } - else - { - return NULL; - } -} - -bool IPInterface::isConnected() //Is the interface connected? -{ - return m_connected; -} - -void IPInterface::setIPAddress(char* ipAddr) -{ - std::strcpy(m_ipAddr, ipAddr); //Let's trust the derived class not to buffer overflow us -} - -void IPInterface::setConnected(bool connected) -{ - m_connected = connected; -} -
--- a/IPInterface.h Fri Feb 20 17:15:55 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* IPInterface.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 IPINTERFACE_H_ -#define IPINTERFACE_H_ - -#include "core/fwk.h" - -/** Generic IP-based network interface - * - */ -class IPInterface -{ -public: - IPInterface(); - virtual ~IPInterface(); - - //int init(); //Initialize interface; no connection should be performed at this stage - virtual int connect() = 0; //Do connect the interface - virtual int disconnect() = 0; - //It is encouraged that the derived class implement a "setup(...)" function to configure the interface before the connection - - char* getIPAddress(); //Get IP Address as a string ('a.b.c.d') - bool isConnected(); //Is the interface connected? - - static IPInterface* getDefaultInterface(); //For use by TCP, UDP sockets library - - //WARN: Implementation will have to be more careful in case of multiple interfaces (or implement a routing protocol based on local IP addresses differentiation) - void registerAsDefaultInterface(); //First come, first served - void unregisterAsDefaultInterface(); //Must be called before inst is destroyed to avoid invalid ptr fault - -protected: - //Must be called by subclasses - void setIPAddress(char* ipAddr); - void setConnected(bool connected); - -private: - char m_ipAddr[16]; - bool m_connected; - - static IPInterface* s_pDefaultInterface; -}; - -#endif /* IPINTERFACE_H_ */
--- a/LwIPInterface.cpp Fri Feb 20 17:15:55 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* LwIPInterface.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. - */ - - -#include "core/fwk.h" - -#include "LwIPInterface.h" - -extern "C" { -#include "lwip/init.h" -#include "lwip/tcpip.h" -} - -LwIPInterface::LwIPInterface() : IPInterface(), m_rdySphre(1) -{ - m_rdySphre.wait(); -} - -LwIPInterface::~LwIPInterface() -{ - -} - -int LwIPInterface::init() //Init LwIP-specific stuff, create the right bindings, etc -{ - //lwip_init(); //All LwIP initialisation functions called on a per-module basis (according to lwipopts.h) - tcpip_init(LwIPInterface::tcpipRdyCb, this); //Start TCP/IP processing thread - m_rdySphre.wait(); //Wait for callback to produce resource - return OK; -} - -/*static*/ void LwIPInterface::tcpipRdyCb(void* ctx) //Result of TCP/IP thread launch -{ - LwIPInterface* pIf = (LwIPInterface*) ctx; - pIf->m_rdySphre.release(); -}
--- a/LwIPInterface.h Fri Feb 20 17:15:55 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* LwIPInterface.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 LWIPINTERFACE_H_ -#define LWIPINTERFACE_H_ - -#include "core/fwk.h" -#include "IPInterface.h" - -#include "rtos.h" - -/** LwIP-based network interface - * - */ -class LwIPInterface : public IPInterface -{ -public: - LwIPInterface(); - virtual ~LwIPInterface(); - - int init(); //Init LwIP-specific stuff, create the right bindings, etc - -private: - static void tcpipRdyCb(void* ctx); //Result of TCP/IP thread launch - Semaphore m_rdySphre; -}; - -#endif /* LWIPINTERFACE_H_ */
--- a/PPPIPInterface.cpp Fri Feb 20 17:15:55 2015 +0000 +++ b/PPPIPInterface.cpp Tue Apr 14 13:27:07 2015 +0000 @@ -16,25 +16,27 @@ * 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 + +#define __DEBUG__ 3 #ifndef __MODULE__ #define __MODULE__ "PPPIPInterface.cpp" #endif +#include "MyDebug.h" -#include "dbg.h" -#define DBG(x, ...) USB_DBG(x, __VA_ARGS__) - +#include "core/errors.h" #include "core/fwk.h" +#include "core/IOStream.h" #include "rtos.h" #include <cstdio> using std::sscanf; #include "PPPIPInterface.h" +#include "USBSerialStream.h" + +#define PPP_SERIAL_PORT 0 #define MSISDN "*99#" - #define CONNECT_CMD "ATD " MSISDN "\x0D" #define EXPECTED_RESP CONNECT_CMD "\x0D" "\x0A" "CONNECT" "\x0D" "\x0A" #define EXPECTED_RESP_DATARATE CONNECT_CMD "\x0D" "\x0A" "CONNECT %d" "\x0D" "\x0A" @@ -43,418 +45,345 @@ #define ESCAPE_SEQ "+++" #define HANGUP_CMD "ATH" "\x0D" #define NO_CARRIER_RESP "\x0D" "\x0A" "NO CARRIER" "\x0D" "\x0A" + extern "C" { #include "lwip/ip_addr.h" #include "lwip/inet.h" #include "lwip/err.h" -#include "lwip/dns.h" - +//#include "lwip/dns.h" +#include "lwip/tcpip.h" #include "netif/ppp/ppp.h" } -PPPIPInterface::PPPIPInterface(IOStream* pStream) : LwIPInterface(), m_linkStatusSphre(1), m_pppErrCode(0), m_pStream(pStream), m_streamAvail(true), m_pppd(-1) -{ - m_linkStatusSphre.wait(); -} +PPPIPInterface::PPPIPInterface(USBSerialStream* pStream): + pppStream(pStream), + pppSession(0), + ipInitiated(false), + pppInitiated(false), + connected(false) {} +PPPIPInterface::~PPPIPInterface() { } -/*virtual*/ PPPIPInterface::~PPPIPInterface() -{ - +void PPPIPInterface::stackInits(const char* user, const char* pw) { + // LwIP Stuffs + if(!ipInitiated) { + DBG("LwIP: Init Stack"); + tcpip_init(PPPIPInterface::tcpipInitDoneCb, this); + DBG("LwIP: Wait for setup"); + while (!ipInitiated) + Thread::wait(1); + DBG("LwIP: setup done"); + } + // PPP Stuffs + if(!pppInitiated) { + pppInit(); + pppSetAuth(PPPAUTHTYPE_ANY, user, pw); + pppInitiated = true; + } } -/*virtual*/ int PPPIPInterface::init() //Init PPP-specific stuff, create the right bindings, etc -{ - DBG("Initializing LwIP"); - LwIPInterface::init(); //Init LwIP, NOT including PPP - DBG("Initializing PPP"); - pppInit(); - DBG("Done"); - return OK; +int PPPIPInterface::dial(void) { + int ret; + char buf[32]; + size_t len; + + DBG("Sending %s", CONNECT_CMD); + ret = pppStream->write((uint8_t*)CONNECT_CMD, strlen(CONNECT_CMD), osWaitForever); + if( ret != OK ) + return NET_UNKNOWN; + DBG("Expect %s", EXPECTED_RESP); + + /* + size_t readLen; + ret = pppStream->read((uint8_t*)buf, &readLen, EXPECTED_RESP_MIN_LEN, 10000); + if( ret != OK ) + return NET_UNKNOWN; + + DBG("Readed %d chars", readLen); + DBG_MEMDUMP("PPPAT",buf,readLen); + */ + + len = 0; + size_t readLen; + ret = pppStream->read((uint8_t*)buf + len, &readLen, EXPECTED_RESP_MIN_LEN, 10000); + if( ret != OK ) + return NET_UNKNOWN; + + len += readLen; + while( (len < EXPECTED_RESP_MIN_LEN) || (buf[len-1] != LF) ) { + ret = pppStream->read((uint8_t*)buf + len, &readLen, 1, 10000); + if( ret != OK ) + return NET_UNKNOWN; + len += readLen; + } + + buf[len]=0; + + DBG("Got %s[len %d]", buf, len); + + int datarate = 0; + if( (sscanf( buf, EXPECTED_RESP_DATARATE, &datarate ) != 1) && (strcmp(EXPECTED_RESP, buf) != 0) ) { + //Discard buffer + do { //Clear buf + ret = pppStream->read((uint8_t*)buf, &len, 32, 0); + DBG("Got %s[len %d]", buf, len); + } while( (ret == OK) && (len > 0) ); + return NET_CONN; + } + + DBG("Transport link open"); + if(datarate != 0) + DBG("Datarate: %d bps", datarate); + return OK; } -int PPPIPInterface::setup(const char* user, const char* pw) -{ - DBG("Configuring PPP authentication method"); - pppSetAuth(PPPAUTHTYPE_ANY, user, pw); - DBG("Done"); - return OK; +int PPPIPInterface::escape(void) { + DBG("Sending %s", ESCAPE_SEQ); + Thread::wait(1000); + int ret = pppStream->write((uint8_t*)ESCAPE_SEQ, strlen(ESCAPE_SEQ), osWaitForever); + Thread::wait(1000); + if( ret != OK ) + return NET_UNKNOWN; + return OK; +} + +int PPPIPInterface::connect(const char* user, const char* pw) { + + DBG("Trying to connect with PPP"); + + // Init the lWIP Stacks + stackInits(user,pw); + + // Clear the line + cleanupLink(); + + // Do the dialing + dial(); + + // Launch the ppp session + pppSession = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this); + DBG("PPP over serial opening returned = %d, pppSession"); + if (pppSession >= 0) { + // the thread was successfully started. + int retries = 600; // Approx (600*100ms) = 60s + while (!connected && (retries-- > 0)) { + Thread::wait(100); + } + + if (retries!=0) { + // We are connected on lwIP over PPP! + DBG("Got Connected"); + return OK; + } else { + DBG("Got a Timeout"); + return NET_UNKNOWN; + } + }else { + DBG("Could not get ppp session"); + return NET_UNKNOWN; + } +} + +int PPPIPInterface::disconnect() { + DBG("Do something on ppp stack and close the session"); + pppClose(pppSession); + escape(); + cleanupLink(); + return OK; } -/*virtual*/ int PPPIPInterface::connect() -{ - int ret; - char buf[32]; - size_t len; - DBG("Trying to connect with PPP"); - - cleanupLink(); - - DBG("Sending %s", CONNECT_CMD); - - ret = m_pStream->write((uint8_t*)CONNECT_CMD, strlen(CONNECT_CMD), osWaitForever); - if( ret != OK ) - { - return NET_UNKNOWN; - } - - DBG("Expect %s", EXPECTED_RESP); - - len = 0; - size_t readLen; - ret = m_pStream->read((uint8_t*)buf + len, &readLen, EXPECTED_RESP_MIN_LEN, 10000); - if( ret != OK ) - { - return NET_UNKNOWN; - } - len += readLen; - while( (len < EXPECTED_RESP_MIN_LEN) || (buf[len-1] != LF) ) - { - ret = m_pStream->read((uint8_t*)buf + len, &readLen, 1, 10000); - if( ret != OK ) - { - return NET_UNKNOWN; - } - len += readLen; - } - - buf[len]=0; - - DBG("Got %s[len %d]", buf, len); - - int datarate = 0; - if( (sscanf( buf, EXPECTED_RESP_DATARATE, &datarate ) != 1) && (strcmp(EXPECTED_RESP, buf) != 0) ) - { - //Discard buffer - do //Clear buf - { - ret = m_pStream->read((uint8_t*)buf, &len, 32, 0); - } while( (ret == OK) && (len > 0) ); - return NET_CONN; - } - - DBG("Transport link open"); - if(datarate != 0) - { - DBG("Datarate: %d bps", datarate); - } - m_linkStatusSphre.wait(0); - if((m_pppd != -1) && (m_pppErrCode == 0)) //Already connected - { - return NET_INVALID; - } - - ret = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this); - if(ret < 0) - { - switch(ret) - { - case PPPERR_OPEN: - default: - return NET_FULL; //All available resources are already used - } - } - m_pppd = ret; //PPP descriptor - m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there - if(m_pppErrCode != PPPERR_NONE) - { - m_pppd = -1; - } - switch(m_pppErrCode) - { - case PPPERR_NONE: //Connected OK - return OK; - case PPPERR_CONNECT: //Connection lost - return NET_INTERRUPTED; - case PPPERR_AUTHFAIL: //Authentication failed - return NET_AUTH; - case PPPERR_PROTOCOL: //Protocol error - return NET_PROTOCOL; - default: - return NET_UNKNOWN; - } +void PPPIPInterface::setConnected(bool val) { + connected = val; +} + +bool PPPIPInterface::isConnected(void) { + return connected; } -/*virtual*/ int PPPIPInterface::disconnect() -{ - int ret = m_linkStatusSphre.wait(0); - if(ret > 0) //Already disconnected? - { - m_pppd = -1; //Discard PPP descriptor - switch(m_pppErrCode) - { - case PPPERR_CONNECT: //Connection terminated - case PPPERR_AUTHFAIL: //Authentication failed - case PPPERR_PROTOCOL: //Protocol error - case PPPERR_USER: - return OK; - default: +int PPPIPInterface::cleanupLink() { + int ret; + char buf[32]; + size_t len; + + do { //Clear buf + ret = pppStream->read((uint8_t*)buf, &len, 32, 100); + if(ret == OK) { + buf[len] = '\0'; + DBG("Got %s", buf); + } + } while( (ret == OK) && (len > 0) ); + + DBG("Sending %s", HANGUP_CMD); + + // Here we could need to pass the ATStream to hangup + IOStream *hangupPort = pppStream; + ret = hangupPort->write((uint8_t*)HANGUP_CMD, strlen(HANGUP_CMD), osWaitForever); + if( ret != OK ) return NET_UNKNOWN; - } - } - else - { - if(m_pppd == -1) - { - return NET_INVALID; + + size_t readLen; + + //Hangup + DBG("Expect %s", HANGUP_CMD); + + len = 0; + while( len < strlen(HANGUP_CMD) ) { + ret = hangupPort->read((uint8_t*)buf + len, &readLen, strlen(HANGUP_CMD) - len, 100); + if( ret != OK ) + break; + len += readLen; + ///// + buf[len]=0; + DBG("Got %s", buf); + } + + buf[len]=0; + + DBG("Got %s[len %d]", buf, len); + + //OK response + DBG("Expect %s", OK_RESP); + + len = 0; + while( len < strlen(OK_RESP) ) { + ret = hangupPort->read((uint8_t*)buf + len, &readLen, strlen(OK_RESP) - len, 100); + if( ret != OK ) { + break; + } + len += readLen; + ///// + buf[len]=0; + DBG("Got %s", buf); + } + + buf[len]=0; + + DBG("Got %s[len %d]", buf, len); + + //NO CARRIER event + DBG("Expect %s", NO_CARRIER_RESP); + + len = 0; + while( len < strlen(NO_CARRIER_RESP) ) { + ret = pppStream->read((uint8_t*)buf + len, &readLen, strlen(NO_CARRIER_RESP) - len, 100); + if( ret != OK ) { + break; + } + len += readLen; + ///// + buf[len]=0; + DBG("Got %s", buf); } - pppClose(m_pppd); - do - { - m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there - DBG("Received PPP err code %d", m_pppErrCode); - } while(m_pppErrCode != PPPERR_USER); - m_pppd = -1; //Discard PPP descriptor - } - - DBG("Sending %s", ESCAPE_SEQ); - - ret = m_pStream->write((uint8_t*)ESCAPE_SEQ, strlen(ESCAPE_SEQ), osWaitForever); - if( ret != OK ) - { - return NET_UNKNOWN; - } - - cleanupLink(); - - return OK; + + buf[len]=0; + + DBG("Got %s[len %d]", buf, len); + + do { //Clear buf + ret = pppStream->read((uint8_t*)buf, &len, 32, 100); + if(ret == OK) { + buf[len] = '\0'; + DBG("Got %s", buf); + } + } while( (ret == OK) && (len > 0) ); + + return OK; +} + +// IP Stuffs +char *PPPIPInterface::getIPAddress(void) { + return ipAddress; +} + +void PPPIPInterface::setIPAddress(char *ip) { + strcpy(ipAddress,ip); +} + +// PPP Stuffs +extern "C" { + u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len) { + //DBG("LEN %d",len); + //DBG_MEMDUMP("IN",(const char*)data,len); + PPPIPInterface* pIf = (PPPIPInterface*)fd; + USBSerialStream *s = pIf->pppStream; + int ret = s->write(data, len, osWaitForever); //Blocks until all data is sent or an error happens + //DBG("sio_write OUT"); + if(ret != OK) { + return 0; + } + return len; + } + + u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len) { + //DBG("sio_read"); + PPPIPInterface* pIf = (PPPIPInterface*)fd; + size_t readLen; + int ret = pIf->pppStream->read(data, &readLen, len, osWaitForever); //Blocks until some data is received or an error happens + if(ret != OK) { + return 0; + } + return readLen; + } + + void sio_read_abort(sio_fd_t fd) { + //DBG("sio_read_abort"); + PPPIPInterface* pIf = (PPPIPInterface*)fd; + pIf->pppStream->abortRead(); + } } -int PPPIPInterface::cleanupLink() -{ - int ret; - char buf[32]; - size_t len; - - do //Clear buf - { - ret = m_pStream->read((uint8_t*)buf, &len, 32, 100); - if(ret == OK) - { - buf[len] = '\0'; - DBG("Got %s", buf); - } - } while( (ret == OK) && (len > 0) ); - - DBG("Sending %s", HANGUP_CMD); - - ret = m_pStream->write((uint8_t*)HANGUP_CMD, strlen(HANGUP_CMD), osWaitForever); - if( ret != OK ) - { - return NET_UNKNOWN; - } - - size_t readLen; - - //Hangup - DBG("Expect %s", HANGUP_CMD); - - len = 0; - while( len < strlen(HANGUP_CMD) ) - { - ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(HANGUP_CMD) - len, 100); - if( ret != OK ) - { - break; - } - len += readLen; - ///// - buf[len]=0; - DBG("Got %s", buf); - } - - buf[len]=0; - - DBG("Got %s[len %d]", buf, len); - - //OK response - DBG("Expect %s", OK_RESP); - - len = 0; - while( len < strlen(OK_RESP) ) - { - ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(OK_RESP) - len, 100); - if( ret != OK ) - { - break; - } - len += readLen; - ///// - buf[len]=0; - DBG("Got %s", buf); - } - - buf[len]=0; - - DBG("Got %s[len %d]", buf, len); - - //NO CARRIER event - DBG("Expect %s", NO_CARRIER_RESP); - - len = 0; - while( len < strlen(NO_CARRIER_RESP) ) - { - ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(NO_CARRIER_RESP) - len, 100); - if( ret != OK ) - { - break; - } - len += readLen; - ///// - buf[len]=0; - DBG("Got %s", buf); - } - - buf[len]=0; - - DBG("Got %s[len %d]", buf, len); - - do //Clear buf - { - ret = m_pStream->read((uint8_t*)buf, &len, 32, 100); - if(ret == OK) - { - buf[len] = '\0'; - DBG("Got %s", buf); - } - } while( (ret == OK) && (len > 0) ); - - - return OK; +// LwIP Callbacks +void PPPIPInterface::tcpipInitDoneCb(void *ctx) { + PPPIPInterface *pIf = (PPPIPInterface*)ctx; + pIf->ipInitiated = true; } -/*static*/ void PPPIPInterface::linkStatusCb(void *ctx, int errCode, void *arg) //PPP link status -{ - PPPIPInterface* pIf = (PPPIPInterface*)ctx; - struct ppp_addrs* addrs = (struct ppp_addrs*) arg; +void PPPIPInterface::linkStatusCb(void *ctx, int errCode, void *arg) { + PPPIPInterface* pIf = (PPPIPInterface*)ctx; + struct ppp_addrs* addrs = (struct ppp_addrs*) arg; - switch(errCode) - { - case PPPERR_NONE: - WARN("Connected via PPP."); - DBG("Local IP address: %s", inet_ntoa(addrs->our_ipaddr)); - DBG("Netmask: %s", inet_ntoa(addrs->netmask)); - DBG("Remote IP address: %s", inet_ntoa(addrs->his_ipaddr)); - DBG("Primary DNS: %s", inet_ntoa(addrs->dns1)); - DBG("Secondary DNS: %s", inet_ntoa(addrs->dns2)); - //Setup DNS - if (addrs->dns1.addr != 0) - { - dns_setserver(0, (struct ip_addr*)&(addrs->dns1)); - } - if (addrs->dns2.addr != 0) - { - dns_setserver(1, (struct ip_addr*)&(addrs->dns1)); - } - - pIf->setConnected(true); - pIf->setIPAddress(inet_ntoa(addrs->our_ipaddr)); - break; - case PPPERR_CONNECT: //Connection lost - WARN("Connection lost/terminated"); - pIf->setConnected(false); - break; - case PPPERR_AUTHFAIL: //Authentication failed - WARN("Authentication failed"); - pIf->setConnected(false); - break; - case PPPERR_PROTOCOL: //Protocol error - WARN("Protocol error"); - pIf->setConnected(false); - break; - case PPPERR_USER: - WARN("Disconnected by user"); - pIf->setConnected(false); - break; - default: - WARN("Unknown error (%d)", errCode); - pIf->setConnected(false); - break; - } - - pIf->m_linkStatusSphre.wait(0); //If previous event has not been handled, "delete" it now - pIf->m_pppErrCode = errCode; - pIf->m_linkStatusSphre.release(); -} - -//LwIP PPP implementation -extern "C" -{ + switch(errCode) { + case PPPERR_NONE: + WARN("Connected via PPP."); + DBG("Local IP address: %s", inet_ntoa(addrs->our_ipaddr)); + DBG("Netmask: %s", inet_ntoa(addrs->netmask)); + DBG("Remote IP address: %s", inet_ntoa(addrs->his_ipaddr)); + DBG("Primary DNS: %s", inet_ntoa(addrs->dns1)); + DBG("Secondary DNS: %s", inet_ntoa(addrs->dns2)); + //Setup DNS + if (addrs->dns1.addr != 0) { + //dns_setserver(0, (struct ip_addr*)&(addrs->dns1)); + } + if (addrs->dns2.addr != 0) { + //dns_setserver(1, (struct ip_addr*)&(addrs->dns1)); + } -/** - * Writes to the serial device. - * - * @param fd serial device handle - * @param data pointer to data to send - * @param len length (in bytes) of data to send - * @return number of bytes actually sent - * - * @note This function will block until all data can be sent. - */ -u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len) -{ - DBG("sio_write"); - PPPIPInterface* pIf = (PPPIPInterface*)fd; - int ret; - if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further - { - return 0; - } - ret = pIf->m_pStream->write(data, len, osWaitForever); //Blocks until all data is sent or an error happens - if(ret != OK) - { - return 0; - } - return len; -} + pIf->setConnected(true); + pIf->setIPAddress(inet_ntoa(addrs->our_ipaddr)); + break; + case PPPERR_CONNECT: //Connection lost + WARN("Connection lost/terminated"); + pIf->setConnected(false); + break; + case PPPERR_AUTHFAIL: //Authentication failed + WARN("Authentication failed"); + pIf->setConnected(false); + break; + case PPPERR_PROTOCOL: //Protocol error + WARN("Protocol error"); + pIf->setConnected(false); + break; + case PPPERR_USER: + WARN("Disconnected by user"); + pIf->setConnected(false); + break; + default: + WARN("Unknown error (%d)", errCode); + pIf->setConnected(false); + break; + } -/** - * Reads from the serial device. - * - * @param fd serial device handle - * @param data pointer to data buffer for receiving - * @param len maximum length (in bytes) of data to receive - * @return number of bytes actually received - may be 0 if aborted by sio_read_abort - * - * @note This function will block until data can be received. The blocking - * can be cancelled by calling sio_read_abort(). - */ -u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len) -{ - DBG("sio_read"); - PPPIPInterface* pIf = (PPPIPInterface*)fd; - int ret; - size_t readLen; - if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further - { - WARN("EXIT NOT AVAIL"); - return 0; - } - ret = pIf->m_pStream->read(data, &readLen, len, osWaitForever); //Blocks until some data is received or an error happens - if(ret != OK) - { - return 0; - } - DBG("ret"); - return readLen; + //pIf->m_linkStatusSphre.wait(0); //If previous event has not been handled, "delete" it now + //pIf->m_pppErrCode = errCode; + //pIf->m_linkStatusSphre.release(); } - -/** - * Aborts a blocking sio_read() call. - * - * @param fd serial device handle - */ -void sio_read_abort(sio_fd_t fd) -{ - DBG("sio_read_abort"); - PPPIPInterface* pIf = (PPPIPInterface*)fd; - if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further - { - return; - } - pIf->m_pStream->abortRead(); - DBG("ret"); -} - -} -
--- a/PPPIPInterface.h Fri Feb 20 17:15:55 2015 +0000 +++ b/PPPIPInterface.h Tue Apr 14 13:27:07 2015 +0000 @@ -1,65 +1,48 @@ -/* PPPIPInterface.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 PPPIPINTERFACE_H_ #define PPPIPINTERFACE_H_ #include "core/fwk.h" - -#include "LwIPInterface.h" - #include "lwip/sio.h" +#include "USBSerialStream.h" -namespace rtos { -class Semaphore; -} -using namespace rtos; - -/** Interface using PPP to connect to an IP-based network - * - */ -class PPPIPInterface : public LwIPInterface -{ +class PPPIPInterface { +private: + char ipAddress[16]; + + USBSerialStream* pppStream; //Serial stream + + int cleanupLink(); + int pppSession; + bool ipInitiated; + bool pppInitiated; + bool connected; public: - PPPIPInterface(IOStream* pStream); + PPPIPInterface(USBSerialStream* pStream); virtual ~PPPIPInterface(); - - int init(); //Init PPP-specific stuff, create the right bindings, etc - int setup(const char* user, const char* pw); //Setup authentication - virtual int connect(); - virtual int disconnect(); - -private: - int cleanupLink(); - - static void linkStatusCb(void *ctx, int errCode, void *arg); //PPP link status - Semaphore m_linkStatusSphre; - int m_pppErrCode; - - IOStream* m_pStream; //Serial stream - bool m_streamAvail; - - int m_pppd; - + + void stackInits(const char* user, const char* pw); + int dial(void); + int escape(void); + + int connect(const char* user, const char* pw); + int disconnect(); + + void setConnected(bool val); + bool isConnected(void); + + // IP stuffs + char *getIPAddress(void); + void setIPAddress(char *ip); + + // PPP implementaion friend u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); friend u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); friend void sio_read_abort(sio_fd_t fd); + + // CallBacks + static void tcpipInitDoneCb(void *arg); + static void linkStatusCb(void *ctx, int errCode, void *arg); }; #endif /* PPPIPINTERFACE_H_ */
--- a/PyrnUSBModem.cpp Fri Feb 20 17:15:55 2015 +0000 +++ b/PyrnUSBModem.cpp Tue Apr 14 13:27:07 2015 +0000 @@ -1,7 +1,11 @@ -#include "dbg.h" #include "PyrnUSBModem.h" -#include "HuaweiUSBModemInitializer.h" + +#define __DEBUG__ 5 +#ifndef __MODULE__ +#define __MODULE__ "PyrnUSBModem.cpp" +#endif +#include "MyDebug.h" // Command Processors @@ -12,18 +16,18 @@ PIN_STATUS getStatus() { return status; } private: virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) { - USB_DBG("GOT %s",line); + DBG("GOT %s",line); if(!strncmp(line, "+CPIN: READY",12)) { status = STATUS_READY; - USB_DBG("STATUS_READY"); + DBG("STATUS_READY"); } else if(!strncmp(line, "+CPIN: SIM PIN",14)) { status = STATUS_SIMPIN; - USB_DBG("STATUS_SIMPIN"); + DBG("STATUS_SIMPIN"); }else if(!strncmp(line, "+CPIN: SIM PUK",14)) { status = STATUS_SIMPUK; - USB_DBG("STATUS_SIMPUK"); + DBG("STATUS_SIMPUK"); } else - USB_DBG("STATUS_NONE"); + DBG("STATUS_NONE"); return OK; } virtual int onNewEntryPrompt(ATCommandsInterface* pInst) { return OK; } @@ -117,135 +121,210 @@ volatile bool valid; }; -PyrnUSBModem::PyrnUSBModem(USBHost *host): +// ==================== MODEM ===================== + +PyrnUSBModem::PyrnUSBModem(): + initialiser(USBHost::getHostInst()), dongle(), atStream(dongle.getSerial(3)), - pppStream(dongle.getSerial(3)), + pppStream(dongle.getSerial(0)), at(&atStream), - ppp(&pppStream), + ppp(&pppStream), atOpen(false), - pppOpen(false) { - // If we support more dongle add the initializer here. - // furthermore add dongle specific initialisation int init(). - HuaweiE372USBModemInitializer *huaweie372Initializer = new HuaweiE372USBModemInitializer(host); - dongle.addInitializer(huaweie372Initializer); + simReady(false), + pppOpen(false), + ipInit(false) { + DBG("Add E372 dongle initializer"); + dongle.addInitializer(&initialiser); } bool PyrnUSBModem::init() { - + int ret = 0; + if(!dongle.connected()){ - while(!dongle.connected()) { - USB_INFO("Dongle try connect"); - dongle.tryConnect(); - Thread::wait(10); + bool detectConnectedModem = false; + for (int x=0; x<5;x++){ + DBG("Trying to connect the dongle"); + dongle.tryConnect(); + if (dongle.connected()) { + DBG("Great the dongle is connected - I've tried %d times to connect", x); + detectConnectedModem = true; + break; // Break out of the for loop once the dongle is connected - otherwise try for a while more + } + Thread::wait(7000); } - if(!dongle.connected()) + if (!detectConnectedModem) { + // OK we got this far - so give up trying and let someone know you can't see the modem + ERR("There is no dongle pluged into the board, or the module does not respond. Is the module/modem switched on?"); return false; - } else - USB_INFO("Dongle is already connected ... continue"); - - if(atOpen) { - USB_INFO("Stream is already opened"); - return true; + } + } else { + INFO("Dongle is already connected ... continue"); } - USB_INFO("Starting AT thread if needed"); - int ret = at.open(); - if(ret) { - USB_ERR("Opening AT failed"); - return false; - } - - USB_INFO("Sending initialisation commands"); - ret = at.init(); - if(ret) { - USB_ERR("Initialisation AT failed"); - return false; - } - - if(dongle.getDongleType() == WAN_DONGLE_TYPE_HUAWEI_E372) { - USB_INFO("Using a Vodafone E372 Dongle"); - // Specific dongle initisation - ret = at.executeSimple("AT", NULL,5000); - if(ret != OK){ - USB_ERR("AT Simple command ERROR"); + if(atOpen) { + INFO("Stream is already opened go to SIM Check"); + } else { + + INFO("Starting AT thread if needed"); + ret = at.open(); + if(ret) { + ERR("Opening AT failed"); return false; - } else { - USB_INFO("AT Simple command gone well!!"); + } + + INFO("Sending initialisation commands"); + // Echo 1 + // Format CRLF + // Unsollicited Codes disabled + ret = at.init("ATZ E1 V1 ^CURC=0"); + if(ret) { + ERR("Initialisation AT failed"); + return false; } - } else { - USB_WARN("Using an Unknown Dongle"); + + if(dongle.getDongleType() == WAN_DONGLE_TYPE_HUAWEI_E372) { + INFO("Using a Vodafone E372 Dongle"); + ERR("Send CMEE cmd ..."); + ret = at.executeSimple("AT+CMEE=1",NULL,5000); + if(ret != OK) { + ERR("CMEE cmd failed"); + return false; + } + } else { + WARN("Using an Unknown Dongle.. do specific init"); + } + + atOpen = true; } ATCommandsInterface::ATResult result; - // SIM PIN Stuff here - bool pin = false; - int retries = 3; - do { - CPINProcessor cpinProcessor; - USB_INFO("Check CPIN STATE"); - ret = at.execute("AT+CPIN?", &cpinProcessor, &result,5000); - USB_INFO("Result of command: Err code=%d\n", ret); - USB_INFO("ATResult: AT return=%d (code %d)\n", result.result, result.code); - if(ret == OK) { - if(cpinProcessor.getStatus() == CPINProcessor::STATUS_READY) { - USB_INFO("ME PIN READY\n"); - pin = true; - break; - } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPIN) { - USB_INFO("ME SIM PIN NEEDED\n"); - ret = at.executeSimple("AT+CPIN=\"0000\"", NULL,5000); - if(ret != OK){ - USB_ERR("CPIN ERROR ... do not retry"); + if(!simReady){ + // SIM PIN Stuff here + int retries = 3; + do { + CPINProcessor cpinProcessor; + INFO("Check CPIN STATE"); + ret = at.execute("AT+CPIN?", &cpinProcessor, &result,5000); + //INFO("Result of command: Err code=%d", ret); + //INFO("ATResult: AT return=%d (code %d)", result.result, result.code); + if(result.code == 14) { + WARN("SIM IS Busy retry"); + retries++; + Thread::wait(500); + } else if(ret == OK) { + if(cpinProcessor.getStatus() == CPINProcessor::STATUS_READY) { + INFO("ME PIN READY"); + simReady = true; + break; + } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPIN) { + INFO("ME SIM PIN NEEDED"); + ret = at.executeSimple("AT+CPIN=\"0000\"",NULL,5000); + if(ret != OK){ + ERR("CPIN ERROR ... do not retry"); + break; + } else { + INFO("CPIN OK"); + } + } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPUK) { + INFO("CPIN IS PUKED"); break; } else { - USB_INFO("CPIN OK"); + ERR("UNKNOWN STATUS"); + break; } - } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPUK) { - USB_INFO("CPIN IS PUKED"); - break; } else { - USB_ERR("UNKNOWN STATUS"); + INFO("SIM PIN ERROR: SIM Probably not inserted"); break; } - } else { - USB_INFO("SIM PIN ERROR: SIM Probably not inserted\n"); - break; + retries--; + } while(retries); + + if(!simReady) { + ERR("Couldn't pin unlock ..."); + return false; } - retries--; - } while(retries); + } else { + INFO("SIM PIN have been unlocked somewhere!"); + } - if(!pin) { - USB_ERR("Couldn't pin unlock ..."); - return false; - } - //Wait for network registration CREGProcessor cregProcessor; do { - USB_INFO("Waiting for network registration"); + INFO("Waiting for network registration"); ret = at.execute("AT+CREG?", &cregProcessor, &result); - USB_INFO("Result of command: Err code=%d\n", ret); - USB_INFO("ATResult: AT return=%d (code %d)\n", result.result, result.code); + //INFO("Result of command: Err code=%d", ret); + //INFO("ATResult: AT return=%d (code %d)", result.result, result.code); if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING) { - Thread::wait(3000); + Thread::wait(500); } } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING); if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED) { - USB_ERR("Registration denied"); + ERR("Registration denied"); return false; } - - atOpen = true; return true; } -bool PyrnUSBModem::isConnected(void) { +bool PyrnUSBModem::attached(void) { return dongle.connected(); } +bool PyrnUSBModem::pppConnected(void) { + return ppp.isConnected(); +} + +/* WANDongleSerialPort *PyrnUSBModem::getAtInterface(int i) { return dongle.getWANSerial(i); +}*/ + +int PyrnUSBModem::connect(const char* apn, const char* user, const char* password) { + int ret; + + if(!init()) { + ERR("Modem could not register"); + return -1; + } + + ATCommandsInterface::ATResult result; + + if(apn != NULL) { + char cmd[48]; + int tries = 30; + DBG("Setting APN to %s", apn); + 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 = 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("Connecting PPP"); + ret = ppp.connect(user, password); + DBG("Result of connect: Err code=%d", ret); + + return ret; +} + +int PyrnUSBModem::disconnect() { + DBG("Disconnecting from PPP"); + int ret = ppp.disconnect(); + if(ret) { + ERR("Disconnect returned %d, still trying to disconnect", ret); + } + + Thread::wait(500); + + return OK; +} + +char* PyrnUSBModem::getIPAddress() { + // return NULL;//ppp.getIPAddress(); + return ppp.getIPAddress(); } \ No newline at end of file
--- a/PyrnUSBModem.h Fri Feb 20 17:15:55 2015 +0000 +++ b/PyrnUSBModem.h Tue Apr 14 13:27:07 2015 +0000 @@ -3,26 +3,42 @@ #define PYRN_USB_MODEM_H #include "mbed.h" + #include "USBHost/USBHost3GModule/WANDongle.h" #include "USBSerialStream.h" #include "ATCommandsInterface.h" #include "PPPIPInterface.h" +#include "HuaweiE372DongleInitializer.h" + class PyrnUSBModem { private: + HuaweiE372DongleInitializer initialiser; WANDongle dongle; + USBSerialStream atStream; USBSerialStream pppStream; + ATCommandsInterface at; PPPIPInterface ppp; + bool atOpen; + bool simReady; bool pppOpen; + bool ipInit; public: - PyrnUSBModem(USBHost *h); + PyrnUSBModem(); bool init(); - bool isConnected(void); - void testAT(void); + WANDongleSerialPort *getAtInterface(int i); + + bool attached(void); + bool pppConnected(void); + + int connect(const char* apn, const char* user, const char* password); + int disconnect(void); + + char* getIPAddress(void); }; #endif \ No newline at end of file
--- a/USBSerialStream.cpp Fri Feb 20 17:15:55 2015 +0000 +++ b/USBSerialStream.cpp Tue Apr 14 13:27:07 2015 +0000 @@ -17,10 +17,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include <stdio.h> +#include <cstdio> #include "USBSerialStream.h" +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "USBSerialStream.cpp" +#endif +#include "MyDebug.h" USBSerialStream::USBSerialStream(IUSBHostSerial& serial) : m_serial(serial), m_serialTxFifoEmpty(true), m_availableSphre(1), m_spaceSphre(1), m_inBuf() @@ -39,11 +44,11 @@ //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*/) { - USB_DBG("Trying to read at most %d chars", maxLength); + DBG("Trying to read at most %d chars", maxLength); int ret = waitAvailable(timeout); if(ret) { - USB_WARN("Error %d while waiting for incoming data", ret); + WARN("Error %d while waiting for incoming data", ret); return ret; } int a = available(); //Prevent macro issues @@ -57,7 +62,7 @@ buf++; } setupReadableISR(true); - USB_DBG("Read %d chars successfully", *pLength); + DBG("Read %d chars successfully", *pLength); return OK; } @@ -78,19 +83,19 @@ return OK; } - USB_DBG("Waiting for data availability %d ms (-1 is infinite)", timeout); + DBG("Waiting for data availability %d ms (-1 is infinite)", timeout); ret = m_availableSphre.wait(timeout); //Wait for data to arrive or for abort if(ret <= 0) { - USB_DBG("Timeout"); + DBG("Timeout"); return NET_TIMEOUT; } if(!m_inBuf.available()) //Even if abort has been called, return that data is available { - USB_DBG("Aborted"); + DBG("Aborted"); return NET_INTERRUPTED; } - USB_DBG("Finished waiting"); + DBG("Finished waiting"); while( m_availableSphre.wait(0) > 0 ); //Clear the queue as data is available return OK; } @@ -103,7 +108,7 @@ } else { - USB_DBG("Serial is readable"); ; + DBG("Serial is readable"); ; } return OK; } @@ -126,18 +131,18 @@ //0 for non-blocking (returns immediately), -1 for infinite blocking /*virtual*/ int USBSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=-1*/) { - USB_DBG("Trying to write %d chars", length); + DBG("Trying to write %d chars", length); do { int ret = waitSpace(timeout); if(ret) { - USB_WARN("Error %d while waiting for space", ret); + WARN("Error %d while waiting for space", ret); return ret; } int s = space(); //Prevent macro issues int writeLen = MIN( s, length ); - USB_DBG("Writing %d chars", writeLen); + DBG("Writing %d chars", writeLen); setupWriteableISR(false); while(writeLen) { @@ -154,7 +159,7 @@ setupWriteableISR(true); } while(length); - USB_DBG("Write successful"); + DBG("Write successful"); return OK; } @@ -175,16 +180,16 @@ return OK; } - USB_DBG("Waiting for data space %d ms (-1 is infinite)", timeout); + DBG("Waiting for data space %d ms (-1 is infinite)", timeout); ret = m_spaceSphre.wait(timeout); //Wait for space to be made or for abort if(ret <= 0) { - USB_DBG("Timeout"); + DBG("Timeout"); return NET_TIMEOUT; } if(!space()) //Even if abort has been called, return that space is available { - USB_DBG("Aborted"); + DBG("Aborted"); return NET_INTERRUPTED; } while( m_spaceSphre.wait(0) > 0); //Clear the queue as space is available
--- a/USBSerialStream.h Fri Feb 20 17:15:55 2015 +0000 +++ b/USBSerialStream.h Tue Apr 14 13:27:07 2015 +0000 @@ -21,8 +21,6 @@ #define USBSERIALSTREAM_H_ #include "rtos.h" - -#include "dbg.h" #include "core/IOStream.h" #include "core/MtxCircBuffer.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/IOStream.h Tue Apr 14 13:27:07 2015 +0000 @@ -0,0 +1,61 @@ +/* IOStream.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 IOSTREAM_H_ +#define IOSTREAM_H_ + +#include "fwk.h" + +#include "rtos.h" + +class IStream +{ +public: + //IStream(); + //virtual ~IStream(); + + //0 for non-blocking (returns immediately), osWaitForever for infinite blocking + virtual int read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout=osWaitForever) = 0; + virtual size_t available() = 0; + virtual int waitAvailable(uint32_t timeout=osWaitForever) = 0; //Wait for data to be available + virtual int abortRead() = 0; //Abort current reading (or waiting) operation +}; + +class OStream +{ +public: + //OStream(); + //virtual ~OStream(); + + //0 for non-blocking (returns immediately), osWaitForever for infinite blocking + virtual int write(uint8_t* buf, size_t length, uint32_t timeout=osWaitForever) = 0; + virtual size_t space() = 0; + virtual int waitSpace(uint32_t timeout=osWaitForever) = 0; //Wait for space to be available + virtual int abortWrite() = 0; //Abort current writing (or waiting) operation +}; + +class IOStream : public IStream, public OStream +{ +public: + //IOStream(); + //virtual ~IOStream(); +}; + + +#endif /* IOSTREAM_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/MtxCircBuffer.h Tue Apr 14 13:27:07 2015 +0000 @@ -0,0 +1,103 @@ +/* MtxCircBuf.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 MTXCIRCBUFFER_H +#define MTXCIRCBUFFER_H + +#include "fwk.h" + +#include "rtos.h" + +//Mutex protected circualr buffer +template<typename T, int size> +class MtxCircBuffer +{ +public: + MtxCircBuffer() //: + //mtx() + { + write = 0; + read = 0; + } + + bool isFull() + { + mtx.lock(); + bool r = (((write + 1) % size) == read); + mtx.unlock(); + return r; + } + + bool isEmpty() + { + mtx.lock(); + bool r = (read == write); + mtx.unlock(); + return r; + } + + void queue(T k) + { + mtx.lock(); + while (((write + 1) % size) == read) //if (isFull()) + { + /*while((((write + 1) % size) == read)) + {*/ + mtx.unlock(); + Thread::wait(10); + mtx.lock(); + /*}*/ + //read++; + //read %= size; + } + buf[write++] = k; + write %= size; + mtx.unlock(); + } + + uint16_t available() + { + mtx.lock(); + uint16_t a = (write >= read) ? (write - read) : (size - read + write); + mtx.unlock(); + return a; + } + + bool dequeue(T * c) + { + mtx.lock(); + bool empty = (read == write); + if (!empty) + { + *c = buf[read++]; + read %= size; + } + mtx.unlock(); + return (!empty); + } + +private: + volatile uint16_t write; + volatile uint16_t read; + volatile T buf[size]; + Mutex mtx; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/config.h Tue Apr 14 13:27:07 2015 +0000 @@ -0,0 +1,27 @@ +/* config.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 CONFIG_H_ +#define CONFIG_H_ + + +//Configuration +#define AT_THREAD_PRIORITY 0 + + +#endif /* CONFIG_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/errors.h Tue Apr 14 13:27:07 2015 +0000 @@ -0,0 +1,47 @@ +/* errors.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 ERRORS_H_ +#define ERRORS_H_ + +/** \page Network-related errors */ + +#define OK 0 //No error + +#define NET_FULL 1 //>All available resources are already used +#define NET_EMPTY 2 //>No resource +#define NET_NOTFOUND 3 //>Element cannot be found +#define NET_INVALID 4 //>Invalid +#define NET_CONTEXT 5 //>Called in a wrong context (eg during an interrupt) +#define NET_TIMEOUT 6 //>Timeout +#define NET_UNKNOWN 7 //>Unknown error +#define NET_OVERFLOW 8 //>Overflow +#define NET_PROCESSING 9 //>Command is processing +#define NET_INTERRUPTED 10 //>Current operation has been interrupted +#define NET_MOREINFO 11 //>More info on this error can be retrieved elsewhere (eg in a parameter passed as ptr) +#define NET_ABORT 12 //>Current operation must be aborted +#define NET_DIFF 13 //>Items that should match are different +#define NET_AUTH 14 //>Authentication failed +#define NET_PROTOCOL 15 //>Protocol error +#define NET_OOM 16 //>Out of memory +#define NET_CONN 17 //>Connection error +#define NET_CLOSED 18 //>Connection was closed by remote end +#define NET_TOOSMALL 19 //>Buffer is too small + +#endif /* ERRORS_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/fwk.h Tue Apr 14 13:27:07 2015 +0000 @@ -0,0 +1,58 @@ +/* fwk.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 FWK_H_ +#define FWK_H_ + +#include "config.h" + +#include "string.h" +//using namespace std; + +#include "stdint.h" +typedef unsigned int size_t; + +#ifndef __cplusplus +//boolean type compatibility +typedef byte bool; +#define true 1 +#define false 0 +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define CR '\x0D' +#define LF '\x0A' +#define GD '\x3E' +#define BRK '\x1A' + +//Custom utility classes +#include "IOStream.h" +//#include "String.h" + +//Error codes +#include "errors.h" + +//Utility macros +#define MIN(x,y) (((x)<(y))?(x):(y)) +#define MAX(x,y) (((x)>(y))?(x):(y)) + +#endif /* FWK_H_ */