summaryrefslogtreecommitdiff
path: root/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular')
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/CellularModem.h78
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/at/ATCommandsInterface.cpp902
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/at/ATCommandsInterface.h153
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/IOStream.h59
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/MtxCircBuffer.h95
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/config.h27
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/dbg.cpp127
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/dbg.h79
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/errors.h47
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/fwk.h61
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/IPInterface.cpp81
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/IPInterface.h60
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/LwIPInterface.cpp52
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/LwIPInterface.h44
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/PPPIPInterface.cpp466
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/PPPIPInterface.h69
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/link/LinkMonitor.cpp175
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/link/LinkMonitor.h96
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/lwipopts_conf.h26
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/CDMASMSInterface.cpp350
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/CDMASMSInterface.h90
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/GSMSMSInterface.cpp423
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/GSMSMSInterface.h97
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/SMSInterface.h67
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ussd/USSDInterface.cpp196
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ussd/USSDInterface.h80
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/io/IOSerialStream.cpp253
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/io/IOSerialStream.h72
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/usb/USBSerialStream.cpp236
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/usb/USBSerialStream.h74
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxCDMAModemInitializer.cpp114
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxCDMAModemInitializer.h63
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxGSMModemInitializer.cpp131
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxGSMModemInitializer.h63
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxModem.cpp559
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxModem.h183
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBCDMAModem.cpp398
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBCDMAModem.h118
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBGSMModem.cpp605
-rw-r--r--tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBGSMModem.h155
40 files changed, 7024 insertions, 0 deletions
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/CellularModem.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/CellularModem.h
new file mode 100644
index 0000000000..fd47622c86
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/CellularModem.h
@@ -0,0 +1,78 @@
+/* CellularModem.h */
+/* Copyright (C) 2013 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 CELLULARMODEM_H_
+#define CELLULARMODEM_H_
+
+#include "core/fwk.h"
+#include "at/ATCommandsInterface.h"
+
+class CellularModem
+{
+public:
+ //Internet-related functions
+
+ /** Open a 3G internet connection
+ @return 0 on success, error code on failure
+ */
+ virtual int connect(const char* apn = NULL, const char* user = NULL, const char* password = NULL) = 0;
+
+ /** Close the internet connection
+ @return 0 on success, error code on failure
+ */
+ virtual int disconnect() = 0;
+
+
+ /** Send a SM
+ @param number The receiver's phone number
+ @param message The message to send
+ @return 0 on success, error code on failure
+ */
+ virtual int sendSM(const char* number, const char* message) = 0;
+
+
+ /** Receive a SM
+ @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the sapce for the null-terminating char)
+ @param message Pointer to a buffer to store the the incoming message
+ @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ virtual int getSM(char* number, char* message, size_t maxLength) = 0;
+
+ /** Get the number of SMs in the incoming box
+ @param pCount pointer to store the number of unprocessed SMs on
+ @return 0 on success, error code on failure
+ */
+ virtual int getSMCount(size_t* pCount) = 0;
+
+ /** Get the ATCommandsInterface instance
+ @return Pointer to the ATCommandsInterface instance
+ */
+ virtual ATCommandsInterface* getATCommandsInterface() = 0;
+
+ /** Switch power on or off
+ In order to use this function, a pin name must have been entered in the constructor
+ @param enable true to switch the dongle on, false to switch it off
+ @return 0 on success, error code on failure
+ */
+ virtual int power(bool enable) = 0;
+};
+
+
+#endif /* CELLULARMODEM_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/at/ATCommandsInterface.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/at/ATCommandsInterface.cpp
new file mode 100644
index 0000000000..9f711630ce
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/at/ATCommandsInterface.cpp
@@ -0,0 +1,902 @@
+/* ATCommandsInterface.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__ 2 //ERR+WARN
+#ifndef __MODULE__
+#define __MODULE__ "ATCommandsInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include <cstdio>
+#include <cstring> //For memset, strstr...
+
+using std::memmove;
+
+#include "ATCommandsInterface.h"
+
+ATCommandsInterface::ATCommandsInterface(IOStream* pStream) :
+ m_pStream(pStream), m_open(false), m_transactionState(IDLE), m_env2AT(), m_AT2Env(), m_processingMtx(),
+ m_processingThread(&ATCommandsInterface::staticCallback, this, (osPriority)AT_THREAD_PRIORITY, 4*192),
+ m_eventsMgmtMtx(), m_eventsProcessingMtx()
+{
+ 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 )
+ {
+ WARN("AT interface is already open");
+ return OK;
+ }
+ DBG("Opening AT interface");
+ //Start processing
+ m_processingThread.signal_set(AT_SIG_PROCESSING_START);
+
+ m_processingMtx.unlock();
+
+ m_open = true;
+
+ DBG("AT interface opened");
+
+ return OK;
+}
+
+//Initialize AT link & start events processing
+int ATCommandsInterface::init(bool reset /* = true*/)
+{
+
+ //Lock transaction mutex
+ m_transactionMtx.lock();
+
+ if (reset)
+ {
+ DBG("Sending ATZ E1 V1");
+ //Should we flush m_pStream at this point ???
+ int err;
+ int tries = 5;
+ do
+ {
+ err = executeInternal("ATZ E1 V1", this, NULL, 3000); //Enable echo and verbosity
+ if(err && tries)
+ {
+ WARN("No response, trying again");
+ Thread::wait(1000); //Give dongle time to recover
+ }
+ } while(err && tries--);
+ if( err )
+ {
+ ERR("Sending ATZ E1 V1 returned with err code %d", err);
+ m_transactionMtx.unlock();
+ return err;
+ }
+ }
+
+ //Enable events handling and execute events enabling commands
+ enableEvents();
+
+ DBG("AT interface initialized");
+
+ //Unlock transaction mutex
+ m_transactionMtx.unlock();
+
+ return OK;
+}
+
+//Close connection
+int ATCommandsInterface::close()
+{
+ if( !m_open )
+ {
+ WARN("AT interface is already closed");
+ return OK;
+ }
+
+ DBG("Closing AT interface");
+
+ //Lock transaction mutex
+ m_transactionMtx.lock();
+
+ //Disable events handling and advertize this to the events handlers
+ disableEvents();
+
+ //Stop processing
+ m_processingThread.signal_set(AT_SIG_PROCESSING_STOP);
+ //m_stopSphre.release();
+
+ int* msg = m_env2AT.alloc(osWaitForever);
+ *msg = AT_STOP;
+ m_env2AT.put(msg); //Used to unstall the process if needed
+
+ //Unlock process routine (abort read)
+ m_pStream->abortRead(); //This is thread-safe
+ m_processingMtx.lock();
+ m_open = false;
+
+ //Unlock transaction mutex
+ m_transactionMtx.unlock();
+
+ DBG("AT interface closed");
+ return OK;
+}
+
+bool ATCommandsInterface::isOpen()
+{
+ return m_open;
+}
+
+int ATCommandsInterface::executeSimple(const char* command, ATResult* pResult, uint32_t timeout/*=1000*/)
+{
+ return execute(command, this, pResult, timeout);
+}
+
+int ATCommandsInterface::execute(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout/*=1000*/)
+{
+ if(!m_open)
+ {
+ WARN("Interface is not open!");
+ return NET_INVALID;
+ }
+
+ //Lock transaction mutex
+ m_transactionMtx.lock();
+
+ 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
+
+ //Unlock transaction mutex
+ m_transactionMtx.unlock();
+
+ return ret;
+}
+
+int ATCommandsInterface::registerEventsHandler(IATEventsHandler* pHdlr)
+{
+ m_eventsMgmtMtx.lock();
+ m_eventsProcessingMtx.lock();
+ for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot
+ {
+ if( m_eventsHandlers[i] == NULL )
+ {
+ m_eventsHandlers[i] = pHdlr;
+ m_eventsProcessingMtx.unlock();
+ m_eventsMgmtMtx.unlock();
+ return OK;
+ }
+ }
+ m_eventsProcessingMtx.unlock();
+ m_eventsMgmtMtx.unlock();
+ return NET_OOM; //No room left
+}
+
+int ATCommandsInterface::deregisterEventsHandler(IATEventsHandler* pHdlr)
+{
+ m_eventsMgmtMtx.lock();
+ m_eventsProcessingMtx.lock();
+ for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find handler in list
+ {
+ if( m_eventsHandlers[i] == pHdlr )
+ {
+ m_eventsHandlers[i] = NULL;
+ m_eventsProcessingMtx.unlock();
+ m_eventsMgmtMtx.unlock();
+ return OK;
+ }
+ }
+ m_eventsProcessingMtx.unlock();
+ m_eventsMgmtMtx.unlock();
+ return NET_NOTFOUND; //Not found
+}
+
+//Private methods
+
+int ATCommandsInterface::executeInternal(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout/*=1000*/)
+{
+ DBG("Executing command %s", command);
+
+ //Discard previous result if it arrived too late
+ osEvent evt = m_AT2Env.get(0);
+
+ if(evt.status == osEventMail)
+ {
+ m_AT2Env.free((int*)evt.value.p);
+ WARN("Previous result discarded");
+ }
+
+ //Send params to the process routine
+ m_transactionCommand = command;
+ if(pProcessor != NULL)
+ {
+ m_pTransactionProcessor = pProcessor;
+ }
+ else
+ {
+ m_pTransactionProcessor = this; //Use default behaviour
+ }
+
+ 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);
+
+ DBG("Trying to enter abortRead()");
+ //Unlock process routine (abort read)
+ m_pStream->abortRead(); //This is thread-safe
+
+ //Wait for a result (get result message)
+ evt = m_AT2Env.get(timeout);
+
+ if(evt.status != osEventMail)
+ {
+ //Cancel request
+ msg = m_env2AT.alloc(osWaitForever);
+ *msg = AT_TIMEOUT;
+ m_env2AT.put(msg);
+
+ DBG("Trying to enter abortRead()");
+ //Unlock process routine (abort read)
+ m_pStream->abortRead(); //This is thread-safe
+
+ //Wait for acknowledge
+ int msgResult;
+ do
+ {
+ evt = m_AT2Env.get(osWaitForever);
+ msgResult = *((int*) evt.value.p);
+ m_AT2Env.free((int*)evt.value.p);
+ } while(msgResult != AT_TIMEOUT);
+
+ WARN("Command returned no message");
+ WARN("Command \"%s\" returned no message", command);
+ return NET_TIMEOUT;
+ }
+ DBG("Command returned with message %d", *msg);
+
+ m_AT2Env.free((int*)evt.value.p);
+
+ if(pResult != NULL)
+ {
+ *pResult = m_transactionResult;
+ }
+
+ int ret = ATResultToReturnCode(m_transactionResult);
+ if(ret != OK)
+ {
+ WARN("Command returned AT result %d with code %d", m_transactionResult.result, m_transactionResult.code);
+ WARN("Command \"%s\" returned AT result %d with code %d", command, m_transactionResult.result, m_transactionResult.code);
+ }
+
+ DBG("Command returned successfully");
+
+ return ret;
+}
+
+int ATCommandsInterface::tryReadLine()
+{
+ static bool lineDetected = false;
+
+ //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)
+ {
+ ret = m_pStream->read((uint8_t*)m_inputBuf + m_inputPos, &readLen, AT_INPUT_BUF_SIZE - 1 - m_inputPos, 0); //Do NOT wait at this point
+ }
+ if(ret == OK)
+ {
+ m_inputPos+=readLen;
+ m_inputBuf[m_inputPos] = '\0'; //Add null terminating character to ease the use of str* functions
+ 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
+ {
+ DBG("Read was interrupted");
+ return NET_INTERRUPTED; //0 chars were read
+ }
+ else if(readLen == 0)
+ {
+ DBG("Nothing read");
+ return OK; //0 chars were read
+ }
+
+ DBG("Trying to process incoming line");
+ bool lineProcessed = false;
+
+ do
+ {
+ lineProcessed = false; //Reset flag
+
+ DBG("New iteration");
+
+ //Look for a new line
+ if(!lineDetected)
+ {
+ DBG("No line detected yet");
+ //Try to look for a starting CRLF
+ char* crPtr = strchr(m_inputBuf, CR);
+ /*
+ Different cases at this point:
+ - CRLF%c sequence: this is the start of a line
+ - CRLFCR(LF) sequence: this is the end of a line (followed by the beginning of the next one)
+ - LF: this is the trailing LF char of the previous line, discard
+ - CR / CRLF incomplete sequence: more data is needed to determine which action to take
+ - %c ... CR sequence: this should be the echo of the previous sequence
+ - %c sequence: This might be the echo of the previous command; more data is needed to determine which action to take
+
+ In every case, move mem at the beginning
+ */
+ if(crPtr != NULL)
+ {
+ DBG("CR char found");
+
+#if 0
+ //Discard all preceding characters (can do nothing if m_inputBuf == crPtr)
+ memmove(m_inputBuf, crPtr, (m_inputPos + 1) - (crPtr-m_inputBuf)); //Move null-terminating char as well
+ m_inputPos = m_inputPos - (crPtr-m_inputBuf); //Adjust m_inputPos
+#endif
+
+ //If the line starts with CR, this should be a result code
+ if( crPtr == m_inputBuf )
+ {
+ //To determine the sequence we need at least 3 chars
+ if(m_inputPos >= 3)
+ {
+ //Look for a LF char next to the CR char
+ if(m_inputBuf[1] == LF)
+ {
+ //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)
+ {
+ DBG("Beginning of new line found");
+ //Beginning of a line
+ lineDetected = true; //Move to next state-machine step
+ }
+ else
+ {
+ //End of an unprocessed line
+ WARN("End of unprocessed line");
+ }
+ //In both cases discard 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
+ 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
+ }
+ }
+ }
+ //if the line does NOT begin with CR, this can be an echo of the previous command, process it
+ else
+ {
+ int crPos = crPtr - m_inputBuf;
+ int lfOff = 0; //Offset for LF if present
+ 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';
+ //Check if there is a LF char afterwards
+ if(m_inputPos - crPos >= 1)
+ {
+ if(m_inputBuf[crPos+1] == LF)
+ {
+ lfOff++; //We will discard LF char as well
+ }
+ }
+ //Process line
+ int ret = processReadLine();
+ if(ret)
+ {
+ m_inputPos = 0;
+ m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer
+ lineDetected = false;
+ return ret;
+ }
+
+ //If sendData has been called, all incoming data has been discarded
+ if(m_inputPos > 0)
+ {
+ 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
+ }
+ 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
+ {
+ 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
+ }
+ }
+
+ //Look for the end of line
+ if(lineDetected)
+ {
+ DBG("Looking for end of line");
+ //Try to look for a terminating CRLF
+ char* crPtr = strchr(m_inputBuf, CR);
+ /*
+ Different cases at this point:
+ - CRLF sequence: this is the end of the line
+ - CR%c sequence : unexpected
+ - CR incomplete sequence: more data is needed to determine which action to take
+ */
+
+ //Try to look for a '>' (greater than character) that marks an entry prompt
+ char* greaterThanPtr = strchr(m_inputBuf, GD);
+ /*
+ This character must be detected as there is no CRLF sequence at the end of an entry prompt
+ */
+
+ if(crPtr != NULL)
+ {
+ DBG("CR char found");
+ int crPos = crPtr - m_inputBuf;
+ //To determine the sequence we need at least 2 chars
+ if(m_inputPos - crPos >= 2)
+ {
+ //Look for a LF char next to the CR char
+ if(m_inputBuf[crPos + 1] == LF)
+ {
+ DBG("End of new line found");
+ //This is the end of line
+ //Replace m_inputBuf[crPos] with null-terminating char
+ m_inputBuf[crPos] = '\0';
+ //Process line
+ int ret = processReadLine();
+ if(ret)
+ {
+ m_inputPos = 0;
+ m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer
+ lineDetected = false;
+ return ret;
+ }
+
+ //If sendData has been called, all incoming data has been discarded
+ if(m_inputPos > 0)
+ {
+ //Shift remaining data to beginning of buffer
+ memmove(m_inputBuf, m_inputBuf + crPos + 2, (m_inputPos + 1) - (crPos + 2)); //Move null-terminating char as well
+ m_inputPos = m_inputPos - (crPos + 2); //Adjust m_inputPos
+ }
+
+ 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
+ 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
+ }
+ lineDetected = false; //In both case search now for a new line
+ }
+ }
+ else if(greaterThanPtr != NULL)
+ {
+ DBG("> char found");
+ int gdPos = greaterThanPtr - m_inputBuf;
+ //To determine the sequence we need at least 2 chars
+ if(m_inputPos - gdPos >= 2)
+ {
+ //Look for a space char next to the GD char
+ if(m_inputBuf[gdPos + 1] == ' ')
+ {
+ //This is an entry prompt
+ //Replace m_inputBuf[gdPos] with null-terminating char
+ m_inputBuf[gdPos] = '\0';
+
+ //Shift remaining data to beginning of buffer
+ 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
+
+ //Process prompt
+ ret = processEntryPrompt();
+ if(ret)
+ {
+ m_inputPos = 0;
+ m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer
+ lineDetected = false;
+ return ret;
+ }
+
+ 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
+ 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
+ }
+ lineDetected = false; //In both case search now for a new line
+ }
+ }
+ }
+ } while(lineProcessed); //If one complete line was processed there might be other incoming lines that can also be processed without reading the buffer again
+
+ //If the line could not be processed AND buffer is full, it means that we won't ever be able to process it (buffer too short)
+ if(m_inputPos == AT_INPUT_BUF_SIZE - 1)
+ {
+ //Discard everything
+ m_inputPos = 0;
+ m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer
+ WARN("Incoming buffer is too short to process incoming line");
+ //Look for a new line
+ lineDetected = false;
+ }
+
+ DBG("Processed every full incoming lines");
+
+ return OK;
+}
+
+int ATCommandsInterface::trySendCommand()
+{
+ osEvent evt = m_env2AT.get(0);
+ DBG("status = %d, msg = %d", evt.status, evt.value.p);
+ if(evt.status == osEventMail)
+ {
+ int* msg = (int*) evt.value.p;
+ if( *msg == AT_CMD_READY ) //Command pending
+ {
+ if(m_transactionState != IDLE)
+ {
+ WARN("Previous command not processed!");
+ }
+ 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
+ m_transactionState = COMMAND_SENT;
+ }
+ else //Timeout
+ {
+ //Acknowledge
+ int* msg = m_AT2Env.alloc(osWaitForever);
+ *msg = AT_TIMEOUT;
+ m_AT2Env.put(msg); //Command has timed out
+ m_transactionState = IDLE; //State-machine reset
+ }
+ m_env2AT.free(msg);
+ }
+ return OK;
+}
+
+int ATCommandsInterface::processReadLine()
+{
+ 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 )
+ {
+ DBG("Command echo received");
+ //If so, it means that the following lines will only be solicited results
+ m_transactionState = READING_RESULT;
+ return OK;
+ }
+ }
+ if(m_transactionState == IDLE || m_transactionState == COMMAND_SENT)
+ {
+ bool found = false;
+ char* pSemicol = strchr(m_inputBuf, ':');
+ char* pData = NULL;
+ if( pSemicol != NULL ) //Split the identifier & the result code (if it exists)
+ {
+ *pSemicol = '\0';
+ pData = pSemicol + 1;
+ if(pData[0]==' ')
+ {
+ pData++; //Suppress whitespace
+ }
+ }
+ //Looks for a unsolicited result code; we can have m_transactionState == COMMAND_SENT as the code may have arrived just before we sent the command
+ m_eventsProcessingMtx.lock();
+ //Go through the list
+ for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot
+ {
+ if( m_eventsHandlers[i] != NULL )
+ {
+ if( m_eventsHandlers[i]->isATCodeHandled(m_inputBuf) )
+ {
+ m_eventsHandlers[i]->onEvent(m_inputBuf, pData);
+ found = true; //Do not break here as there might be multiple handlers for one event type
+ }
+ }
+ }
+ m_eventsProcessingMtx.unlock();
+ if(found)
+ {
+ return OK;
+ }
+ }
+ if(m_transactionState == READING_RESULT)
+ {
+ //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)
+ {
+ DBG("OK result received");
+ m_transactionResult.code = 0;
+ m_transactionResult.result = ATResult::AT_OK;
+ m_transactionState = IDLE;
+ int* msg = m_AT2Env.alloc(osWaitForever);
+ *msg = AT_RESULT_READY;
+ m_AT2Env.put(msg); //Command has been processed
+ return OK;
+ }
+ else if(strcmp("ERROR", m_inputBuf) == 0)
+ {
+ DBG("ERROR result received");
+ m_transactionResult.code = 0;
+ m_transactionResult.result = ATResult::AT_ERROR;
+ m_transactionState = IDLE;
+ int* msg = m_AT2Env.alloc(osWaitForever);
+ *msg = AT_RESULT_READY;
+ m_AT2Env.put(msg); //Command has been processed
+ return OK;
+ }
+ else if(strncmp("CONNECT", m_inputBuf, 7 /*=strlen("CONNECT")*/) == 0) //Result can be "CONNECT" or "CONNECT %d", indicating baudrate
+ {
+ DBG("CONNECT result received");
+ m_transactionResult.code = 0;
+ m_transactionResult.result = ATResult::AT_CONNECT;
+ m_transactionState = IDLE;
+ int* msg = m_AT2Env.alloc(osWaitForever);
+ *msg = AT_RESULT_READY;
+ m_AT2Env.put(msg); //Command has been processed
+ return OK;
+ }
+ else if(strcmp("COMMAND NOT SUPPORT", m_inputBuf) == 0) //Huawei-specific, not normalized
+ {
+ DBG("COMMAND NOT SUPPORT result received");
+ m_transactionResult.code = 0;
+ m_transactionResult.result = ATResult::AT_ERROR;
+ m_transactionState = IDLE;
+ int* msg = m_AT2Env.alloc(osWaitForever);
+ *msg = AT_RESULT_READY;
+ m_AT2Env.put(msg); //Command has been processed
+ return OK;
+ }
+ else if(strstr(m_inputBuf, "+CME ERROR:") == m_inputBuf) //Mobile Equipment Error
+ {
+ std::sscanf(m_inputBuf + 12 /* =strlen("+CME ERROR: ") */, "%d", &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);
+ *msg = AT_RESULT_READY;
+ m_AT2Env.put(msg); //Command has been processed
+ return OK;
+ }
+ else if(strstr(m_inputBuf, "+CMS ERROR:") == m_inputBuf) //SIM Error
+ {
+ std::sscanf(m_inputBuf + 13 /* =strlen("+CME ERROR: ") */, "%d", &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);
+ *msg = AT_RESULT_READY;
+ m_AT2Env.put(msg); //Command has been processed
+ return OK;
+ }
+ else
+ {
+ 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;
+ }
+ }
+
+ return OK;
+}
+
+int ATCommandsInterface::processEntryPrompt()
+{
+ DBG("Calling prompt handler");
+ int ret = m_pTransactionProcessor->onNewEntryPrompt(this); //Here sendData can be called
+
+ if( ret != NET_MOREINFO ) //A new prompt is expected
+ {
+ DBG("Sending break character");
+ //Send CTRL+Z (break sequence) to exit prompt
+ char seq[2] = {BRK, 0x00};
+ sendData(seq);
+ }
+ return OK;
+}
+
+//This will be called on initialization & after the execution of a command
+void ATCommandsInterface::enableEvents()
+{
+ //Advertize this to events handlers
+ m_eventsMgmtMtx.lock();
+ for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot
+ {
+ if( m_eventsHandlers[i] != NULL )
+ {
+ m_eventsHandlers[i]->onDispatchStart();
+ //Enable this kind of events
+ const char* cmd = m_eventsHandlers[i]->getEventsEnableCommand();
+ if(cmd != NULL)
+ {
+ int ret = executeInternal(cmd, this, NULL); //Execute enable command
+ if(ret)
+ {
+ WARN("Events enabling command \"%s\" failed", cmd);
+ }
+ }
+ }
+ }
+ m_eventsMgmtMtx.unlock();
+}
+
+//This will be called on de-initialization & before the execution of a command to prevent unsollicited result codes from polluting the results
+void ATCommandsInterface::disableEvents()
+{
+ //Advertize this to events handlers
+ m_eventsMgmtMtx.lock();
+ for(int i = 0; i < MAX_AT_EVENTS_HANDLERS; i++) //Find a free slot
+ {
+ if( m_eventsHandlers[i] != NULL )
+ {
+ m_eventsHandlers[i]->onDispatchStart();
+ //Disable this kind of events
+ const char* cmd = m_eventsHandlers[i]->getEventsDisableCommand();
+ if(cmd != NULL)
+ {
+ int ret = executeInternal(cmd, this, NULL); //Execute disable command
+ if(ret)
+ {
+ WARN("Events disabling command \"%s\" failed", cmd);
+ }
+ }
+ }
+ }
+ m_eventsMgmtMtx.unlock();
+}
+
+//Commands that can be called during onNewATResponseLine callback, additionally to close()
+//Access to this method is protected (can ONLY be called on processing thread during IATCommandsProcessor::onNewATResponseLine execution)
+int ATCommandsInterface::sendData(const char* data)
+{
+ //m_inputBuf is cleared at this point (and MUST therefore be empty)
+ int dataLen = strlen(data);
+ DBG("Sending raw string of length %d", dataLen);
+ int ret = m_pStream->write((uint8_t*)data, dataLen, osWaitForever);
+ if(ret)
+ {
+ WARN("Could not write to stream (returned %d)", ret);
+ return ret;
+ }
+
+ int dataPos = 0;
+ do
+ {
+ //Read echo
+ size_t readLen;
+ 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)
+ {
+ 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;
+ }
+
+ if( memcmp(m_inputBuf, data + dataPos, readLen) != 0 )
+ {
+ //Echo does not match output
+ m_inputBuf[readLen] = '\0';
+ WARN("Echo does not match output, got '%s' instead", m_inputBuf);
+ m_inputPos = 0; //Reset input buffer state
+ m_inputBuf[0] = '\0'; //Always have a null-terminating char at start of buffer
+ return NET_DIFF;
+ }
+
+ dataPos += readLen;
+ //If all characters have not been read yet
+
+ } while(dataPos < dataLen);
+
+ 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
+
+ return OK;
+}
+
+/*static*/ void ATCommandsInterface::staticCallback(void const* p)
+{
+ ((ATCommandsInterface*)p)->process();
+}
+
+int ATCommandsInterface::ATResultToReturnCode(ATResult result) //Helper
+{
+ if(result.result == ATResult::AT_OK)
+ {
+ return OK;
+ }
+ else
+ {
+ return NET_MOREINFO;
+ }
+}
+
+/*virtual*/ int ATCommandsInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line) //Default implementation for simple commands handling
+{
+ return OK;
+}
+
+/*virtual*/ int ATCommandsInterface::onNewEntryPrompt(ATCommandsInterface* pInst) //Default implementation (just sends Ctrl+Z to exit the prompt by returning OK right-away)
+{
+ return OK;
+}
+
+void ATCommandsInterface::process() //Processing thread
+{
+ DBG("AT Thread started");
+ while(true)
+ {
+ DBG("AT Processing on hold");
+ m_processingThread.signal_wait(AT_SIG_PROCESSING_START); //Block until the process is started
+
+ m_processingMtx.lock();
+ DBG("AT Processing started");
+ //First of all discard buffer
+ int ret;
+ size_t readLen;
+ do //Drop everything
+ {
+ ret = m_pStream->read((uint8_t*)m_inputBuf, &readLen, AT_INPUT_BUF_SIZE - 1, 0); //Do NOT wait at this point
+ } while(ret == OK);
+ m_inputPos = 0; //Clear input buffer
+ do
+ {
+ DBG("Trying to send a pending command");
+ trySendCommand(); //This must be tried first as we discarded the buffer before and therefore would be blocking though there is a pending command
+ DBG("Trying to read a new line");
+ tryReadLine();
+ } while( m_processingThread.signal_wait(AT_SIG_PROCESSING_STOP, 0).status != osEventSignal ); //Loop until the process is interrupted
+ m_processingMtx.unlock();
+ DBG("AT Processing stopped");
+ }
+}
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/at/ATCommandsInterface.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/at/ATCommandsInterface.h
new file mode 100644
index 0000000000..8334df8957
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/at/ATCommandsInterface.h
@@ -0,0 +1,153 @@
+/* ATCommandsInterface.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 ATCOMMANDSINTERFACE_H_
+#define ATCOMMANDSINTERFACE_H_
+
+#include "core/fwk.h"
+#include "rtos.h"
+
+#define MAX_AT_EVENTS_HANDLERS 4
+
+class ATCommandsInterface;
+
+/** Interface implemented by components handling AT events
+ *
+ */
+class IATEventsHandler
+{
+protected:
+ virtual bool isATCodeHandled(const char* atCode) = 0; //Is this AT code handled
+ virtual void onDispatchStart() = 0;
+ virtual void onDispatchStop() = 0;
+ virtual char* getEventsEnableCommand() = 0;
+ virtual char* getEventsDisableCommand() = 0;
+ virtual void onEvent(const char* atCode, const char* evt) = 0;
+ friend class ATCommandsInterface;
+};
+
+/** Interface implemented by components executing complex AT commands
+ *
+ */
+class IATCommandsProcessor
+{
+protected:
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) = 0;
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst) = 0;
+ friend class ATCommandsInterface;
+};
+
+#define AT_INPUT_BUF_SIZE 192//64
+
+//Signals to be sent to the processing thread
+#define AT_SIG_PROCESSING_START 1
+#define AT_SIG_PROCESSING_STOP 2
+//Messages to be sent to the processing thread
+#define AT_CMD_READY 1
+#define AT_TIMEOUT 2
+#define AT_STOP 3
+//Messages to be sent from the processing thread
+#define AT_RESULT_READY 1
+
+/** AT Commands interface class
+ *
+ */
+class ATCommandsInterface : protected IATCommandsProcessor
+{
+public:
+ ATCommandsInterface(IOStream* pStream);
+
+ //Open connection to AT Interface in order to execute command & register/unregister events
+ int open();
+
+ //Initialize AT link
+ int init(bool reset = true);
+
+ //Close connection
+ int close();
+
+ bool isOpen();
+
+ class ATResult
+ {
+ public:
+ enum { AT_OK, AT_ERROR, AT_CONNECT, AT_CMS_ERROR, AT_CME_ERROR } result;
+ int code;
+ };
+
+ int executeSimple(const char* command, ATResult* pResult, uint32_t timeout=1000);
+ int execute(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout=1000);
+
+ int registerEventsHandler(IATEventsHandler* pHdlr);
+ int deregisterEventsHandler(IATEventsHandler* pHdlr);
+
+ //Commands that can be called during onNewATResponseLine callback, additionally to close()
+ //Access to this method is protected (can ONLY be called on processing thread during IATCommandsProcessor::onNewATResponseLine execution)
+ int sendData(const char* data);
+
+ static void staticCallback(void const* p);
+private:
+ int executeInternal(const char* command, IATCommandsProcessor* pProcessor, ATResult* pResult, uint32_t timeout=1000);
+
+ int tryReadLine();
+ int trySendCommand();
+ int processReadLine();
+ int processEntryPrompt();
+
+ void enableEvents();
+ void disableEvents();
+
+ int ATResultToReturnCode(ATResult result); //Helper
+
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line); //Default implementation for simple commands handling
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst); //Default implementation (just sends Ctrl+Z to exit the prompt)
+
+ void process(); //Processing thread
+
+ IOStream* m_pStream;
+
+ bool m_open; //< TRUE when the AT interface is open, and FALSE when it is not.
+
+ const char* m_transactionCommand;
+ const char* m_transactionData;
+
+ IATCommandsProcessor* m_pTransactionProcessor;
+ ATResult m_transactionResult;
+
+ enum { IDLE, COMMAND_SENT, READING_RESULT, ABORTED } m_transactionState;
+
+ 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;
+
+ // 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
+ Mail<int,1> m_AT2Env; // used by processing thread to inform calling function of events
+
+ IATEventsHandler* m_eventsHandlers[MAX_AT_EVENTS_HANDLERS]; // all registered events handlers
+
+ Mutex m_processingMtx;
+ Thread m_processingThread;
+
+ Mutex m_eventsMgmtMtx; //Lock events use within the calling thread
+ Mutex m_eventsProcessingMtx; //Lock events use within the processing thread
+};
+
+#endif /* ATCOMMANDSINTERFACE_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/IOStream.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/IOStream.h
new file mode 100644
index 0000000000..6d411b8e4b
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/IOStream.h
@@ -0,0 +1,59 @@
+/* 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 "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_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/MtxCircBuffer.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/MtxCircBuffer.h
new file mode 100644
index 0000000000..b011693eb4
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/MtxCircBuffer.h
@@ -0,0 +1,95 @@
+/* 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 "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();
+ buf[write++] = k;
+ write %= size;
+ if (isFull())
+ {
+ read++;
+ read %= 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
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/config.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/config.h
new file mode 100644
index 0000000000..508424dc66
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/config.h
@@ -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_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/dbg.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/dbg.cpp
new file mode 100644
index 0000000000..4314e2342f
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/dbg.cpp
@@ -0,0 +1,127 @@
+/* dbg.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 "dbg.h"
+
+#include "mbed.h"
+#include "rtos.h"
+
+#include <cstdio>
+#include <cstdarg>
+
+using namespace std;
+
+static Serial debug_pc(USBTX, USBRX);
+
+static char debug_newline[3];
+
+static void debug_lock(bool set)
+{
+ static Mutex* mtx = new Mutex(); //Singleton runtime initialisation to avoid static initialisation chaos problems
+ static bool init = false;
+ if(set)
+ {
+ mtx->lock();
+ if(!init)
+ {
+ strncpy( debug_newline, "\n", 2 );
+ printf("[START]\n");
+ fflush(stdout);
+ init = true;
+ }
+ }
+ else
+ {
+ mtx->unlock();
+ }
+}
+
+void debug_init()
+{
+ debug_lock(true); //Force init
+ debug_lock(false);
+}
+
+void debug_set_newline(const char* newline)
+{
+ debug_lock(true);
+ strncpy( debug_newline, newline, 2 );
+ debug_newline[2] = '\0';
+ debug_lock(false);
+}
+
+void debug_set_speed(int speed)
+{
+ debug_pc.baud(speed);
+}
+
+void debug(int level, const char* module, int line, const char* fmt, ...)
+{
+ debug_lock(true);
+ switch(level)
+ {
+ default:
+ case 1:
+ printf("[ERROR]");
+ break;
+ case 2:
+ printf("[WARN]");
+ break;
+ case 3:
+ printf("[INFO]");
+ break;
+ case 4:
+ printf("[DBG]");
+ break;
+ }
+
+ printf(" Module %s - Line %d: ", module, line);
+
+ va_list argp;
+
+ va_start(argp, fmt);
+ vprintf(fmt, argp);
+ va_end(argp);
+
+ printf(debug_newline);
+
+ fflush(stdout);
+
+ debug_lock(false);
+
+}
+
+void debug_error(const char* module, int line, int ret)
+{
+ debug_lock(true);
+ printf("[RC] Module %s - Line %d : Error %d\n", module, line, ret);
+ fflush(stdout);
+ debug_lock(false);
+}
+
+void debug_exact(const char* fmt, ...)
+{
+ debug_lock(true);
+ va_list argp;
+
+ va_start(argp, fmt);
+ vprintf(fmt, argp);
+ va_end(argp);
+ debug_lock(false);
+}
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/dbg.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/dbg.h
new file mode 100644
index 0000000000..2ff24e1b31
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/dbg.h
@@ -0,0 +1,79 @@
+/* dbg.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 DBG_H_
+#define DBG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void debug_init(void);
+void debug(int level, const char* module, int line, const char* fmt, ...);
+void debug_set_newline(const char* newline);
+void debug_set_speed(int speed);
+void debug_error(const char* module, int line, int ret);
+void debug_exact(const char* fmt, ...);
+
+#define DBG_INIT() do{ debug_init(); }while(0)
+
+#define DBG_SET_NEWLINE( x ) do{ debug_set_newline(x); }while(0)
+
+#define DBG_SET_SPEED( x ) do{ debug_set_speed(x); }while(0)
+
+#if __DEBUG__ > 0
+#ifndef __MODULE__
+#error "__MODULE__ must be defined"
+#endif
+#endif
+
+#if __DEBUG__ >= 1
+#define ERR(...) do{ debug(1, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#else
+#define ERR(...) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 2
+#define WARN(...) do{ debug(2, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#else
+#define WARN(...) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 3
+#define INFO(...) do{ debug(3, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#define CHECK(ret) do{ if(ret){ debug_error(__MODULE__, __LINE__, ret); } }while(0)
+#else
+#define INFO(...) do{ }while(0)
+#define CHECK(ret) do{ }while(0)
+#endif
+
+#if __DEBUG__ >= 4
+#define DBG(...) do{ debug(4, __MODULE__, __LINE__, __VA_ARGS__); }while(0)
+#define DBGX(...) do{ debug_exact(__VA_ARGS__); }while(0)
+#else
+#define DBG(...) do{ }while(0)
+#define DBGX(...) do{ }while(0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DBG_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/errors.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/errors.h
new file mode 100644
index 0000000000..73ca00c1c4
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/errors.h
@@ -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_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/fwk.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/fwk.h
new file mode 100644
index 0000000000..4efc281c0e
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/core/fwk.h
@@ -0,0 +1,61 @@
+/* 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"
+
+//Debug
+#include "dbg.h"
+
+//Utility macros
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#define MAX(x,y) (((x)>(y))?(x):(y))
+
+#endif /* FWK_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/IPInterface.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/IPInterface.cpp
new file mode 100644
index 0000000000..3732303e24
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/IPInterface.cpp
@@ -0,0 +1,81 @@
+/* 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;
+}
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/IPInterface.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/IPInterface.h
new file mode 100644
index 0000000000..6655aec9ca
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/IPInterface.h
@@ -0,0 +1,60 @@
+/* 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_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/LwIPInterface.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/LwIPInterface.cpp
new file mode 100644
index 0000000000..b20f2a6617
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/LwIPInterface.cpp
@@ -0,0 +1,52 @@
+/* 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();
+}
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/LwIPInterface.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/LwIPInterface.h
new file mode 100644
index 0000000000..7e5471e204
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/LwIPInterface.h
@@ -0,0 +1,44 @@
+/* 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_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/PPPIPInterface.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/PPPIPInterface.cpp
new file mode 100644
index 0000000000..98614050ef
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/PPPIPInterface.cpp
@@ -0,0 +1,466 @@
+/* PPPIPInterface.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__ 0
+#ifndef __MODULE__
+#define __MODULE__ "PPPIPInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+#include "rtos.h"
+
+#include <cstdio>
+using std::sscanf;
+using std::sprintf;
+
+#include "PPPIPInterface.h"
+
+#define MSISDN "*99#"
+
+#define CONNECT_CMD_PREFIX "ATD "
+#define CONNECT_CMD_SUFFIX "\x0D"
+#define EXPECTED_RESP_SUFFIX "\x0D" "\x0A" "CONNECT" "\x0D" "\x0A"
+#define EXPECTED_RESP_DATARATE_SUFFIX "\x0D" "\x0A" "CONNECT %d" "\x0D" "\x0A"
+#define EXPECTED_RESP_MIN_LEN 20
+#define OK_RESP "\x0D" "\x0A" "OK" "\x0D" "\x0A"
+#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 "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();
+}
+
+
+
+/*virtual*/ PPPIPInterface::~PPPIPInterface()
+{
+}
+
+/*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::setup(const char* user, const char* pw, const char* msisdn)
+{
+ DBG("Configuring PPP authentication method");
+ pppSetAuth(PPPAUTHTYPE_ANY, user, pw);
+ m_msisdn = msisdn;
+ DBG("Done");
+ return OK;
+}
+
+/*virtual*/ int PPPIPInterface::connect()
+{
+ int ret;
+ char cmd[32];
+ int cmdLen;
+ char buf[32];
+ size_t len;
+ DBG("Trying to connect with PPP");
+
+ cleanupLink();
+
+ cmdLen = sprintf(cmd, "%s%s%s", CONNECT_CMD_PREFIX, m_msisdn, CONNECT_CMD_SUFFIX);
+ DBG("Sending %s", cmd);
+ ret = m_pStream->write((uint8_t*)cmd, cmdLen, osWaitForever);
+ if( ret != OK )
+ {
+ return NET_UNKNOWN;
+ }
+
+ 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;
+ strcpy(&cmd[cmdLen], EXPECTED_RESP_DATARATE_SUFFIX);
+ if( (sscanf(buf, cmd, &datarate ) != 1))
+ {
+ strcpy(&cmd[cmdLen], EXPECTED_RESP_SUFFIX);
+ if (strcmp(cmd, 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;
+ }
+}
+
+/*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:
+ return NET_UNKNOWN;
+ }
+ }
+ else
+ {
+ if(m_pppd == -1)
+ {
+ return NET_INVALID;
+ }
+ 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;
+}
+
+
+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;
+}
+
+/*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;
+
+ 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"
+{
+
+/**
+ * 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;
+}
+
+/**
+ * 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;
+}
+
+/**
+ * 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");
+}
+
+}
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/PPPIPInterface.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/PPPIPInterface.h
new file mode 100644
index 0000000000..2d24009dcd
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ip/PPPIPInterface.h
@@ -0,0 +1,69 @@
+/* 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"
+
+namespace rtos {
+class Semaphore;
+}
+using namespace rtos;
+
+#define DEFAULT_MSISDN_GSM "*99#"
+#define DEFAULT_MSISDN_CDMA "#777"
+
+/** Interface using PPP to connect to an IP-based network
+ *
+ */
+class PPPIPInterface : public LwIPInterface
+{
+public:
+ PPPIPInterface(IOStream* pStream);
+ virtual ~PPPIPInterface();
+
+ int init(); //Init PPP-specific stuff, create the right bindings, etc
+ int setup(const char* user, const char* pw, const char* msisdn); //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;
+ const char* m_msisdn;
+
+ int m_pppd;
+
+ 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);
+};
+
+#endif /* PPPIPINTERFACE_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/link/LinkMonitor.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/link/LinkMonitor.cpp
new file mode 100644
index 0000000000..612b376921
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/link/LinkMonitor.cpp
@@ -0,0 +1,175 @@
+/* LinkMonitor.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__ 0
+#ifndef __MODULE__
+#define __MODULE__ "LinkMonitor.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "LinkMonitor.h"
+
+#include <cstdio>
+using std::sscanf;
+
+#define DEFAULT_TIMEOUT 10000
+
+LinkMonitor::LinkMonitor(ATCommandsInterface* pIf) : m_pIf(pIf), m_rssi(0), m_registrationState(REGISTRATION_STATE_UNKNOWN), m_bearer(BEARER_UNKNOWN)
+{
+ m_gsm = true;
+}
+
+int LinkMonitor::init(bool gsm)
+{
+ m_gsm = gsm;
+ if (m_gsm)
+ {
+ // we need to make sure that we setup the operator selection to be in 'numeric' format.
+ // i.e. it is made up of a network and country code when returned by the modem e.g. Operator = 23415. This allows easy logic parsing for
+ // setting up other network parameters in future.
+ DBG("LinkMonitor::init() being called. This should only happen once: executinging AT+COPS=0,2");
+ int ret = m_pIf->executeSimple("AT+COPS=0,2", NULL, DEFAULT_TIMEOUT); //Configure to set the operator string to Country Code and mobile network code
+ if(ret != OK)
+ {
+ WARN(" NET_PROTOCOL error from sending the AT+COPS command to the modem. ");
+ return NET_PROTOCOL;
+ }
+ }
+ return OK;
+}
+
+/*virtual*/ int LinkMonitor::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+{
+ DBG("Line is %s", line);
+ char n[32] = "";
+ char s[32] = "";
+ int v;
+ if( sscanf(line, "+CREG: %*d,%d", &v) >= 1 ) //Reg state is valid
+ {
+ DBG("+CREG %d", v);
+ switch( v )
+ {
+ case 0:
+ m_registrationState = REGISTRATION_STATE_UNKNOWN;
+ break;
+ case 1:
+ m_registrationState = REGISTRATION_STATE_HOME_NETWORK;
+ break;
+ case 2:
+ m_registrationState = REGISTRATION_STATE_REGISTERING;
+ break;
+ case 3:
+ m_registrationState = REGISTRATION_STATE_DENIED;
+ break;
+ case 4:
+ m_registrationState = REGISTRATION_STATE_NO_SIGNAL;
+ break;
+ case 5:
+ m_registrationState = REGISTRATION_STATE_ROAMING;
+ break;
+ default:
+ m_registrationState = REGISTRATION_STATE_UNKNOWN;
+ break;
+ }
+ }
+ else if( sscanf(line, "+COPS: %*d,%*d,\"%*[^\"]\",%d", &v) >= 1 )
+ {
+ DBG("+COPS %d", v);
+ switch( v )
+ {
+ case 0:
+ m_bearer = BEARER_GSM;
+ break;
+ case 2:
+ m_bearer = BEARER_UMTS;
+ break;
+ case 3:
+ m_bearer = BEARER_EDGE;
+ break;
+ case 4: //HSDPA
+ case 5: //HSUPA
+ case 6: //HSDPA + HSUPA
+ m_bearer = BEARER_HSPA;
+ break;
+ case 7:
+ m_bearer = BEARER_LTE;
+ break;
+ case 1: //GSM Compact
+ default:
+ m_bearer = BEARER_UNKNOWN;
+ break;
+ }
+ }
+ else if( sscanf(line, "+CSQ: %d,%*d", &v) >= 1 )
+ {
+ DBG("+CSQ %d", v);
+ if(v == 99) //Unknown
+ {
+ m_rssi = 0; //Unknown
+ }
+ else
+ {
+ m_rssi = -113 + 2*v;
+ }
+ }
+ else if ( (sscanf(line, "+CNUM: \"%[^\"]\",\"%[^\"]\",%d", n, s, &v) == 3) ||
+ (sscanf(line, "+CNUM: \"\",\"%[^\"]\",%d", s, &v) == 2) )
+ {
+ if (*s && ((v == 145/*number includes + */) || (v == 129/*otherwise*/))) {
+ strcpy(m_phoneNumber, s);
+ }
+ }
+ return OK;
+}
+
+/*virtual*/ int LinkMonitor::onNewEntryPrompt(ATCommandsInterface* pInst)
+{
+ return OK;
+}
+
+int LinkMonitor::getState(int* pRssi, REGISTRATION_STATE* pRegistrationState, BEARER* pBearer)
+{
+ m_rssi = 0;
+ m_registrationState = REGISTRATION_STATE_UNKNOWN;
+ m_bearer = BEARER_UNKNOWN;
+ int ret = m_pIf->execute(m_gsm ? "AT+CREG?;+COPS?;+CSQ" : "AT+CREG?;+CSQ", this, NULL, DEFAULT_TIMEOUT); //Configure to get registration info & get it; get signal quality
+ if(ret != OK)
+ {
+ return NET_PROTOCOL;
+ }
+ *pRssi = m_rssi;
+ *pRegistrationState = m_registrationState;
+ *pBearer = m_bearer;
+ return OK;
+}
+
+int LinkMonitor::getPhoneNumber(char* phoneNumber)
+{
+ *m_phoneNumber = '\0';
+ if (m_gsm) {
+ int ret = m_pIf->execute("AT+CNUM", this, NULL, DEFAULT_TIMEOUT);
+ if(ret != OK)
+ {
+ return NET_PROTOCOL;
+ }
+ }
+ strcpy(phoneNumber, m_phoneNumber);
+ return OK;
+} \ No newline at end of file
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/link/LinkMonitor.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/link/LinkMonitor.h
new file mode 100644
index 0000000000..864909d6c5
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/link/LinkMonitor.h
@@ -0,0 +1,96 @@
+/* LinkMonitor.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 LINKMONITOR_H_
+#define LINKMONITOR_H_
+
+#include "core/fwk.h"
+
+#include "rtos.h"
+
+#include "at/ATCommandsInterface.h"
+
+/** Component to monitor link quality
+ *
+ */
+class LinkMonitor : protected IATCommandsProcessor
+{
+public:
+ /** Create LinkMonitor instance
+ @param pIf Pointer to the ATCommandsInterface instance to use
+ */
+ LinkMonitor(ATCommandsInterface* pIf);
+
+ /** Initialize monitor
+ */
+ int init(bool gsm = true);
+
+ /** Registration State
+ */
+ enum REGISTRATION_STATE
+ {
+ REGISTRATION_STATE_UNKNOWN, //!< Unknown
+ REGISTRATION_STATE_REGISTERING, //!< Registering
+ REGISTRATION_STATE_DENIED, //!< Denied
+ REGISTRATION_STATE_NO_SIGNAL, //!< No Signal
+ REGISTRATION_STATE_HOME_NETWORK, //!< Registered on home network
+ REGISTRATION_STATE_ROAMING //!< Registered on roaming network
+ };
+
+ /** Bearer type
+ */
+ enum BEARER
+ {
+ BEARER_UNKNOWN, //!< Unknown
+ BEARER_GSM, //!< GSM (2G)
+ BEARER_EDGE, //!< EDGE (2.5G)
+ BEARER_UMTS, //!< UMTS (3G)
+ BEARER_HSPA, //!< HSPA (3G+)
+ BEARER_LTE //!< LTE (4G)
+ };
+
+ /** Get link state
+ @param pRssi pointer to store the current RSSI in dBm, between -51 dBm and -113 dBm if known; -51 dBm means -51 dBm or more; -113 dBm means -113 dBm or less; 0 if unknown
+ @param pRegistrationState pointer to store the current registration state
+ @param pBearer pointer to store the current bearer
+ @return 0 on success, error code on failure
+ */
+ int getState(int* pRssi, REGISTRATION_STATE* pRegistrationState, BEARER* pBearer);
+
+ /** Get my phone number
+ @param phoneNumber pointer to store the current phoneNumber
+ @return 0 on success, error code on failure
+ */
+ int getPhoneNumber(char* phoneNumber);
+protected:
+ //IATCommandsProcessor
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst);
+
+private:
+ ATCommandsInterface* m_pIf;
+
+ int m_rssi;
+ bool m_gsm;
+ REGISTRATION_STATE m_registrationState;
+ BEARER m_bearer;
+ char m_phoneNumber[16];
+};
+
+#endif /* LINKMONITOR_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/lwipopts_conf.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/lwipopts_conf.h
new file mode 100644
index 0000000000..5cd84be875
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/lwipopts_conf.h
@@ -0,0 +1,26 @@
+/* lwipopts.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 LWIPOPTS_CONF_H_
+#define LWIPOPTS_CONF_H_
+
+#define LWIP_TRANSPORT_PPP 1
+
+#endif /* LWIPOPTS_CONF_H_ */
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/CDMASMSInterface.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/CDMASMSInterface.cpp
new file mode 100644
index 0000000000..978b3e1e8b
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/CDMASMSInterface.cpp
@@ -0,0 +1,350 @@
+/* CDMASMSInterface.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__ 0
+#ifndef __MODULE__
+#define __MODULE__ "CDMASMSInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "CDMASMSInterface.h"
+
+#include <cstdio>
+#include <cstring>
+
+using std::sscanf;
+
+#define DEFAULT_TIMEOUT 10000
+
+CDMASMSInterface::CDMASMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL)
+{
+}
+
+int CDMASMSInterface::init()
+{
+ m_state = SMS_IDLE;
+
+ DBG("Get number of messages in the different inboxes");
+ int ret = updateInbox();
+ if(ret)
+ {
+ return NET_PROTOCOL;
+ }
+
+ DBG("Initialization done");
+ return OK;
+}
+
+int CDMASMSInterface::send(const char* number, const char* message)
+{
+ if( strlen(number) > 16 )
+ {
+ return NET_INVALID; //Number too long
+ }
+
+ int ret;
+
+ //Prepare infos
+ m_state = SMS_SEND_CMD_SENT;
+
+ bool intlNumber=(number[0]=='+'); //If the number starts with the + sign, replace it with 011 instead (int'l dialing code in the US)
+
+ DBG("Send SM");
+ //Send command
+ char cmd[32+strlen(message)];
+ std::sprintf(cmd, "AT!SSMS=0,%s%s,,\"%s\"",intlNumber?"011":"", intlNumber?(number+1):number, message); //Send with normal priority
+ ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
+
+ if(ret != OK)
+ {
+ WARN("ret %d", ret);
+ m_state = SMS_IDLE;
+ return NET_PROTOCOL;
+ }
+
+ DBG("Check status");
+ m_txState = SMS_PENDING;
+
+ int tries = 10;
+ while(tries--)
+ {
+ m_state = SMS_GET_TX_STATUS_CMD_SENT;
+ ret = m_pIf->execute("AT!SSMS?", this, NULL, DEFAULT_TIMEOUT);
+ if(ret)
+ {
+ m_state = SMS_IDLE;
+ return ret;
+ }
+ m_state = SMS_IDLE;
+ if(m_txState == SMS_PENDING) //Wait more
+ {
+ Thread::wait(1000);
+ continue;
+ }
+ else if(m_txState == SMS_FAILED)
+ {
+ ERR("The modem could not send the SM");
+ return NET_CONN; //Probably a conenction issue, the user can retry
+ }
+ else
+ {
+ break;
+ }
+ }
+ if(!tries)
+ {
+ ERR("The is still trying to send the SM");
+ return NET_TIMEOUT;
+ }
+ return OK;
+}
+
+
+int CDMASMSInterface::get(char* number, char* message, size_t maxLength)
+{
+ if( maxLength < 1 )
+ {
+ return NET_INVALID; //Buffer too short
+ }
+
+ int ret;
+
+ DBG("Get next message");
+ if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0)
+ {
+ DBG("Message list count is 0 and needs updating. Running updateInbox.");
+ ret = updateInbox();
+ if (ret)
+ {
+ return ret;
+ }
+ }
+
+ if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0)
+ {
+ DBG("Message list count is 0");
+ return NET_EMPTY; //No message to read
+ }
+
+ //Determine which index to use : 3 (read), then 1 (urgent), then 2 (regular)
+ int index;
+ if(m_msgInListsCount[2])
+ {
+ index = 3;
+ }
+ else if(m_msgInListsCount[0])
+ {
+ index = 1;
+ }
+ else //if(m_msgInListsCount[1])
+ {
+ index = 2;
+ }
+
+ //Prepare infos
+ m_state = SMS_GET_CMD_SENT;
+ m_msisdn = (char*) number;
+ m_msg = (char*) message;
+ m_maxMsgLength = maxLength;
+ m_headersToRead = 3;
+
+ m_msisdn[0] = '\0';
+
+ DBG("Get SMS");
+ //Read command
+ char cmd[32];
+ std::sprintf(cmd, "AT!GSMS?%d,1", index); //1 is the oldest message
+ ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
+ if( ret != OK )
+ {
+ WARN("AT!GSMS returned %d", ret);
+ m_state = SMS_IDLE;
+ return NET_PROTOCOL;
+ }
+
+ //If message is not read, it will be put at the end of the read list
+ int item;
+ if( index != 3 )
+ {
+ //Decrement count in relevant list
+ m_msgInListsCount[index-1]--;
+ //Increment count in read list
+ m_msgInListsCount[3-1]++;
+ item = m_msgInListsCount[3-1];
+ //Normally item should be equal to 1 as we'd have read any older messages first
+ if( item != 1 )
+ {
+ WARN("Still some older messages pending in the read inbox");
+ }
+ }
+ else
+ {
+ //The item is still the oldest one
+ item = 1;
+ }
+
+ DBG("Deleting message");
+ //Delete message from inbox
+ std::sprintf(cmd, "AT!DSMS=3"/*,%d", item*/); //FIXME why doesn't that work when specifying the index??
+ ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
+ if(ret != OK)
+ {
+ ERR("Could not delete message");
+ }
+ else
+ {
+ //Now we can decrease the number of read messages
+ m_msgInListsCount[3-1]--;
+ }
+
+ if (m_state != SMS_CMD_PROCESSED)
+ {
+ WARN("Message could not be retrieved properly");
+ m_state = SMS_IDLE;
+ return NET_EMPTY;
+ }
+
+ m_state = SMS_IDLE;
+
+ return OK;
+}
+
+
+int CDMASMSInterface::getCount(size_t* pCount)
+{
+ int ret = updateInbox();
+ if(ret)
+ {
+ return NET_PROTOCOL;
+ }
+
+ *pCount = m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]; //Urgent messages + regular messages + read messages
+
+ return OK;
+}
+
+
+/*virtual*/ int CDMASMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+{
+ if(m_state == SMS_SEND_CMD_SENT)
+ {
+ DBG("SMS Send: %s", line);
+ }
+ else if(m_state == SMS_GET_TX_STATUS_CMD_SENT)
+ {
+ if(!strcmp(line, "sent"))
+ {
+ m_txState = SMS_SENT;
+ m_state = SMS_CMD_PROCESSED;
+ }
+ else if(!strcmp(line, "failed"))
+ {
+ m_txState = SMS_FAILED;
+ m_state = SMS_CMD_PROCESSED;
+ }
+ else if(!strcmp(line, "none"))
+ {
+ m_txState = SMS_NONE;
+ m_state = SMS_CMD_PROCESSED;
+ }
+ else if(!strcmp(line, "pending"))
+ {
+ m_txState = SMS_PENDING;
+ m_state = SMS_CMD_PROCESSED;
+ }
+ }
+ else if(m_state == SMS_GET_CMD_SENT)
+ {
+ DBG("Header: %s", line);
+
+ if(m_msisdn[0]=='\0')
+ {
+ sscanf(line, "From: %16s", m_msisdn);
+ }
+
+ m_headersToRead--;
+
+ if(m_headersToRead==0) //End of headers
+ {
+ if(m_msisdn[0]!='\0') //Checks that the incoming number has been retrieved
+ {
+ m_state = SMS_GET_HDR_RECEIVED;
+ }
+ else
+ {
+ m_state = SMS_IDLE; //Error, signal it
+ }
+ }
+ }
+ else if(m_state == SMS_GET_HDR_RECEIVED)
+ {
+ DBG("Message: %s", line);
+ size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 );
+ std::memcpy( m_msg, line, cpyLen );
+ m_msg[cpyLen] = '\0';
+ m_state = SMS_CMD_PROCESSED;
+ }
+ else if(m_state == SMS_GET_COUNT_CMD_SENT)
+ {
+ DBG("Inbox: %s", line);
+ int index;
+ size_t count;
+ if((strlen(line) > 16) && sscanf(line + 16, "{Index = %d}: %d", &index, &count) == 2)
+ {
+ if((index > 0) && (index <=4))
+ {
+ m_msgInListsCount[index-1] = count;
+ }
+ if(index == 4)
+ {
+ m_state = SMS_CMD_PROCESSED;
+ }
+ }
+ }
+ return OK;
+}
+
+/*virtual*/ int CDMASMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
+{
+ return OK;
+}
+
+
+int CDMASMSInterface::updateInbox()
+{
+ //Get number of unread/read messages
+
+ DBG("Updating inbox");
+ m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Reset counts
+
+ //Get counts
+ m_state = SMS_GET_COUNT_CMD_SENT;
+ int ret = m_pIf->execute("AT!CNTSMS", this, NULL, DEFAULT_TIMEOUT);
+ if( ret != OK )
+ {
+ WARN("AT!CNTSMS returned %d", ret);
+ m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Invalidate counts
+ m_state = SMS_IDLE;
+ return NET_PROTOCOL;
+ }
+
+ return OK;
+}
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/CDMASMSInterface.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/CDMASMSInterface.h
new file mode 100644
index 0000000000..6aa4557c36
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/CDMASMSInterface.h
@@ -0,0 +1,90 @@
+/* SMSInterface.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 CDMASMSINTERFACE_H_
+#define CDMASMSINTERFACE_H_
+
+#include "SMSInterface.h"
+
+#define MAX_SM 8
+
+/** Component to use the Short Messages Service (SMS)
+ *
+ */
+class CDMASMSInterface : public ISMSInterface, protected IATCommandsProcessor
+{
+public:
+ /** Create SMSInterface instance
+ @param pIf Pointer to the ATCommandsInterface instance to use
+ */
+ CDMASMSInterface(ATCommandsInterface* pIf);
+
+ /** Initialize interface
+ Configure SMS commands & register for SMS-related unsolicited result codes
+ */
+ virtual int init();
+
+ /** Send a SM
+ @param number The receiver's phone number
+ @param message The message to send
+ @return 0 on success, error code on failure
+ */
+ virtual int send(const char* number, const char* message);
+
+
+ /** Receive a SM
+ @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the space for the null-terminating char)
+ @param message Pointer to a buffer to store the the incoming message
+ @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ virtual int get(char* number, char* message, size_t maxLength);
+
+
+ /** Get the number of SMs in the incoming box
+ @param pCount pointer to store the number of unprocessed SMs on
+ @return 0 on success, error code on failure
+ */
+ virtual int getCount(size_t* pCount);
+
+protected:
+ //IATCommandsProcessor
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst);
+
+ int updateInbox(); //Update messages count in the different inboxes
+
+private:
+ ATCommandsInterface* m_pIf;
+
+ //Current message
+ char* m_msg;
+ size_t m_maxMsgLength;
+ char* m_msisdn;
+
+ //Messages list
+ size_t m_msgInListsCount[4]; //4 lists
+
+ size_t m_headersToRead;
+
+ enum { SMS_NONE, SMS_SENT, SMS_PENDING, SMS_FAILED } m_txState;
+ enum { SMS_IDLE, SMS_SEND_CMD_SENT, SMS_GET_TX_STATUS_CMD_SENT, SMS_GET_CMD_SENT, SMS_GET_HDR_RECEIVED, SMS_GET_COUNT_CMD_SENT, SMS_CMD_PROCESSED } m_state;
+};
+
+#endif /* CDMASMSINTERFACE_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/GSMSMSInterface.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/GSMSMSInterface.cpp
new file mode 100644
index 0000000000..2ed50ad126
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/GSMSMSInterface.cpp
@@ -0,0 +1,423 @@
+/* GSMSMSInterface.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__ 2
+#ifndef __MODULE__
+#define __MODULE__ "GSMSMSInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "GSMSMSInterface.h"
+
+#include <cstdio>
+#include <cstring>
+
+#define DEFAULT_TIMEOUT 10000
+
+GSMSMSInterface::GSMSMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL)
+{
+ m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
+}
+
+int GSMSMSInterface::init()
+{
+ m_msgRefListCount = 0;
+ m_needsUpdate = true;
+ m_state = SMS_IDLE;
+
+ DBG("Set format");
+ //Set Text mode format
+ int ret = m_pIf->executeSimple("AT+CMGF=1", NULL, DEFAULT_TIMEOUT);
+ if(ret != OK)
+ {
+ return NET_PROTOCOL;
+ }
+
+ DBG("Setup new messages indication");
+ //Setup new messages indication
+ ret = m_pIf->executeSimple("AT+CNMI=2,1,0,0,0", NULL, DEFAULT_TIMEOUT);
+ if(ret != OK)
+ {
+ return NET_PROTOCOL;
+ }
+
+ DBG("Try to fetch inbox");
+ m_inboxMtx.lock();
+ if( m_needsUpdate )
+ {
+ ret = updateInbox(); //Fetch existing messages references
+ if(ret)
+ {
+ m_inboxMtx.unlock();
+ return NET_PROTOCOL;
+ }
+ }
+ m_inboxMtx.unlock();
+
+ DBG("Initialization done");
+ return OK;
+}
+
+int GSMSMSInterface::send(const char* number, const char* message)
+{
+ if( strlen(number) > 16 )
+ {
+ return NET_INVALID; //Number too long to match 3GPP spec
+ }
+
+ int ret;
+
+ //Prepare infos
+ m_state = SMS_SEND_CMD_SENT;
+ m_msg = (char*) message;
+
+ DBG("Send SM");
+ //Send command
+ char cmd[32];
+ std::sprintf(cmd, "AT+CMGS=\"%s\"", number);
+ ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
+
+ if( (ret != OK) || (m_state != SMS_CMD_PROCESSED) )
+ {
+ WARN("ret %d, state %d", ret, m_state);
+ m_state = SMS_IDLE;
+ return NET_PROTOCOL;
+ }
+
+ DBG("SM sent");
+ m_state = SMS_IDLE;
+ return OK;
+}
+
+
+int GSMSMSInterface::get(char* number, char* message, size_t maxLength)
+{
+ if( maxLength < 1 )
+ {
+ return NET_INVALID; //Buffer too short
+ }
+
+ int ret;
+
+ DBG("Get next message");
+ m_inboxMtx.lock();
+ if( ((m_msgRefListCount == 0) && m_needsUpdate) || ((m_msgRefListCount > 0) && (m_msgRefList[0] == -1)) )
+ {
+ DBG("Message list count is 0 and needs updating or next index is unknown, calling updateInbox()");
+ ret = updateInbox();
+
+ if (ret)
+ {
+ m_inboxMtx.unlock();
+ return ret;
+ }
+ }
+
+ DBG("%d messages to read", m_msgRefListCount);
+
+ if(m_msgRefListCount == 0)
+ {
+ m_inboxMtx.unlock();
+ DBG("Message list count is 0, I think it's empty and returning.");
+ return NET_EMPTY; //No message to read
+ }
+
+ //Prepare infos
+ m_state = SMS_GET_CMD_SENT;
+ m_msisdn = (char*) number;
+ m_msg = (char*) message;
+ m_maxMsgLength = maxLength;
+
+ DBG("Get SMS");
+ //List command
+ char cmd[32];
+ std::sprintf(cmd, "AT+CMGR=%d", m_msgRefList[0]);
+ ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
+ if( ret != OK )
+ {
+ WARN("AT+CMGR returned %d", ret);
+ m_state = SMS_IDLE;
+ m_inboxMtx.unlock();
+ return NET_PROTOCOL;
+ }
+
+ if (m_state != SMS_CMD_PROCESSED)
+ {
+ WARN("State variable is not 'SMS_CMD_PROCESSED' - returning 'NET_EMPTY'");
+ }
+
+ DBG("Deleting message from index number: %d", m_msgRefList[0] );
+ //Delete message from outbox
+ std::sprintf(cmd, "AT+CMGD=%d", m_msgRefList[0]);
+ ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
+ if(ret != OK)
+ {
+ ERR("Could not delete message");
+ }
+ //Remove message from list
+ std::memmove(&m_msgRefList[0], &m_msgRefList[1], MIN(m_msgRefListCount-1,MAX_SM-1)*sizeof(m_msgRefList[0]));
+ m_msgRefListCount--;
+
+ if(m_msgRefListCount > MAX_SM - 1) //Last message index is unknown, so put -1 to tell the lib to fetch it when needed
+ {
+ DBG("Last message index is unknown, will need to be updated");
+ m_msgRefList[MAX_SM - 1] = -1;
+ }
+
+ DBG("%d messages to read", m_msgRefListCount);
+
+ if (m_state != SMS_CMD_PROCESSED)
+ {
+ m_state = SMS_IDLE;
+ m_inboxMtx.unlock();
+ return NET_EMPTY;
+ }
+
+ m_state = SMS_IDLE;
+ m_inboxMtx.unlock();
+
+ return OK;
+}
+
+
+int GSMSMSInterface::getCount(size_t* pCount)
+{
+ int ret;
+
+ m_inboxMtx.lock();
+ if( m_needsUpdate )
+ {
+ ret = updateInbox();
+ if(ret)
+ {
+ m_inboxMtx.unlock();
+ return NET_PROTOCOL;
+ }
+ }
+
+ *pCount = m_msgRefListCount;
+ m_inboxMtx.unlock();
+
+ return OK;
+}
+
+
+/*virtual*/ int GSMSMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+{
+ if(m_state == SMS_SEND_CMD_SENT)
+ {
+ if( std::sscanf(line, "+CMGS: %*d") == 0 )
+ {
+ DBG("SM sent");
+ m_state = SMS_CMD_PROCESSED;
+ }
+ }
+ else if(m_state == SMS_GET_CMD_SENT)
+ {
+ DBG("Header: %s", line);
+ if( std::sscanf(line, "+CMGR: %*[^,],\"%16[^\"]\"", m_msisdn) == 1 ) //Get message ref
+ {
+ m_state = SMS_GET_HDR_RECEIVED;
+ }
+ }
+ else if(m_state == SMS_GET_HDR_RECEIVED)
+ {
+ DBG("Message: %s", line);
+ size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 );
+ std::memcpy( m_msg, line, cpyLen );
+ m_msg[cpyLen] = '\0';
+ m_state = SMS_CMD_PROCESSED;
+ }
+ else if(m_state == SMS_GET_COUNT_CMD_SENT)
+ {
+ DBG("Header: %s", line);
+ int msgRef;
+ if( std::sscanf(line, "+CMGL: %d,\"REC", &msgRef) == 1 ) //Filter on REC READ and REC UNREAD messages
+ {
+ m_state = SMS_GET_COUNT_HDR_RECEIVED;
+ //Add message to list
+ if(m_msgRefListCount < MAX_SM)
+ {
+ m_msgRefList[m_msgRefListCount] = msgRef;
+ }
+ m_msgRefListCount++; //Always count message
+ DBG("m_msgRefListCount=%d",m_msgRefListCount);
+ }
+ }
+ else if(m_state == SMS_GET_COUNT_HDR_RECEIVED)
+ {
+ DBG("Message (debug only): %s", line); //For debug only
+ m_state = SMS_GET_COUNT_CMD_SENT;
+ }
+ return OK;
+}
+
+/*virtual*/ int GSMSMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
+{
+ if(m_state == SMS_SEND_CMD_SENT)
+ {
+ char* crPtr = strchr(m_msg, CR);
+ if(crPtr != NULL)
+ {
+ int crPos = crPtr - m_msg;
+ //Replace m_inputBuf[crPos] with null-terminating char
+ m_msg[crPos] = '\x0';
+
+ //If there is a CR char, split message there
+
+ //Do print the message
+ int ret = pInst->sendData(m_msg);
+ if(ret)
+ {
+ return ret;
+ }
+
+ char cr[2] = {CR, '\0'};
+ ret = pInst->sendData(cr);
+ if(ret)
+ {
+ return ret;
+ }
+
+ m_msg += crPos;
+
+ if(m_msg[0] == LF)
+ {
+ m_msg++; //Discard LF char as well
+ }
+
+ return NET_MOREINFO;
+ }
+ else
+ {
+ //Do print the message
+ pInst->sendData(m_msg);
+ return OK;
+ }
+ }
+
+ return OK;
+}
+
+/*virtual*/ bool GSMSMSInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
+{
+ DBG("AT code is %s", atCode);
+ if( strcmp("+CMTI", atCode) == 0 )
+ {
+ return true;
+ }
+
+ DBG("Not handled");
+ return false;
+}
+
+/*virtual*/ void GSMSMSInterface::onDispatchStart()
+{
+
+}
+
+/*virtual*/ void GSMSMSInterface::onDispatchStop()
+{
+
+}
+
+/*virtual*/ char* GSMSMSInterface::getEventsEnableCommand()
+{
+ return "AT+CNMI=2,1,0,0,0";
+}
+
+/*virtual*/ char* GSMSMSInterface::getEventsDisableCommand()
+{
+ return "AT+CNMI=0,0,0,0,0"; //Indications will be buffered within the modem and flushed back when the former command is executed
+}
+
+/*virtual*/ void GSMSMSInterface::onEvent(const char* atCode, const char* evt)
+{
+ if( strcmp("+CMTI", atCode) != 0 )
+ {
+ return; //Not supported
+ }
+
+ DBG("Unsollicited result code: %s - %s", atCode, evt);
+
+ //Get index
+ int msgRef;
+ if(( std::sscanf(evt, "\"SM\",%d", &msgRef) == 1 ) ||
+ ( std::sscanf(evt, "\"ME\",%d", &msgRef) == 1 ))
+ {
+ DBG("Adding message to list (ref %d)", msgRef);
+ if(m_inboxMtx.trylock())
+ {
+ //Add message to list
+ if(m_msgRefListCount < MAX_SM)
+ {
+ m_msgRefList[m_msgRefListCount] = msgRef;
+ }
+ m_msgRefListCount++; //Always count message
+ m_inboxMtx.unlock();
+ }
+ else
+ {
+ WARN("Could not get lock");
+ m_needsUpdate = true;
+ }
+ }
+}
+
+int GSMSMSInterface::updateInbox()
+{
+ //Get memory indexes of unread messages
+
+ DBG("Updating inbox");
+ m_msgRefListCount = 0; //Reset list
+ m_needsUpdate = false; //Assume we won't need update after this routine (can be set to true by an incoming SM event)
+
+ //First list the "REC READ" messages that were not processed in the previous session
+ m_state = SMS_GET_COUNT_CMD_SENT;
+ int ret = m_pIf->execute("AT+CMGL=\"REC READ\"", this, NULL, DEFAULT_TIMEOUT);
+ if( ret != OK )
+ {
+ WARN("AT+CMGL returned %d", ret);
+ m_state = SMS_IDLE;
+ m_msgRefListCount = 0; //List could be invalid
+ m_needsUpdate = true;
+ return NET_PROTOCOL;
+ }
+
+ //Now list the "REC UNREAD" messages that were received by the modem since
+ m_state = SMS_GET_COUNT_CMD_SENT;
+ ret = m_pIf->execute("AT+CMGL=\"REC UNREAD\"", this, NULL, DEFAULT_TIMEOUT);
+ if( ret != OK )
+ {
+ WARN("AT+CMGL returned %d", ret);
+ m_state = SMS_IDLE;
+ m_msgRefListCount = 0; //List could be invalid
+ m_needsUpdate = true;
+ return NET_PROTOCOL;
+ }
+
+ DBG("%d incoming messages in inbox", m_msgRefListCount);
+
+ m_state = SMS_IDLE;
+
+ return OK;
+}
+
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/GSMSMSInterface.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/GSMSMSInterface.h
new file mode 100644
index 0000000000..446a73e518
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/GSMSMSInterface.h
@@ -0,0 +1,97 @@
+/* SMSInterface.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 GSMSMSINTERFACE_H_
+#define GSMSMSINTERFACE_H_
+
+#include "SMSInterface.h"
+
+/** Component to use the Short Messages Service (SMS)
+ *
+ */
+class GSMSMSInterface : public ISMSInterface, protected IATCommandsProcessor, IATEventsHandler
+{
+public:
+ /** Create SMSInterface instance
+ @param pIf Pointer to the ATCommandsInterface instance to use
+ */
+ GSMSMSInterface(ATCommandsInterface* pIf);
+
+ /** Initialize interface
+ Configure SMS commands & register for SMS-related unsolicited result codes
+ */
+ virtual int init();
+
+ /** Send a SM
+ @param number The receiver's phone number
+ @param message The message to send
+ @return 0 on success, error code on failure
+ */
+ virtual int send(const char* number, const char* message);
+
+
+ /** Receive a SM
+ @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the space for the null-terminating char)
+ @param message Pointer to a buffer to store the the incoming message
+ @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ virtual int get(char* number, char* message, size_t maxLength);
+
+
+ /** Get the number of SMs in the incoming box
+ @param pCount pointer to store the number of unprocessed SMs on
+ @return 0 on success, error code on failure
+ */
+ virtual int getCount(size_t* pCount);
+
+protected:
+ //IATCommandsProcessor
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst);
+
+ //IATEventsHandler
+ virtual bool isATCodeHandled(const char* atCode); //Is this AT code handled
+ virtual void onDispatchStart();
+ virtual void onDispatchStop();
+ virtual char* getEventsEnableCommand();
+ virtual char* getEventsDisableCommand();
+ virtual void onEvent(const char* atCode, const char* evt);
+
+ //Updates messages count/references
+ int updateInbox();
+
+private:
+ ATCommandsInterface* m_pIf;
+
+ //Current message
+ char* m_msg;
+ size_t m_maxMsgLength;
+ char* m_msisdn;
+
+ //Messages list
+ int m_msgRefList[MAX_SM];
+ size_t m_msgRefListCount;
+ bool m_needsUpdate;
+ Mutex m_inboxMtx; //To protect concurrent accesses btw the user's thread and the AT thread
+
+ enum { SMS_IDLE, SMS_SEND_CMD_SENT, SMS_GET_CMD_SENT, SMS_GET_HDR_RECEIVED, SMS_GET_COUNT_CMD_SENT, SMS_GET_COUNT_HDR_RECEIVED, SMS_CMD_PROCESSED } m_state;
+};
+
+#endif /* GSMSMSINTERFACE_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/SMSInterface.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/SMSInterface.h
new file mode 100644
index 0000000000..df226709d1
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/SMSInterface.h
@@ -0,0 +1,67 @@
+/* SMSInterface.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 ISMSINTERFACE_H_
+#define ISMSINTERFACE_H_
+
+#include "core/fwk.h"
+
+#include "rtos.h"
+
+#include "at/ATCommandsInterface.h"
+
+#define MAX_SM 8
+
+/** Component to use the Short Messages Service (SMS)
+ *
+ */
+class ISMSInterface
+{
+public:
+ /** Initialize interface
+ Configure SMS commands & register for SMS-related unsolicited result codes
+ */
+ virtual int init() = 0;
+
+
+ /** Send a SM
+ @param number The receiver's phone number
+ @param message The message to send
+ @return 0 on success, error code on failure
+ */
+ virtual int send(const char* number, const char* message) = 0;
+
+
+ /** Receive a SM
+ @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the space for the null-terminating char)
+ @param message Pointer to a buffer to store the the incoming message
+ @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ virtual int get(char* number, char* message, size_t maxLength) = 0;
+
+
+ /** Get the number of SMs in the incoming box
+ @param pCount pointer to store the number of unprocessed SMs on
+ @return 0 on success, error code on failure
+ */
+ virtual int getCount(size_t* pCount) = 0;
+};
+
+#endif /* ISMSINTERFACE_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ussd/USSDInterface.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ussd/USSDInterface.cpp
new file mode 100644
index 0000000000..4815babd6a
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ussd/USSDInterface.cpp
@@ -0,0 +1,196 @@
+/* USSDInterface.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__ 0
+#ifndef __MODULE__
+#define __MODULE__ "USSDInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "USSDInterface.h"
+
+#include <cstdio>
+
+#define DEFAULT_TIMEOUT 10000
+#define USSD_TIMEOUT 15000
+
+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
+ m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
+}
+
+int USSDInterface::init()
+{
+ DBG("Initialization done");
+ return OK;
+}
+
+int USSDInterface::send(const char* command, char* result, size_t maxLength)
+{
+ if (strlen(command) > 20) //Prevent buffer overflow
+ {
+ return NET_TOOSMALL;
+ }
+
+ m_responseMtx.lock();
+ m_result = result;
+ m_maxResultLength = maxLength;
+ m_responseMtx.unlock();
+
+ m_responseSphre.wait(0); //Make sure there is not a pending result that needs to be discarded
+
+ DBG("Send USSD command & register for unsolicited result codes");
+ //Send USSD command to the network
+ char cmd[32];
+ std::sprintf(cmd, "AT+CUSD=1,\"%s\"", command);
+ int ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
+ if( ret != OK )
+ {
+ return NET_PROTOCOL;
+ }
+
+ //Did we already get a response (3GPP rev < 6) ?
+
+ //Now wait for response
+ int res = m_responseSphre.wait(USSD_TIMEOUT);
+
+ //Reset data
+ m_responseMtx.lock();
+ m_result = NULL;
+ m_maxResultLength = 0;
+ m_responseMtx.unlock();
+
+ if(res <= 0)
+ {
+ DBG("No result received");
+ ret = m_pIf->executeSimple("AT+CUSD=2", NULL, DEFAULT_TIMEOUT); //Cancel command
+ if( ret != OK )
+ {
+ return NET_PROTOCOL;
+ }
+ return NET_TIMEOUT;
+ }
+
+ DBG("Result received: %s", result);
+
+ return OK;
+}
+
+/*virtual*/ int USSDInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+{
+ const char* pSemicol = strchr(line, ':');
+ if( ( (pSemicol - line) != strlen("+CUSD") ) || ( memcmp(line, "+CUSD", strlen("+CUSD")) != 0) )
+ {
+ WARN("Unknown code");
+ return OK;
+ }
+
+ const char* pData = NULL;
+ if( pSemicol != NULL ) //Split the identifier & the result code (if it exists)
+ {
+ pData = pSemicol + 1;
+ if(pData[0]==' ')
+ {
+ pData++; //Suppress whitespace
+ }
+ processResult(pData);
+ }
+ return OK;
+}
+
+/*virtual*/ int USSDInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
+{
+ return OK;
+}
+
+/*virtual*/ bool USSDInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
+{
+ DBG("AT code is %s", atCode);
+ if( strcmp("+CUSD", atCode) == 0 )
+ {
+ return true;
+ }
+
+ DBG("Not handled");
+ return false;
+}
+
+/*virtual*/ void USSDInterface::onDispatchStart()
+{
+
+
+}
+
+/*virtual*/ void USSDInterface::onDispatchStop()
+{
+
+}
+
+/*virtual*/ char* USSDInterface::getEventsEnableCommand()
+{
+ return NULL; //No need to disable events here
+}
+
+/*virtual*/ char* USSDInterface::getEventsDisableCommand()
+{
+ return NULL; //No need to re-enable events here
+}
+
+/*virtual*/ void USSDInterface::onEvent(const char* atCode, const char* evt)
+{
+ if( strcmp("+CUSD", atCode) != 0 )
+ {
+ WARN("Wrong AT Code");
+ return; //Not supported
+ }
+
+ processResult(evt);
+}
+
+void USSDInterface::processResult(const char* data)
+{
+ char* pStart = (char*) strchr(data,'\"');
+ if(pStart==NULL)
+ {
+ WARN("Could not find opening quote");
+ return; //Invalid/incomplete response
+ }
+ pStart++; //Point to first char of response
+ char* pEnd = (char*) strchr(pStart,'\"');
+ if(pEnd==NULL)
+ {
+ WARN("Could not find closing quote");
+ return; //Invalid/incomplete response
+ }
+ m_responseMtx.lock();
+ if(m_maxResultLength == 0) //No pending command
+ {
+ WARN("No pending command");
+ m_responseMtx.unlock();
+ return;
+ }
+ size_t cpyLen = MIN( pEnd - pStart, m_maxResultLength - 1 );
+ memcpy((void*)m_result, pStart, cpyLen);
+ m_result[cpyLen] = '\0';
+ DBG("Got USSD response: %s", m_result);
+ m_responseMtx.unlock();
+ m_responseSphre.release(); //Signal user thread that response is ready
+}
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ussd/USSDInterface.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ussd/USSDInterface.h
new file mode 100644
index 0000000000..47984d1d91
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/ussd/USSDInterface.h
@@ -0,0 +1,80 @@
+/* USSDInterface.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 USSDINTERFACE_H_
+#define USSDINTERFACE_H_
+
+#include "core/fwk.h"
+
+#include "rtos.h"
+
+#include "at/ATCommandsInterface.h"
+
+/** Component to send/receive Unstructured Supplementary Service Data (USSD)
+ *
+ */
+class USSDInterface : protected IATCommandsProcessor, IATEventsHandler
+{
+public:
+ /** Create USSDInterface instance
+ @param pIf Pointer to the ATCommandsInterface instance to use
+ */
+ USSDInterface(ATCommandsInterface* pIf);
+
+ /** Initialize interface
+ Configure USSD commands & register for USSD-related unsolicited result codes
+ */
+ int init();
+
+ /** Send a USSD command & wait for its result
+ @param command The command to send
+ @param result Buffer in which to store the result
+ @param maxLength Maximum result length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ int send(const char* command, char* result, size_t maxLength);
+
+protected:
+ //IATCommandsProcessor, needed for implementations of 3GGP standard < r06
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst);
+
+ //IATEventsHandler, needed for implementations of 3GGP standard >= r06
+ virtual bool isATCodeHandled(const char* atCode); //Is this AT code handled
+ virtual void onDispatchStart();
+ virtual void onDispatchStop();
+ virtual char* getEventsEnableCommand();
+ virtual char* getEventsDisableCommand();
+ virtual void onEvent(const char* atCode, const char* evt);
+
+private:
+ void processResult(const char* data);
+
+ ATCommandsInterface* m_pIf;
+ Mutex m_responseMtx; //To protect concurrent accesses btw the user's thread and the AT thread
+ Semaphore m_responseSphre;
+
+ //Result
+ volatile char* m_result;
+ volatile size_t m_maxResultLength;
+
+};
+
+
+#endif /* USSDINTERFACE_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/io/IOSerialStream.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/io/IOSerialStream.cpp
new file mode 100644
index 0000000000..2a05c1c2c4
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/io/IOSerialStream.cpp
@@ -0,0 +1,253 @@
+/* IOSerialStream.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__ 0 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "IOSerialStream.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include <cstring>
+
+#include "IOSerialStream.h"
+
+#define UART_X ((LPC_UART_TypeDef *)(UART_1))
+
+IOSerialStream::IOSerialStream(mbed::RawSerial& serial) : m_serial(serial), m_serialTxFifoEmpty(true),
+m_availableSphre(1), m_spaceSphre(1), m_inBuf(), m_outBuf()
+{
+ m_availableSphre.wait();
+ m_spaceSphre.wait();
+ //Attach interrupts
+ m_serial.attach(this, &IOSerialStream::readable, mbed::SerialBase::RxIrq);
+ m_serial.attach(this, &IOSerialStream::writeable, mbed::SerialBase::TxIrq);
+}
+
+/*virtual*/ IOSerialStream::~IOSerialStream()
+{
+ m_serial.attach(NULL, mbed::SerialBase::RxIrq);
+ m_serial.attach(NULL, mbed::SerialBase::TxIrq);
+}
+
+//0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+/*virtual*/ int IOSerialStream::read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout/*=osWaitForever*/)
+{
+ DBG("Trying to read at most %d chars", maxLength);
+ int ret = waitAvailable(timeout);
+ if(ret)
+ {
+ WARN("Error %d while waiting for incoming data", ret);
+ return ret;
+ }
+ int readLen = MIN( available(), maxLength );
+ *pLength = readLen;
+ setupReadableISR(false);
+ while(readLen--)
+ {
+ m_inBuf.dequeue(buf);
+ buf++;
+ }
+ setupReadableISR(true);
+ DBG("Read %d chars successfully", *pLength);
+ return OK;
+}
+
+/*virtual*/ size_t IOSerialStream::available()
+{
+ setupReadableISR(false); //m_inBuf.available() is not reentrant
+ size_t len = m_inBuf.available();
+ setupReadableISR(true);
+ return len;
+}
+
+/*virtual*/ int IOSerialStream::waitAvailable(uint32_t timeout/*=osWaitForever*/) //Wait for data to be available
+{
+ int ret;
+ if(available()) //Is data already available?
+ {
+ m_availableSphre.wait(0); //Clear the queue as data is available
+ return OK;
+ }
+
+ 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)
+ {
+ DBG("Timeout");
+ return NET_TIMEOUT;
+ }
+ if(!available()) //Even if abort has been called, return that data is available
+ {
+ DBG("Aborted");
+ return NET_INTERRUPTED;
+ }
+ DBG("Finished waiting");
+ m_availableSphre.wait(0); //Clear the queue as data is available
+ return OK;
+}
+
+/*virtual*/ int IOSerialStream::abortRead() //Abort current reading (or waiting) operation
+{
+ if( !available() ) //If there is data pending, no need to abort
+ {
+ m_availableSphre.release(); //Force exiting the waiting state; kludge to pass a RC directly
+ }
+ else
+ {
+ DBG("Serial is readable"); ;
+ }
+ return OK;
+}
+
+void IOSerialStream::setupReadableISR(bool en)
+{
+ if(en)
+ {
+ UART_X->IER |= 1 << 0;
+ }
+ else
+ {
+ UART_X->IER &= ~(1 << 0);
+ }
+}
+
+void IOSerialStream::readable() //Callback from m_serial when new data is available
+{
+ do
+ {
+ m_inBuf.queue(m_serial.getc());
+ } while(m_serial.readable());
+ m_availableSphre.release(); //Force exiting the waiting state
+}
+
+//0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+/*virtual*/ int IOSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=osWaitForever*/)
+{
+ DBG("Trying to write %d chars", length);
+ int ret = waitSpace(timeout);
+ if(ret)
+ {
+ WARN("Error %d while waiting for space", ret);
+ return ret;
+ }
+ DBG("Writing %d chars", length);
+ setupWriteableISR(false);
+ while(length)
+ {
+ m_outBuf.queue(*buf);
+ buf++;
+ length--;
+ if(length && !space())
+ {
+ DBG("Waiting to write remaining %d chars", length);
+ setupWriteableISR(true);
+ ret = waitSpace(timeout);
+ if(ret)
+ {
+ WARN("Error %d while waiting for space", ret);
+ return ret;
+ }
+ setupWriteableISR(false);
+ }
+ }
+ //If m_serial tx fifo is empty we need to manually tx a byte in order to trigger the interrupt
+ if( m_outBuf.available() && m_serialTxFifoEmpty )
+ {
+ m_serialTxFifoEmpty = false;
+ uint8_t c;
+ m_outBuf.dequeue(&c);
+ m_serial.putc((char)c);
+ }
+ setupWriteableISR(true);
+ DBG("Write successful");
+ return OK;
+}
+
+/*virtual*/ size_t IOSerialStream::space()
+{
+ setupWriteableISR(false); //m_outBuf.available() is not reentrant
+ size_t len = CIRCBUF_SIZE - m_outBuf.available();
+ setupWriteableISR(true);
+ return len;
+}
+
+/*virtual*/ int IOSerialStream::waitSpace(uint32_t timeout/*=osWaitForever*/) //Wait for space to be available
+{
+ int ret;
+ if(space()) //Is still space already left?
+ {
+ m_spaceSphre.wait(0); //Clear the queue as space is available
+ return OK;
+ }
+
+ 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)
+ {
+ DBG("Timeout");
+ return NET_TIMEOUT;
+ }
+ if(!space()) //Even if abort has been called, return that space is available
+ {
+ DBG("Aborted");
+ return NET_INTERRUPTED;
+ }
+ m_spaceSphre.wait(0); //Clear the queue as space is available
+ return OK;
+}
+
+/*virtual*/ int IOSerialStream::abortWrite() //Abort current writing (or waiting) operation
+{
+ if( !space() ) //If there is space left, no need to abort
+ {
+ m_spaceSphre.release(); //Force exiting the waiting state
+ }
+ return OK;
+}
+
+void IOSerialStream::setupWriteableISR(bool en)
+{
+ if(en)
+ {
+ UART_X->IER |= 1 << 1;
+ }
+ else
+ {
+ UART_X->IER &= ~(1 << 1);
+ }
+}
+
+void IOSerialStream::writeable() //Callback from m_serial when new space is available
+{
+ if(m_outBuf.isEmpty())
+ {
+ m_serialTxFifoEmpty = true;
+ }
+ else
+ {
+ while(m_serial.writeable() && !m_outBuf.isEmpty())
+ {
+ uint8_t c;
+ m_outBuf.dequeue(&c);
+ m_serial.putc((char)c);
+ }
+ }
+ m_spaceSphre.release(); //Force exiting the waiting state
+}
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/io/IOSerialStream.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/io/IOSerialStream.h
new file mode 100644
index 0000000000..7e9ef89d05
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/io/IOSerialStream.h
@@ -0,0 +1,72 @@
+/* IOSerialStream.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 IOSERIALSTREAM_H_
+#define IOSERIALSTREAM_H_
+
+#include "core/fwk.h"
+
+#include "RawSerial.h"
+
+#include "rtos.h"
+#include "core/MtxCircBuffer.h"
+
+/** Input Serial Stream for physical serial interfaces (UART...)
+This class is not thread-safe, except for the *Abort() methods that can be called by any thread/ISR
+*/
+class IOSerialStream : public IOStream
+{
+public:
+ enum { CIRCBUF_SIZE = 255 };
+ IOSerialStream(mbed::RawSerial& serial);
+ /*virtual*/ ~IOSerialStream();
+
+ //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);
+ virtual size_t available();
+ virtual int waitAvailable(uint32_t timeout=osWaitForever); //Wait for data to be available
+ virtual int abortRead(); //Abort current reading (or waiting) operation
+
+
+ //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+ virtual int write(uint8_t* buf, size_t length, uint32_t timeout=osWaitForever);
+ virtual size_t space();
+ virtual int waitSpace(uint32_t timeout=osWaitForever); //Wait for space to be available
+ virtual int abortWrite(); //Abort current writing (or waiting) operation
+
+private:
+
+ mbed::RawSerial& m_serial;
+ volatile bool m_serialTxFifoEmpty;
+
+ void setupReadableISR(bool en);
+ void readable(); //Callback from m_serial when new data is available
+
+ Semaphore m_availableSphre; //Used for signalling
+
+ void setupWriteableISR(bool en);
+ void writeable(); //Callback from m_serial when new space is available
+
+ Semaphore m_spaceSphre; //Used for signalling
+
+ MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_inBuf;
+ MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_outBuf;
+
+};
+
+#endif /* IOSERIALSTREAM_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/usb/USBSerialStream.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/usb/USBSerialStream.cpp
new file mode 100644
index 0000000000..81349ce884
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/usb/USBSerialStream.cpp
@@ -0,0 +1,236 @@
+/* USBSerialStream.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__ 0
+#ifndef __MODULE__
+#define __MODULE__ "USBSerialStream.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include <cstring>
+
+#include "USBSerialStream.h"
+
+
+USBSerialStream::USBSerialStream(IUSBHostSerial& serial) : m_serial(serial), m_serialTxFifoEmpty(true),
+m_availableSphre(1), m_spaceSphre(1), m_inBuf()
+{
+ m_availableSphre.wait();
+ m_spaceSphre.wait();
+ //Attach interrupts
+ m_serial.attach(this);
+}
+
+/*virtual*/ USBSerialStream::~USBSerialStream()
+{
+ m_serial.attach(NULL);
+}
+
+//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*/)
+{
+ DBG("Trying to read at most %d chars", maxLength);
+ int ret = waitAvailable(timeout);
+ if(ret)
+ {
+ WARN("Error %d while waiting for incoming data", ret);
+ return ret;
+ }
+ int a = available(); //Prevent macro issues
+ int readLen = MIN( a, maxLength );
+ *pLength = readLen;
+
+ setupReadableISR(false);
+ while(readLen--)
+ {
+ m_inBuf.dequeue(buf);
+ buf++;
+ }
+ setupReadableISR(true);
+ DBG("Read %d chars successfully", *pLength);
+ return OK;
+}
+
+/*virtual*/ size_t USBSerialStream::available()
+{
+ setupReadableISR(false); //m_inBuf.available() is not reentrant
+ size_t len = m_inBuf.available();
+ setupReadableISR(true);
+ return len;
+}
+
+/*virtual*/ int USBSerialStream::waitAvailable(uint32_t timeout/*=osWaitForever*/) //Wait for data to be available
+{
+ int ret;
+ if(available()) //Is data already available?
+ {
+ while( m_availableSphre.wait(0) > 0 ); //Clear the queue as data is available
+ return OK;
+ }
+
+ 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)
+ {
+ DBG("Timeout");
+ return NET_TIMEOUT;
+ }
+ if(!m_inBuf.available()) //Even if abort has been called, return that data is available
+ {
+ DBG("Aborted");
+ return NET_INTERRUPTED;
+ }
+ DBG("Finished waiting");
+ while( m_availableSphre.wait(0) > 0 ); //Clear the queue as data is available
+ return OK;
+}
+
+/*virtual*/ int USBSerialStream::abortRead() //Abort current reading (or waiting) operation
+{
+ if( /*!available()*/true ) //If there is data pending, no need to abort
+ {
+ m_availableSphre.release(); //Force exiting the waiting state
+ }
+ else
+ {
+ DBG("Serial is readable"); ;
+ }
+ return OK;
+}
+
+void USBSerialStream::setupReadableISR(bool en)
+{
+ m_serial.setupIrq(en, IUSBHostSerial::RxIrq);
+}
+
+void USBSerialStream::readable() //Callback from m_serial when new data is available
+{
+ while(m_serial.readable())
+ {
+ m_inBuf.queue(m_serial.getc());
+ }
+ m_serial.readPacket(); //Start read of next packet
+ 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*/)
+{
+ DBG("Trying to write %d chars", length);
+ do
+ {
+ int ret = waitSpace(timeout);
+ if(ret)
+ {
+ WARN("Error %d while waiting for space", ret);
+ return ret;
+ }
+ int s = space(); //Prevent macro issues
+ int writeLen = MIN( s, length );
+ DBG("Writing %d chars", writeLen);
+ setupWriteableISR(false);
+ while(writeLen)
+ {
+ m_outBuf.queue(*buf);
+ buf++;
+ length--;
+ writeLen--;
+ }
+ //If m_serial tx fifo is empty we need to start the packet write
+ if( m_outBuf.available() && m_serialTxFifoEmpty )
+ {
+ writeable();
+ }
+ setupWriteableISR(true);
+ } while(length);
+
+ DBG("Write successful");
+ return OK;
+}
+
+/*virtual*/ size_t USBSerialStream::space()
+{
+ setupWriteableISR(false); //m_outBuf.available() is not reentrant
+ size_t len = CIRCBUF_SIZE - m_outBuf.available();
+ setupWriteableISR(true);
+ return len;
+}
+
+/*virtual*/ int USBSerialStream::waitSpace(uint32_t timeout/*=-1*/) //Wait for space to be available
+{
+ int ret;
+ if(space()) //Is still space already left?
+ {
+ while( m_spaceSphre.wait(0) > 0); //Clear the queue as space is available
+ return OK;
+ }
+
+ 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)
+ {
+ DBG("Timeout");
+ return NET_TIMEOUT;
+ }
+ if(!space()) //Even if abort has been called, return that space is available
+ {
+ DBG("Aborted");
+ return NET_INTERRUPTED;
+ }
+ while( m_spaceSphre.wait(0) > 0); //Clear the queue as space is available
+ return OK;
+}
+
+/*virtual*/ int USBSerialStream::abortWrite() //Abort current writing (or waiting) operation
+{
+ if( !space() ) //If there is space left, no need to abort
+ {
+ m_spaceSphre.release(); //Force exiting the waiting state
+ }
+ return OK;
+}
+
+void USBSerialStream::setupWriteableISR(bool en)
+{
+ m_serial.setupIrq(en, IUSBHostSerial::TxIrq);
+}
+
+void USBSerialStream::writeable() //Callback from m_serial when new space is available
+{
+ if(m_outBuf.isEmpty())
+ {
+ m_serialTxFifoEmpty = true;
+ }
+ else
+ {
+ m_serialTxFifoEmpty = false;
+ while(m_serial.writeable() && !m_outBuf.isEmpty())
+ {
+ uint8_t c;
+ m_outBuf.dequeue(&c);
+ m_serial.putc((char)c);
+ }
+ m_serial.writePacket(); //Start packet write
+ }
+ if(!m_outBuf.isFull())
+ {
+ m_spaceSphre.release(); //Force exiting the waiting state
+ }
+}
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/usb/USBSerialStream.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/usb/USBSerialStream.h
new file mode 100644
index 0000000000..97cf3c6860
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularUSBModem/serial/usb/USBSerialStream.h
@@ -0,0 +1,74 @@
+/* USBSerialStream.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 USBSERIALSTREAM_H_
+#define USBSERIALSTREAM_H_
+
+
+#include "core/fwk.h"
+
+#include "USBHost3GModule/IUSBHostSerial.h"
+#include "USBHost3GModule/IUSBHostSerialListener.h"
+
+#include "rtos.h"
+#include "core/MtxCircBuffer.h"
+
+/* Input Serial Stream for USB virtual serial ports interfaces
+This class is not thread-safe, except for the *Abort() methods that can be called by any thread/ISR
+*/
+
+class USBSerialStream : public IOStream, IUSBHostSerialListener
+{
+public:
+ enum { CIRCBUF_SIZE = 127 };
+ USBSerialStream(IUSBHostSerial& serial);
+ /*virtual*/ ~USBSerialStream();
+
+ //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);
+ virtual size_t available();
+ virtual int waitAvailable(uint32_t timeout=osWaitForever); //Wait for data to be available
+ virtual int abortRead(); //Abort current reading (or waiting) operation
+
+
+ //0 for non-blocking (returns immediately), osWaitForever for infinite blocking
+ virtual int write(uint8_t* buf, size_t length, uint32_t timeout=osWaitForever);
+ virtual size_t space();
+ virtual int waitSpace(uint32_t timeout=osWaitForever); //Wait for space to be available
+ virtual int abortWrite(); //Abort current writing (or waiting) operation
+
+private:
+ IUSBHostSerial& m_serial;
+ volatile bool m_serialTxFifoEmpty;
+
+ void setupReadableISR(bool en);
+ virtual void readable(); //Callback from m_serial when new data is available
+
+ Semaphore m_availableSphre; //Used for signalling
+
+ void setupWriteableISR(bool en);
+ virtual void writeable(); //Callback from m_serial when new space is available
+
+ Semaphore m_spaceSphre; //Used for signalling
+
+ MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_inBuf;
+ MtxCircBuffer<uint8_t, CIRCBUF_SIZE + 1> m_outBuf;
+};
+
+#endif /* USBSERIALSTREAM_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxCDMAModemInitializer.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxCDMAModemInitializer.cpp
new file mode 100644
index 0000000000..6464afc984
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxCDMAModemInitializer.cpp
@@ -0,0 +1,114 @@
+/* Copyright (c) 2010-2012 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#define __DEBUG__ 4
+#ifndef __MODULE__
+#define __MODULE__ "UbloxCDMAModemInitializer.cpp"
+#endif
+
+#include "core/dbg.h"
+
+#include <stdint.h>
+
+#include "UbloxCDMAModemInitializer.h"
+
+UbloxCDMAModemInitializer::UbloxCDMAModemInitializer(USBHost* pHost) : WANDongleInitializer(pHost)
+{
+}
+
+uint16_t UbloxCDMAModemInitializer::getMSDVid()
+{
+ return 0x05C6;
+}
+uint16_t UbloxCDMAModemInitializer::getMSDPid()
+{
+ return 0x0000; //No MSD mode (presumably)
+}
+
+uint16_t UbloxCDMAModemInitializer::getSerialVid()
+{
+ return 0x05C6;
+}
+uint16_t UbloxCDMAModemInitializer::getSerialPid()
+{
+ return 0x9004;
+}
+
+bool UbloxCDMAModemInitializer::switchMode(USBDeviceConnected* pDev)
+{
+ return true;
+}
+
+int UbloxCDMAModemInitializer::getSerialPortCount()
+{
+ return 2;
+}
+
+/*virtual*/ void UbloxCDMAModemInitializer::setVidPid(uint16_t vid, uint16_t pid)
+{
+ m_currentSerialIntf = 0;
+ m_currentEndpoint = 0;
+}
+
+/*virtual*/ bool UbloxCDMAModemInitializer::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+ DBG("Interface #%d; Class:%02x; SubClass:%02x; Protocol:%02x", intf_nb, intf_class, intf_subclass, intf_protocol);
+
+ if( intf_class == 0xFF ) {
+ if( m_currentSerialIntf == 0 || m_currentSerialIntf == 1) {
+ m_serialIntfMap[m_currentSerialIntf++] = intf_nb;
+ return true;
+ }
+ m_currentSerialIntf++;
+ }
+
+ return false;
+}
+
+/*virtual*/ bool UbloxCDMAModemInitializer::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+ DBG("USBEndpoint on Interface #%d; Type:%d; Direction:%d Current %d", intf_nb, type, dir, m_currentEndpoint);
+ if(type == BULK_ENDPOINT) {
+ if( intf_nb == 1 || intf_nb == 0) {
+ m_currentEndpoint++;
+ return true;
+ } else {
+ m_currentEndpoint++;
+ }
+ }
+
+ /*
+ if(type == INTERRUPT_ENDPOINT) {
+ if( intf_nb == 1) {
+ m_currentEndpoint++;
+ return true;
+ } else {
+ m_currentEndpoint++;
+ }
+ }
+ */
+
+ return false;
+}
+
+
+/*virtual*/ int UbloxCDMAModemInitializer::getType()
+{
+ return WAN_DONGLE_TYPE_UBLOX_LISAC200;
+}
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxCDMAModemInitializer.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxCDMAModemInitializer.h
new file mode 100644
index 0000000000..4836680da2
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxCDMAModemInitializer.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2010-2012 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef UBLOXCDMAMODEMINITIALIZER_H
+#define UBLOXCDMAMODEMINITIALIZER_H
+
+#include <stdint.h>
+
+#include "WANDongleInitializer.h"
+#include "USBHost.h"
+#include "IUSBEnumerator.h"
+
+enum
+{
+ WAN_DONGLE_TYPE_UBLOX_LISAC200 = 0xC200,
+};
+
+class UbloxCDMAModemInitializer : public WANDongleInitializer
+{
+public:
+ UbloxCDMAModemInitializer(USBHost* pHost);
+
+ virtual uint16_t getMSDVid();
+ virtual uint16_t getMSDPid();
+
+ virtual uint16_t getSerialVid();
+ virtual uint16_t getSerialPid();
+
+ virtual bool switchMode(USBDeviceConnected* pDev);
+
+ virtual int getSerialPortCount();
+
+ virtual void setVidPid(uint16_t vid, uint16_t pid);
+
+ virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+
+ virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+ virtual int getType();
+
+private:
+
+ int m_currentSerialIntf;
+ int m_currentEndpoint;
+};
+
+#endif
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxGSMModemInitializer.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxGSMModemInitializer.cpp
new file mode 100644
index 0000000000..e28632593a
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxGSMModemInitializer.cpp
@@ -0,0 +1,131 @@
+/* Copyright (c) 2010-2012 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "UbloxGSMModemInitializer.h"
+#include "core/dbg.h"
+
+#define __DEBUG__ 0
+#ifndef __MODULE__
+#define __MODULE__ "UbloxGSMModemInitializer.cpp"
+#endif
+
+//-----------------------------------------------------------------------
+// mamm, u-blox Modem
+//-----------------------------------------------------------------------
+
+UbloxGSMModemInitializer::UbloxGSMModemInitializer(USBHost* pHost) : WANDongleInitializer(pHost)
+{
+
+}
+
+uint16_t UbloxGSMModemInitializer::getMSDVid() { return 0x1546; }
+uint16_t UbloxGSMModemInitializer::getMSDPid() { return 0x0000; }
+
+uint16_t UbloxGSMModemInitializer::getSerialVid() { return 0x1546; }
+uint16_t UbloxGSMModemInitializer::getSerialPid() { return 0x1102; }
+
+bool UbloxGSMModemInitializer::switchMode(USBDeviceConnected* pDev)
+{
+ for (int i = 0; i < pDev->getNbIntf(); i++)
+ {
+ if (pDev->getInterface(i)->intf_class == MSD_CLASS)
+ {
+ USBEndpoint* pEp = pDev->getEndpoint(i, BULK_ENDPOINT, OUT);
+ if ( pEp != NULL )
+ {
+ ERR("MSD descriptor found on device %p, intf %d", (void *)pDev, i);
+ }
+ }
+ }
+ return false;
+}
+
+#define UBX_SERIALCOUNT 7
+
+int UbloxGSMModemInitializer::getSerialPortCount()
+{
+ return UBX_SERIALCOUNT;
+}
+
+/*virtual*/ void UbloxGSMModemInitializer::setVidPid(uint16_t vid, uint16_t pid)
+{
+ if( (vid == getSerialVid() ) && ( pid == getSerialPid() ) )
+ {
+ m_hasSwitched = true;
+ m_currentSerialIntf = 0;
+ m_endpointsToFetch = UBX_SERIALCOUNT*2;
+ }
+ else
+ {
+ m_hasSwitched = false;
+ m_endpointsToFetch = 1;
+ }
+}
+
+/*virtual*/ bool UbloxGSMModemInitializer::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+ if( m_hasSwitched )
+ {
+ DBG("Interface #%d; Class:%02x; SubClass:%02x; Protocol:%02x", intf_nb, intf_class, intf_subclass, intf_protocol);
+ if( intf_class == 0x0A )
+ {
+ if( (m_currentSerialIntf == 0) || (m_currentSerialIntf == 1) )
+ {
+ m_serialIntfMap[m_currentSerialIntf++] = intf_nb;
+ return true;
+ }
+ m_currentSerialIntf++;
+ }
+ }
+ else
+ {
+ if( (intf_nb == 0) && (intf_class == MSD_CLASS) )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*virtual*/ bool UbloxGSMModemInitializer::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+ if( m_hasSwitched )
+ {
+ DBG("USBEndpoint on Interface #%d; Type:%d; Direction:%d", intf_nb, type, dir);
+ if( (type == BULK_ENDPOINT) && m_endpointsToFetch )
+ {
+ m_endpointsToFetch--;
+ return true;
+ }
+ }
+ else
+ {
+ if( (type == BULK_ENDPOINT) && (dir == OUT) && m_endpointsToFetch )
+ {
+ m_endpointsToFetch--;
+ return true;
+ }
+ }
+ return false;
+}
+
+/*virtual*/ int UbloxGSMModemInitializer::getType()
+{
+ return WAN_DONGLE_TYPE_UBLOX_LISAU200;
+}
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxGSMModemInitializer.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxGSMModemInitializer.h
new file mode 100644
index 0000000000..383c443eb3
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxGSMModemInitializer.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2010-2012 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef UBLOXGSMMODEMINITIALIZER_H
+#define UBLOXGSNMODEMINITIALIZER_H
+
+#include "WANDongleInitializer.h"
+
+enum
+{
+ WAN_DONGLE_TYPE_UBLOX_LISAU200 = 0x0200
+};
+
+//-----------------------------------------------------------------------
+// mamm, u-blox Modem
+//-----------------------------------------------------------------------
+
+class UbloxGSMModemInitializer : public WANDongleInitializer
+{
+public:
+ UbloxGSMModemInitializer(USBHost* pHost);
+
+ virtual uint16_t getMSDVid();
+ virtual uint16_t getMSDPid();
+
+ virtual uint16_t getSerialVid();
+ virtual uint16_t getSerialPid();
+
+ virtual bool switchMode(USBDeviceConnected* pDev);
+
+ virtual int getSerialPortCount();
+
+ virtual void setVidPid(uint16_t vid, uint16_t pid);
+
+ virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+
+ virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+ virtual int getType();
+
+private:
+
+ bool m_hasSwitched;
+ int m_currentSerialIntf;
+ int m_endpointsToFetch;
+};
+
+#endif
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxModem.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxModem.cpp
new file mode 100644
index 0000000000..a9fec4cbf0
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxModem.cpp
@@ -0,0 +1,559 @@
+/* UbloxModem.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__ "UbloxModem.cpp"
+#endif
+
+#include "core/fwk.h"
+#include "sms/GSMSMSInterface.h"
+#include "sms/CDMASMSInterface.h"
+
+#include "UbloxModem.h"
+
+UbloxModem::UbloxModem(IOStream* atStream, IOStream* pppStream) :
+ m_at(atStream), // Construct ATCommandsInterface with the AT serial channel
+ m_CdmaSms(&m_at), // Construct SMSInterface with the ATCommandsInterface
+ m_GsmSms(&m_at), // Construct SMSInterface with the ATCommandsInterface
+ m_ussd(&m_at), // Construct USSDInterface with the ATCommandsInterface
+ m_linkMonitor(&m_at), // Construct LinkMonitor with the ATCommandsInterface
+ m_ppp(pppStream ? pppStream : atStream), // Construct PPPIPInterface with the PPP serial channel
+ m_ipInit(false), // PPIPInterface connection is initially down
+ m_smsInit(false), // SMSInterface starts un-initialised
+ m_ussdInit(false), // USSDInterface starts un-initialised
+ m_linkMonitorInit(false), // LinkMonitor subsystem starts un-initialised
+ m_atOpen(false), // ATCommandsInterface starts in a closed state
+ m_onePort(pppStream == NULL),
+ m_type(UNKNOWN)
+{
+}
+
+
+genericAtProcessor::genericAtProcessor()
+{
+ i = 0;
+ str[0] = '\0';
+}
+
+const char* genericAtProcessor::getResponse(void)
+{
+ return str;
+}
+
+int genericAtProcessor::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+{
+ int l = strlen(line);
+ if (i + l + 2 > sizeof(str))
+ return NET_OVERFLOW;
+ if (i) str[i++] = ',';
+ strcat(&str[i], line);
+ i += l;
+ return OK;
+}
+
+int genericAtProcessor::onNewEntryPrompt(ATCommandsInterface* pInst)
+{
+ return OK;
+}
+
+class CREGProcessor : public IATCommandsProcessor
+{
+public:
+ CREGProcessor(bool gsm) : status(STATUS_REGISTERING)
+ {
+ m_gsm = gsm;
+ }
+ enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK, STATUS_FAILED };
+ REGISTERING_STATUS getStatus()
+ {
+ return status;
+ }
+ const char* getAtCommand()
+ {
+ return m_gsm ? "AT+CREG?" : "AT+CSS?";
+ }
+private:
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+ {
+ int r;
+ if (m_gsm)
+ {
+ if( sscanf(line, "+CREG: %*d,%d", &r) == 1 )
+ {
+ status = (r == 1 || r == 5) ? STATUS_OK :
+ (r == 0 || r == 2) ? STATUS_REGISTERING :
+ // (r == 3) ? STATUS_FAILED :
+ STATUS_FAILED;
+ }
+ }
+ else
+ {
+ char bc[3] = "";
+ if(sscanf(line, "%*s %*c,%2s,%*d",bc)==1)
+ {
+ status = (strcmp("Z", bc) == 0) ? STATUS_REGISTERING : STATUS_OK;
+ }
+ }
+ return OK;
+ }
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+ {
+ return OK;
+ }
+ volatile REGISTERING_STATUS status;
+ bool m_gsm;
+};
+
+int UbloxModem::connect(const char* apn, const char* user, const char* password)
+{
+ if( !m_ipInit )
+ {
+ m_ipInit = true;
+ m_ppp.init();
+ }
+ m_ppp.setup(user, password, (m_type != LISA_C200) ? DEFAULT_MSISDN_GSM : DEFAULT_MSISDN_CDMA);
+
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if (m_onePort)
+ {
+ m_smsInit = false; //SMS status reset
+ m_ussdInit = false; //USSD status reset
+ m_linkMonitorInit = false; //Link monitor status reset
+ }
+
+ ATCommandsInterface::ATResult result;
+
+ if(apn != NULL)
+ {
+ char cmd[48];
+ int tries = 30;
+ sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
+ do //Try 30 times because for some reasons it can fail *a lot* with the K3772-Z dongle
+ {
+ ret = m_at.executeSimple(cmd, &result);
+ DBG("Result of command: Err code=%d", ret);
+ if(ret)
+ {
+ Thread::wait(500);
+ }
+ } while(ret && --tries);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+ DBG("APN set to %s", apn);
+ }
+
+ //Connect
+ DBG("Connecting");
+ if (m_onePort)
+ {
+ m_at.close(); // Closing AT parser
+ m_atOpen = false; //Will need to be reinitialized afterwards
+ }
+
+ DBG("Connecting PPP");
+
+ ret = m_ppp.connect();
+ DBG("Result of connect: Err code=%d", ret);
+ return ret;
+}
+
+
+int UbloxModem::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 (m_onePort)
+ {
+ //ATCommandsInterface::ATResult result;
+ DBG("Starting AT thread");
+ ret = m_at.open();
+ if(ret)
+ {
+ return ret;
+ }
+ }
+
+ DBG("Trying to hangup");
+
+ if (m_onePort)
+ {
+ //Reinit AT parser
+ ret = m_at.init(false);
+ 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;
+ }
+
+ }
+ return OK;
+}
+
+int UbloxModem::sendSM(const char* number, const char* message)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ ISMSInterface* sms;
+ if (m_type == LISA_C200) sms = &m_CdmaSms;
+ else sms = &m_GsmSms;
+ if(!m_smsInit)
+ {
+ ret = sms->init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = sms->send(number, message);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxModem::getSM(char* number, char* message, size_t maxLength)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ ISMSInterface* sms;
+ if (m_type == LISA_C200) sms = &m_CdmaSms;
+ else sms = &m_GsmSms;
+ if(!m_smsInit)
+ {
+ ret = sms->init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = sms->get(number, message, maxLength);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxModem::getSMCount(size_t* pCount)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ ISMSInterface* sms;
+ if (m_type == LISA_C200) sms = &m_CdmaSms;
+ else sms = &m_GsmSms;
+ if(!m_smsInit)
+ {
+ ret = sms->init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = sms->getCount(pCount);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+ATCommandsInterface* UbloxModem::getATCommandsInterface()
+{
+ return &m_at;
+}
+
+int UbloxModem::init()
+{
+ 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(false);
+ if(ret)
+ {
+ return ret;
+ }
+
+
+ ATCommandsInterface::ATResult result;
+ genericAtProcessor atiProcessor;
+ ret = m_at.execute("ATI", &atiProcessor, &result);
+ if (OK != ret)
+ return ret;
+ const char* info = atiProcessor.getResponse();
+ INFO("Modem Identification [%s]", info);
+ if (strstr(info, "LISA-C200")) {
+ m_type = LISA_C200;
+ m_onePort = true; // force use of only one port
+ }
+ else if (strstr(info, "LISA-U200")) {
+ m_type = LISA_U200;
+ }
+ else if (strstr(info, "SARA-G350")) {
+ m_type = SARA_G350;
+ }
+
+ // enable the network indicator
+ if (m_type == SARA_G350) {
+ m_at.executeSimple("AT+UGPIOC=16,2", &result);
+ }
+ else if (m_type == LISA_U200) {
+ m_at.executeSimple("AT+UGPIOC=20,2", &result);
+ }
+ else if (m_type == LISA_C200) {
+ // LISA-C200 02S/22S : GPIO1 do not support network status indication
+ // m_at.executeSimple("AT+UGPIOC=20,2", &result);
+ }
+ INFO("Modem Identification [%s]", info);
+
+ CREGProcessor cregProcessor(m_type != LISA_C200);
+ //Wait for network registration
+ do
+ {
+ DBG("Waiting for network registration");
+ ret = m_at.execute(cregProcessor.getAtCommand(), &cregProcessor, &result);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING)
+ {
+ Thread::wait(3000);
+ }
+ } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING);
+ if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED)
+ {
+ ERR("Registration denied");
+ return NET_AUTH;
+ }
+
+ m_atOpen = true;
+
+ return OK;
+}
+
+int UbloxModem::cleanup()
+{
+ if(m_ppp.isConnected())
+ {
+ WARN("Data connection is still open"); //Try to encourage good behaviour from the user
+ m_ppp.disconnect();
+ }
+
+ m_smsInit = false;
+ m_ussdInit = false;
+ m_linkMonitorInit = false;
+ //We don't reset m_ipInit as PPPIPInterface::init() only needs to be called once
+
+ if(m_atOpen)
+ {
+ m_at.close();
+ m_atOpen = false;
+ }
+
+ return OK;
+}
+
+int UbloxModem::sendUSSD(const char* command, char* result, size_t maxLength)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_ussdInit)
+ {
+ ret = m_ussd.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_ussdInit = true;
+ }
+
+ ret = m_ussd.send(command, result, maxLength);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxModem::getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegistrationState, LinkMonitor::BEARER* pBearer)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_linkMonitorInit)
+ {
+ ret = m_linkMonitor.init(m_type != LISA_C200);
+ if(ret)
+ {
+ return ret;
+ }
+ m_linkMonitorInit = true;
+ }
+
+ ret = m_linkMonitor.getState(pRssi, pRegistrationState, pBearer);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxModem::getPhoneNumber(char* phoneNumber)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_linkMonitorInit)
+ {
+ ret = m_linkMonitor.init(m_type != LISA_C200);
+ if(ret)
+ {
+ return ret;
+ }
+ m_linkMonitorInit = true;
+ }
+
+ ret = m_linkMonitor.getPhoneNumber(phoneNumber);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+#include "USBHost.h"
+#include "UbloxGSMModemInitializer.h"
+#include "UbloxCDMAModemInitializer.h"
+
+UbloxUSBModem::UbloxUSBModem() :
+ UbloxModem(&m_atStream, &m_pppStream),
+ m_dongle(), // Construct WANDongle: USB interface with two serial channels to the modem (USBSerialStream objects)
+ m_atStream(m_dongle.getSerial(1)), // AT commands are sent down one serial channel.
+ m_pppStream(m_dongle.getSerial(0)), // PPP connections are managed via another serial channel.
+ m_dongleConnected(false) // Dongle is initially not ready for anything
+{
+ USBHost* host = USBHost::getHostInst();
+ m_dongle.addInitializer(new UbloxGSMModemInitializer(host));
+ m_dongle.addInitializer(new UbloxCDMAModemInitializer(host));
+}
+
+int UbloxUSBModem::init()
+{
+ if( !m_dongleConnected )
+ {
+ m_dongleConnected = true;
+ while( !m_dongle.connected() )
+ {
+ m_dongle.tryConnect();
+ Thread::wait(10);
+ }
+ if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAU200)
+ {
+ INFO("Using a u-blox LISA-U200 3G/WCDMA Modem");
+ m_type = LISA_U200;
+ }
+ else if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAC200)
+ {
+ INFO("Using a u-blox LISA-C200 CDMA Modem");
+ m_type = LISA_C200;
+ m_onePort = true;
+ }
+ else
+ {
+ WARN("Using an Unknown Dongle");
+ }
+ }
+ return UbloxModem::init();
+}
+
+int UbloxUSBModem::cleanup()
+{
+ UbloxModem::cleanup();
+ m_dongle.disconnect();
+ m_dongleConnected = false;
+ return OK;
+}
+
+UbloxSerModem::UbloxSerModem() :
+ UbloxModem(&m_atStream, NULL),
+ m_Serial(P0_15/*MDMTXD*/,P0_16/*MDMRXD*/),
+ m_atStream(m_Serial)
+{
+ m_Serial.baud(115200/*MDMBAUD*/);
+ m_Serial.set_flow_control(SerialBase::RTSCTS, P0_22/*MDMRTS*/, P0_17/*MDMCTS*/);
+}
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxModem.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxModem.h
new file mode 100644
index 0000000000..dc0e1205a4
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxModem.h
@@ -0,0 +1,183 @@
+/* VodafoneUSBModem.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef UBLOXMODEM_H_
+#define UBLOXMODEM_H_
+
+#include "core/fwk.h"
+
+#include "at/ATCommandsInterface.h"
+#include "ip/PPPIPInterface.h"
+#include "sms/GSMSMSInterface.h"
+#include "sms/CDMASMSInterface.h"
+#include "ussd/USSDInterface.h"
+#include "link/LinkMonitor.h"
+#include "CellularModem.h"
+
+class genericAtProcessor : public IATCommandsProcessor
+{
+public:
+ genericAtProcessor();
+ const char* getResponse(void);
+private:
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst);
+protected:
+ char str[256];
+ int i;
+};
+
+/** u-blox WCDMA modem (LISA-U200)
+ */
+class UbloxModem: public CellularModem
+{
+public:
+ /** Create u-blox API instance
+ @param powerGatingPin Optional pin commanding a power gating transistor on the modem's power line
+ @param powerGatingOnWhenPinHigh true if the pin needs to be high to power the dongle, defaults to true
+ */
+ UbloxModem(IOStream* atStream, IOStream* pppStream);
+
+ //Internet-related functions
+
+ /** Open a 3G internet connection
+ @return 0 on success, error code on failure
+ */
+ virtual int connect(const char* apn = NULL, const char* user = NULL, const char* password = NULL);
+
+ /** Close the internet connection
+ @return 0 on success, error code on failure
+ */
+ virtual int disconnect();
+
+
+ /** Send a SM
+ @param number The receiver's phone number
+ @param message The message to send
+ @return 0 on success, error code on failure
+ */
+ virtual int sendSM(const char* number, const char* message);
+
+
+ /** Receive a SM
+ @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the sapce for the null-terminating char)
+ @param message Pointer to a buffer to store the the incoming message
+ @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ virtual int getSM(char* number, char* message, size_t maxLength);
+
+ /** Get the number of SMs in the incoming box
+ @param pCount pointer to store the number of unprocessed SMs on
+ @return 0 on success, error code on failure
+ */
+ virtual int getSMCount(size_t* pCount);
+
+ /** Send a USSD command & wait for its result
+ @param command The command to send
+ @param result Buffer in which to store the result
+ @param maxLength Maximum result length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ int sendUSSD(const char* command, char* result, size_t maxLength);
+
+ /** Get link state
+ @param pRssi pointer to store the current RSSI in dBm, between -51 dBm and -113 dBm if known; -51 dBm means -51 dBm or more; -113 dBm means -113 dBm or less; 0 if unknown
+ @param pRegistrationState pointer to store the current registration state
+ @param pBearer pointer to store the current bearer
+ @return 0 on success, error code on failure
+ */
+ int getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegistrationState, LinkMonitor::BEARER* pBearer);
+
+ int getPhoneNumber(char* phoneNumber);
+
+ /** Get the ATCommandsInterface instance
+ @return Pointer to the ATCommandsInterface instance
+ */
+ virtual ATCommandsInterface* getATCommandsInterface();
+
+protected:
+ /** Initialise dongle.
+ * The following actions are performed:
+ * 1) Start AT interface thread
+ * 2) Wait for network registration
+ */
+ virtual int init();
+
+ /** De-initialise dongle.
+ * The following actions are performed:
+ * 1) Tear down PPP session
+ * 2) Set SMS,USSD, and LinkMonitor subsystems to un-initialised
+ * 3) Close the AT commands interface
+ */
+ virtual int cleanup();
+
+private:
+ ATCommandsInterface m_at; //< Interface to AT commands processing
+
+ CDMASMSInterface m_CdmaSms; //< Interface to SMS manager (send/receive etc)
+ GSMSMSInterface m_GsmSms; //< Interface to SMS manager (send/receive etc)
+ USSDInterface m_ussd; //< Interface to USSD manager (send etc)
+ LinkMonitor m_linkMonitor; //< Interface to link monitor (RSSI)
+
+ PPPIPInterface m_ppp; //< Interface to PPP conection manager (IP assignment etc)
+
+ bool m_ipInit; //< Has PPIPInterface object (m_ppp) been initialised? true/false
+ bool m_smsInit; //< Has SMSInterface object (m_sms) been initialised? true/false
+ bool m_ussdInit; //< Has USSDInterface object (m_ussd) been initialised? true/false
+ bool m_linkMonitorInit; //< Has LinkMonitor object (m_linkMonitor) been initialised? true/false
+ bool m_atOpen; //< Is the interface to the ATCommandsInterface open? true/false
+protected:
+ bool m_onePort;
+ enum { LISA_C200, LISA_U200, SARA_G350, UNKNOWN } m_type;
+};
+
+#include "WANDongle.h"
+#include "serial/usb/USBSerialStream.h"
+
+class UbloxUSBModem: public UbloxModem
+{
+public:
+ UbloxUSBModem();
+ virtual int init();
+ virtual int cleanup();
+ virtual int power(bool enable) { return 1; }
+
+private:
+ WANDongle m_dongle; //< Interface to USB connected WAN dongle
+
+ USBSerialStream m_atStream; //< Serial interface to AT channel on modem
+ USBSerialStream m_pppStream; //< Serial interface to PPP channel on modem
+
+ bool m_dongleConnected; //< Is the dongle physically connected (does the USB stack respond)? true/false
+};
+
+#include "serial/io/IOSerialStream.h"
+
+class UbloxSerModem: public UbloxModem
+{
+public:
+ UbloxSerModem();
+ virtual int power(bool enable) { return 1; }
+private:
+ RawSerial m_Serial;
+ IOSerialStream m_atStream; //< Serial interface to AT channel on modem
+};
+
+#endif /* UBLOXMODEM_H_ */
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBCDMAModem.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBCDMAModem.cpp
new file mode 100644
index 0000000000..5e4e32a2b5
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBCDMAModem.cpp
@@ -0,0 +1,398 @@
+/* UbloxUSBCDMAModem.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define __DEBUG__ 4
+#ifndef __MODULE__
+#define __MODULE__ "UbloxUSBCDMAModem.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "UbloxUSBCDMAModem.h"
+#include "UbloxCDMAModemInitializer.h"
+#include "USBHost.h"
+
+#define USE_ONE_PORT 1
+
+UbloxUSBCDMAModem::UbloxUSBCDMAModem(PinName powerGatingPin /*= NC*/, bool powerGatingOnWhenPinHigh /* = true*/, int serial /* 0 */) : m_dongle(),
+m_stream(m_dongle.getSerial(serial)),
+m_at(&m_stream),
+m_sms(&m_at), m_ppp(&m_stream),
+m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false),
+m_powerGatingPin(powerGatingPin), m_powerGatingOnWhenPinHigh(powerGatingOnWhenPinHigh)
+{
+ USBHost* host = USBHost::getHostInst();
+ m_dongle.addInitializer(new UbloxCDMAModemInitializer(host));
+ if( m_powerGatingPin != NC )
+ {
+ power(false); //Dongle will have to be powered on manually
+ }
+}
+
+class CSSProcessor : public IATCommandsProcessor
+{
+public:
+ CSSProcessor() : status(STATUS_REGISTERING)
+ {
+
+ }
+ enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK };
+ REGISTERING_STATUS getStatus()
+ {
+ return status;
+ }
+private:
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+ {
+ char b;
+ char bc[3] = "";
+ int sid = 99999;
+
+ //if( sscanf(line, "%*d, %c", &r) == 1 )
+ if(sscanf(line, "%*s %c,%2s,%d", &b,bc,&sid)==3)
+ {
+ if(strcmp("Z", bc) == 0)
+ status = STATUS_REGISTERING;
+ else
+ status = STATUS_OK;
+ }
+ return OK;
+ }
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+ {
+ return OK;
+ }
+ volatile REGISTERING_STATUS status;
+};
+
+int UbloxUSBCDMAModem::connect(const char* apn, const char* user, const char* password)
+{
+ if( !m_ipInit )
+ {
+ m_ipInit = true;
+ m_ppp.init();
+ }
+ m_ppp.setup(user, password, DEFAULT_MSISDN_CDMA);
+
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ #if USE_ONE_PORT
+ m_smsInit = false; //SMS status reset
+ //m_ussdInit = false; //USSD status reset
+ //m_linkMonitorInit = false; //Link monitor status reset
+ #endif
+
+ ATCommandsInterface::ATResult result;
+
+ if(apn != NULL)
+ {
+ char cmd[48];
+ sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
+ ret = m_at.executeSimple(cmd, &result);
+ DBG("Result of command: Err code=%d", ret);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+ DBG("APN set to %s", apn);
+ }
+
+
+ //Connect
+ DBG("Connecting");
+ #if USE_ONE_PORT
+ m_at.close(); // Closing AT parser
+ m_atOpen = false; //Will need to be reinitialized afterwards
+ #endif
+
+ DBG("Connecting PPP");
+
+ ret = m_ppp.connect();
+ DBG("Result of connect: Err code=%d", ret);
+ return ret;
+}
+
+
+int UbloxUSBCDMAModem::disconnect()
+{
+ DBG("Disconnecting from PPP");
+ int ret = m_ppp.disconnect();
+ if(ret)
+ {
+ ERR("Disconnect returned %d, still trying to disconnect", ret);
+ }
+
+ //Ugly but leave dongle time to recover
+ Thread::wait(500);
+
+ #if USE_ONE_PORT
+ ATCommandsInterface::ATResult result;
+ DBG("Starting AT thread");
+ ret = m_at.open();
+ if(ret)
+ {
+ return ret;
+ }
+ #endif
+
+ DBG("Trying to hangup");
+
+ #if 0 //Does not appear to work
+ int tries = 10;
+ do
+ {
+ ret = m_at.executeSimple("+++", &result, 1000);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ } while(tries-- && ret);
+ if(!ret)
+ {
+ ret = m_at.executeSimple("ATH", &result);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ }
+ #endif
+
+ #if USE_ONE_PORT
+ //Reinit AT parser
+ ret = m_at.init();
+ DBG("Result of command: Err code=%d\n", ret);
+ if(ret)
+ {
+ m_at.close(); // Closing AT parser
+ DBG("AT Parser closed, could not complete disconnection");
+ return NET_TIMEOUT;
+ }
+
+ #if 0
+ m_at.close(); // Closing AT parser
+ DBG("AT Parser closed");
+ #endif
+ #endif
+ return OK;
+}
+
+int UbloxUSBCDMAModem::sendSM(const char* number, const char* message)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_smsInit)
+ {
+ ret = m_sms.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = m_sms.send(number, message);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxUSBCDMAModem::getSM(char* number, char* message, size_t maxLength)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_smsInit)
+ {
+ ret = m_sms.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = m_sms.get(number, message, maxLength);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxUSBCDMAModem::getSMCount(size_t* pCount)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_smsInit)
+ {
+ ret = m_sms.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = m_sms.getCount(pCount);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+ATCommandsInterface* UbloxUSBCDMAModem::getATCommandsInterface()
+{
+ return &m_at;
+}
+
+int UbloxUSBCDMAModem::power(bool enable)
+{
+ if( m_powerGatingPin == NC )
+ {
+ return NET_INVALID; //A pin name has not been provided in the constructor
+ }
+
+ if(!enable) //Will force components to re-init
+ {
+ cleanup();
+ }
+
+ DigitalOut powerGatingOut(m_powerGatingPin);
+ powerGatingOut = m_powerGatingOnWhenPinHigh?enable:!enable;
+
+ return OK;
+}
+
+bool UbloxUSBCDMAModem::power()
+{
+ if( m_powerGatingPin == NC )
+ {
+ return true; //Assume power is always on
+ }
+
+ DigitalOut powerGatingOut(m_powerGatingPin);
+ return m_powerGatingOnWhenPinHigh?powerGatingOut:!powerGatingOut;
+}
+
+int UbloxUSBCDMAModem::init()
+{
+ if( !m_dongleConnected )
+ {
+ if(!power())
+ {
+ //Obviously cannot initialize the dongle if it is disconnected...
+ ERR("Power is off");
+ return NET_INVALID;
+ }
+ m_dongleConnected = true;
+ while( !m_dongle.connected() )
+ {
+ m_dongle.tryConnect();
+ Thread::wait(100);
+ }
+ }
+
+ if(m_atOpen)
+ {
+ return OK;
+ }
+
+ DBG("Starting AT thread if needed");
+ int ret = m_at.open();
+ if(ret)
+ {
+ return ret;
+ }
+
+ DBG("Sending initialisation commands");
+ ret = m_at.init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAC200)
+ {
+ INFO("Using a UBLOX C200 Dongle");
+ }
+ else
+ {
+ WARN("Using an Unknown Dongle");
+ }
+
+ ATCommandsInterface::ATResult result;
+
+ //Wait for network registration
+ CSSProcessor cssProcessor;
+ do
+ {
+ DBG("Waiting for network registration");
+ ret = m_at.execute("AT+CSS?", &cssProcessor, &result);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ if(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING)
+ {
+ Thread::wait(3000);
+ }
+ } while(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING);
+
+ m_atOpen = true;
+
+ return OK;
+}
+
+int UbloxUSBCDMAModem::cleanup()
+{
+ if(m_ppp.isConnected())
+ {
+ WARN("Data connection is still open"); //Try to encourage good behaviour from the user
+ m_ppp.disconnect();
+ }
+
+ m_smsInit = false;
+// m_linkMonitorInit = false;
+ //We don't reset m_ipInit as PPPIPInterface::init() only needs to be called once
+
+ if(m_atOpen)
+ {
+ m_at.close();
+ m_atOpen = false;
+ }
+
+ m_dongle.disconnect();
+ m_dongleConnected = false;
+
+ return OK;
+}
+
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBCDMAModem.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBCDMAModem.h
new file mode 100644
index 0000000000..988afb29ad
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBCDMAModem.h
@@ -0,0 +1,118 @@
+/* UbloxUSBCDMAModem.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef UBLOXUSBCDMAMODEM_H_
+#define UBLOXUSBCDMAMODEM_H_
+
+#include "core/fwk.h"
+
+#include "WANDongle.h"
+#include "at/ATCommandsInterface.h"
+#include "USBSerialStream.h"
+#include "ip/PPPIPInterface.h"
+#include "sms/CDMASMSInterface.h"
+#include "CellularModem.h"
+
+/** u-blox LISA-C200 modem
+ */
+class UbloxUSBCDMAModem: public CellularModem
+{
+public:
+ /** Create Sprint USB Modem (Sierra Wireless 598U) API instance
+ @param powerGatingPin Optional pin commanding a power gating transistor on the modem's power line
+ @param powerGatingOnWhenPinHigh true if the pin needs to be high to power the dongle, defaults to true
+ */
+ UbloxUSBCDMAModem(PinName powerGatingPin = NC, bool powerGatingOnWhenPinHigh = true, int serial = 0);
+
+ //Internet-related functions
+
+ /** Open a 3G internet connection
+ @return 0 on success, error code on failure
+ */
+ virtual int connect(const char* apn = NULL, const char* user = NULL, const char* password = NULL);
+
+ /** Close the internet connection
+ @return 0 on success, error code on failure
+ */
+ virtual int disconnect();
+
+
+ /** Send a SM
+ @param number The receiver's phone number
+ @param message The message to send
+ @return 0 on success, error code on failure
+ */
+ virtual int sendSM(const char* number, const char* message);
+
+
+ /** Receive a SM
+ @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the sapce for the null-terminating char)
+ @param message Pointer to a buffer to store the the incoming message
+ @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ virtual int getSM(char* number, char* message, size_t maxLength);
+
+ /** Get the number of SMs in the incoming box
+ @param pCount pointer to store the number of unprocessed SMs on
+ @return 0 on success, error code on failure
+ */
+ virtual int getSMCount(size_t* pCount);
+
+ /** Get the ATCommandsInterface instance
+ @return Pointer to the ATCommandsInterface instance
+ */
+ virtual ATCommandsInterface* getATCommandsInterface();
+
+ /** Switch power on or off
+ In order to use this function, a pin name must have been entered in the constructor
+ @param enable true to switch the dongle on, false to switch it off
+ @return 0 on success, error code on failure
+ */
+ virtual int power(bool enable);
+
+protected:
+ bool power();
+
+ int init();
+ int cleanup();
+
+private:
+ WANDongle m_dongle;
+
+ USBSerialStream m_stream;
+
+ ATCommandsInterface m_at;
+
+ CDMASMSInterface m_sms;
+
+ PPPIPInterface m_ppp;
+
+ bool m_dongleConnected;
+ bool m_ipInit;
+ bool m_smsInit;
+ bool m_atOpen;
+
+ PinName m_powerGatingPin;
+ bool m_powerGatingOnWhenPinHigh;
+};
+
+
+#endif /* UBLOXUSBCDMAMODEM_H_ */
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBGSMModem.cpp b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBGSMModem.cpp
new file mode 100644
index 0000000000..8209dc6a88
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBGSMModem.cpp
@@ -0,0 +1,605 @@
+/* UbloxUSBGSMModem.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define __DEBUG__ 3
+#ifndef __MODULE__
+#define __MODULE__ "UbloxUSBGSMModem.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "UbloxUSBGSMModem.h"
+#include "UbloxGSMModemInitializer.h"
+#include "USBHost.h"
+
+UbloxUSBGSMModem::UbloxUSBGSMModem(PinName powerGatingPin /*= NC*/, bool powerGatingOnWhenPinHigh /* = true*/) :
+ m_dongle(), // Construct WANDongle: USB interface with two serial channels to the modem (USBSerialStream objects)
+ m_atStream(m_dongle.getSerial(1)), // AT commands are sent down one serial channel.
+ m_pppStream(m_dongle.getSerial(0)), // PPP connections are managed via another serial channel.
+ m_at(&m_atStream), // Construct ATCommandsInterface with the AT serial channel
+ m_sms(&m_at), // Construct SMSInterface with the ATCommandsInterface
+ m_ussd(&m_at), // Construct USSDInterface with the ATCommandsInterface
+ m_linkMonitor(&m_at), // Construct LinkMonitor with the ATCommandsInterface
+ m_ppp(&m_pppStream), // Construct PPPIPInterface with the PPP serial channel
+ m_dongleConnected(false), // Dongle is initially not ready for anything
+ m_ipInit(false), // PPIPInterface connection is initially down
+ m_smsInit(false), // SMSInterface starts un-initialised
+ m_ussdInit(false), // USSDInterface starts un-initialised
+ m_linkMonitorInit(false), // LinkMonitor subsystem starts un-initialised
+ m_atOpen(false), // ATCommandsInterface starts in a closed state
+ m_powerGatingPin(powerGatingPin), // set power gating pin
+ m_powerGatingOnWhenPinHigh(powerGatingOnWhenPinHigh) // set state semantics for power gating pin
+{
+ USBHost* host = USBHost::getHostInst();
+ m_dongle.addInitializer(new UbloxGSMModemInitializer(host));
+ if( m_powerGatingPin != NC )
+ {
+ power(false); //Dongle will have to be powered on manually
+ }
+}
+
+class CREGProcessor : public IATCommandsProcessor
+{
+public:
+ CREGProcessor() : status(STATUS_REGISTERING)
+ {
+
+ }
+ enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK, STATUS_FAILED };
+ REGISTERING_STATUS getStatus()
+ {
+ return status;
+ }
+private:
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+ {
+ int r;
+ if( sscanf(line, "+CREG: %*d,%d", &r) == 1 )
+ {
+ switch(r)
+ {
+ case 1:
+ case 5:
+ status = STATUS_OK;
+ break;
+ case 0:
+ case 2:
+ status = STATUS_REGISTERING;
+ break;
+ case 3:
+ default:
+ status = STATUS_FAILED;
+ break;
+ }
+ }
+ return OK;
+ }
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+ {
+ return OK;
+ }
+ volatile REGISTERING_STATUS status;
+};
+
+#if 0
+class COPSProcessor : public IATCommandsProcessor
+{
+public:
+ COPSProcessor() : valid(false)
+ {
+ network[0] = '\0';
+ apn[0] = '\0';
+ bearer[0] = '\0';
+ }
+ char* getNetwork()
+ {
+ return network;
+ }
+ char* getAPN()
+ {
+ return apn;
+ }
+ char* getBearer()
+ {
+ return bearer;
+ }
+ bool isValid()
+ {
+ return valid;
+ }
+private:
+ virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+ {
+ int networkId;
+ int bearerId;
+ int s = sscanf(line, "+COPS: %*d,%*d,\"%d\",%d", &networkId, &bearerId);
+ if( s == 2 )
+ {
+ switch(networkId)
+ {
+ case 23415:
+ strcpy(network, "Vodafone UK");
+ strcpy(apn, "pp.vodafone.co.uk");
+ valid = true;
+ break;
+ case 20810:
+ strcpy(network, "SFR FR");
+ strcpy(apn, "websfr");
+ valid = true;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ return OK;
+ }
+ switch(bearerId)
+ {
+ case 0: strcpy(bearer, "GSM"); break;
+ case 1: strcpy(bearer, "GSM Compact"); break;
+ case 2: strcpy(bearer, "UTRAN"); break;
+ case 3: strcpy(bearer, "GSM w/EGPRS"); break;
+ case 4: strcpy(bearer, "UTRAN w/HSDPA"); break;
+ case 5: strcpy(bearer, "UTRAN w/HSUPA"); break;
+ case 6: strcpy(bearer, "UTRAN w/HSDPA and HSUPA"); break;
+ case 7: strcpy(bearer, "E-UTRAN"); break;
+
+ default:
+ break;
+ }
+ return OK;
+ }
+ virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
+ {
+ return OK;
+ }
+ char network[24];
+ char bearer[24];
+ char apn[24];
+ volatile bool valid;
+};
+#endif
+
+int UbloxUSBGSMModem::connect(const char* apn, const char* user, const char* password)
+{
+ if( !m_ipInit )
+ {
+ m_ipInit = true;
+ m_ppp.init();
+ }
+ m_ppp.setup(user, password, DEFAULT_MSISDN_GSM);
+
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ #if USE_ONE_PORT
+ m_smsInit = false; //SMS status reset
+ m_ussdInit = false; //USSD status reset
+ m_linkMonitorInit = false; //Link monitor status reset
+ #endif
+
+ ATCommandsInterface::ATResult result;
+
+ #if 0
+ //Get network info & select corresponding APN
+ COPSProcessor copsProcessor;
+ DBG("Get network info & select APN from DB");
+ ret = m_at.execute("AT+COPS=,2;+COPS?", &copsProcessor, &result); //Configure to get operator's info in numeric code & get operator's id
+ DBG("Result of command: Err code=%d", ret);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+
+ if(!copsProcessor.isValid())
+ {
+ WARN("Connected to an unknown network, try to connect with default parameters");
+ DBG("Connected with %s", copsProcessor.getBearer());
+ }
+ else
+ {
+ DBG("Connected to %s with %s", copsProcessor.getNetwork(), copsProcessor.getBearer());
+ char cmd[48];
+ int tries = 3;
+ sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", copsProcessor.getAPN());
+ do //Try 3 times because for some reasons it can fail with the K3772-Z dongle
+ {
+ ret = m_at.executeSimple(cmd, &result);
+ DBG("Result of command: Err code=%d", ret);
+ } while(ret && --tries);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+ DBG("APN set to %s", copsProcessor.getAPN());
+ }
+ #else
+ if(apn != NULL)
+ {
+ char cmd[48];
+ int tries = 30;
+ sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
+ do //Try 30 times because for some reasons it can fail *a lot* with the K3772-Z dongle
+ {
+ ret = m_at.executeSimple(cmd, &result);
+ DBG("Result of command: Err code=%d", ret);
+ if(ret)
+ {
+ Thread::wait(500);
+ }
+ } while(ret && --tries);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+ DBG("APN set to %s", apn);
+ }
+ #endif
+
+
+ //Connect
+ DBG("Connecting");
+ #if 0
+ ret = m_at.executeSimple("ATDT *99#", &result);
+ DBG("Result of command: Err code=%d", ret);
+ DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+ #endif
+ #if USE_ONE_PORT
+ m_at.close(); // Closing AT parser
+ m_atOpen = false; //Will need to be reinitialized afterwards
+ #endif
+
+ #if 0
+ DBG("AT Parser closed");
+ if( (ret!=NET_MOREINFO) || (result.result != ATCommandsInterface::ATResult::AT_CONNECT))
+ {
+ ERR("Could not connect");
+ return ret; //Could not connect
+ }
+ #endif
+ DBG("Connecting PPP");
+
+ ret = m_ppp.connect();
+ DBG("Result of connect: Err code=%d", ret);
+ return ret;
+}
+
+
+int UbloxUSBGSMModem::disconnect()
+{
+ DBG("Disconnecting from PPP");
+ int ret = m_ppp.disconnect();
+ if(ret)
+ {
+ ERR("Disconnect returned %d, still trying to disconnect", ret);
+ }
+
+ //Ugly but leave dongle time to recover
+ Thread::wait(500);
+
+ #if USE_ONE_PORT
+ ATCommandsInterface::ATResult result;
+ DBG("Starting AT thread");
+ ret = m_at.open();
+ if(ret)
+ {
+ return ret;
+ }
+ #endif
+
+ DBG("Trying to hangup");
+
+ #if 0 //Does not appear to work
+ int tries = 10;
+ do
+ {
+ ret = m_at.executeSimple("+++", &result, 1000);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ } while(tries-- && ret);
+ if(!ret)
+ {
+ ret = m_at.executeSimple("ATH", &result);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ }
+ #endif
+
+ #if USE_ONE_PORT
+ //Reinit AT parser
+ ret = m_at.init();
+ DBG("Result of command: Err code=%d\n", ret);
+ if(ret)
+ {
+ m_at.close(); // Closing AT parser
+ DBG("AT Parser closed, could not complete disconnection");
+ return NET_TIMEOUT;
+ }
+
+ #if 0
+ m_at.close(); // Closing AT parser
+ DBG("AT Parser closed");
+ #endif
+ #endif
+ return OK;
+}
+
+int UbloxUSBGSMModem::sendSM(const char* number, const char* message)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_smsInit)
+ {
+ ret = m_sms.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = m_sms.send(number, message);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxUSBGSMModem::getSM(char* number, char* message, size_t maxLength)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_smsInit)
+ {
+ ret = m_sms.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = m_sms.get(number, message, maxLength);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxUSBGSMModem::getSMCount(size_t* pCount)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_smsInit)
+ {
+ ret = m_sms.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_smsInit = true;
+ }
+
+ ret = m_sms.getCount(pCount);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxUSBGSMModem::sendUSSD(const char* command, char* result, size_t maxLength)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_ussdInit)
+ {
+ ret = m_ussd.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_ussdInit = true;
+ }
+
+ ret = m_ussd.send(command, result, maxLength);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+int UbloxUSBGSMModem::getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegistrationState, LinkMonitor::BEARER* pBearer)
+{
+ int ret = init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(!m_linkMonitorInit)
+ {
+ ret = m_linkMonitor.init();
+ if(ret)
+ {
+ return ret;
+ }
+ m_linkMonitorInit = true;
+ }
+
+ ret = m_linkMonitor.getState(pRssi, pRegistrationState, pBearer);
+ if(ret)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+
+ATCommandsInterface* UbloxUSBGSMModem::getATCommandsInterface()
+{
+ return &m_at;
+}
+
+int UbloxUSBGSMModem::power(bool enable)
+{
+ if( m_powerGatingPin == NC )
+ {
+ return NET_INVALID; //A pin name has not been provided in the constructor
+ }
+
+ if(!enable) //Will force components to re-init
+ {
+ cleanup();
+ }
+
+ DigitalOut powerGatingOut(m_powerGatingPin);
+ powerGatingOut = m_powerGatingOnWhenPinHigh?enable:!enable;
+
+ return OK;
+}
+
+bool UbloxUSBGSMModem::power()
+{
+ if( m_powerGatingPin == NC )
+ {
+ return true; //Assume power is always on
+ }
+
+ DigitalOut powerGatingOut(m_powerGatingPin);
+ return m_powerGatingOnWhenPinHigh?powerGatingOut:!powerGatingOut;
+}
+
+int UbloxUSBGSMModem::init()
+{
+ if( !m_dongleConnected )
+ {
+ if(!power())
+ {
+ //Obviously cannot initialize the dongle if it is disconnected...
+ ERR("Power is off");
+ return NET_INVALID;
+ }
+ m_dongleConnected = true;
+ while( !m_dongle.connected() )
+ {
+ m_dongle.tryConnect();
+ Thread::wait(10);
+ }
+ }
+
+ if(m_atOpen)
+ {
+ return OK;
+ }
+
+ DBG("Starting AT thread if needed");
+ int ret = m_at.open();
+ if(ret)
+ {
+ return ret;
+ }
+
+ DBG("Sending initialisation commands");
+ ret = m_at.init();
+ if(ret)
+ {
+ return ret;
+ }
+
+ if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAU200)
+ {
+ INFO("Using a u-blox LISA-U");
+ }
+ else
+ {
+ WARN("Using an Unknown Dongle");
+ }
+
+ ATCommandsInterface::ATResult result;
+
+ //Wait for network registration
+ CREGProcessor cregProcessor;
+ do
+ {
+ DBG("Waiting for network registration");
+ ret = m_at.execute("AT+CREG?", &cregProcessor, &result);
+ DBG("Result of command: Err code=%d\n", ret);
+ DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+ if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING)
+ {
+ Thread::wait(3000);
+ }
+ } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING);
+ if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED)
+ {
+ ERR("Registration denied");
+ return NET_AUTH;
+ }
+
+ m_atOpen = true;
+
+ return OK;
+}
+
+int UbloxUSBGSMModem::cleanup()
+{
+ if(m_ppp.isConnected())
+ {
+ WARN("Data connection is still open"); //Try to encourage good behaviour from the user
+ m_ppp.disconnect();
+ }
+
+ m_smsInit = false;
+ m_ussdInit = false;
+ m_linkMonitorInit = false;
+ //We don't reset m_ipInit as PPPIPInterface::init() only needs to be called once
+
+ if(m_atOpen)
+ {
+ m_at.close();
+ m_atOpen = false;
+ }
+
+ m_dongle.disconnect();
+ m_dongleConnected = false;
+
+ return OK;
+}
+
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBGSMModem.h b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBGSMModem.h
new file mode 100644
index 0000000000..2cc432a2c2
--- /dev/null
+++ b/tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBGSMModem.h
@@ -0,0 +1,155 @@
+/* VodafoneUSBModem.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef UBLOXUSBGSMMODEM_H_
+#define UBLOXUSBGSMMODEM_H_
+
+#include "core/fwk.h"
+
+#include "WANDongle.h"
+#include "at/ATCommandsInterface.h"
+#include "serial/usb/USBSerialStream.h"
+#include "ip/PPPIPInterface.h"
+#include "sms/GSMSMSInterface.h"
+#include "ussd/USSDInterface.h"
+#include "link/LinkMonitor.h"
+#include "CellularModem.h"
+
+/** u-blox WCDMA modem (LISA-U200)
+ */
+class UbloxUSBGSMModem: public CellularModem
+{
+public:
+ /** Create u-blox API instance
+ @param powerGatingPin Optional pin commanding a power gating transistor on the modem's power line
+ @param powerGatingOnWhenPinHigh true if the pin needs to be high to power the dongle, defaults to true
+ */
+ UbloxUSBGSMModem(PinName powerGatingPin = NC, bool powerGatingOnWhenPinHigh = true);
+
+ //Internet-related functions
+
+ /** Open a 3G internet connection
+ @return 0 on success, error code on failure
+ */
+ virtual int connect(const char* apn = NULL, const char* user = NULL, const char* password = NULL);
+
+ /** Close the internet connection
+ @return 0 on success, error code on failure
+ */
+ virtual int disconnect();
+
+
+ /** Send a SM
+ @param number The receiver's phone number
+ @param message The message to send
+ @return 0 on success, error code on failure
+ */
+ virtual int sendSM(const char* number, const char* message);
+
+
+ /** Receive a SM
+ @param number Pointer to a buffer to store the sender's phone number (must be at least 17 characters-long, including the sapce for the null-terminating char)
+ @param message Pointer to a buffer to store the the incoming message
+ @param maxLength Maximum message length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ virtual int getSM(char* number, char* message, size_t maxLength);
+
+ /** Get the number of SMs in the incoming box
+ @param pCount pointer to store the number of unprocessed SMs on
+ @return 0 on success, error code on failure
+ */
+ virtual int getSMCount(size_t* pCount);
+
+ /** Send a USSD command & wait for its result
+ @param command The command to send
+ @param result Buffer in which to store the result
+ @param maxLength Maximum result length that can be stored in buffer (including null-terminating character)
+ @return 0 on success, error code on failure
+ */
+ int sendUSSD(const char* command, char* result, size_t maxLength);
+
+ /** Get link state
+ @param pRssi pointer to store the current RSSI in dBm, between -51 dBm and -113 dBm if known; -51 dBm means -51 dBm or more; -113 dBm means -113 dBm or less; 0 if unknown
+ @param pRegistrationState pointer to store the current registration state
+ @param pBearer pointer to store the current bearer
+ @return 0 on success, error code on failure
+ */
+ int getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegistrationState, LinkMonitor::BEARER* pBearer);
+
+ /** Get the ATCommandsInterface instance
+ @return Pointer to the ATCommandsInterface instance
+ */
+ virtual ATCommandsInterface* getATCommandsInterface();
+
+ /** Switch power on or off
+ In order to use this function, a pin name must have been entered in the constructor
+ @param enable true to switch the dongle on, false to switch it off
+ @return 0 on success, error code on failure
+ */
+ virtual int power(bool enable);
+
+protected:
+ bool power(); //< Turn power to USB dongle ON.
+
+ /** Initialise dongle.
+ * The following actions are performed:
+ * 1) Power up
+ * 2) Establish USB connection to dongle
+ * 3) Start AT interface thread
+ * 4) Wait for network registration
+ */
+ int init();
+
+ /** De-initialise dongle.
+ * The following actions are performed:
+ * 1) Tear down PPP session
+ * 2) Set SMS,USSD, and LinkMonitor subsystems to un-initialised
+ * 3) Close the AT commands interface
+ * 4) Tear down the USB connection to dongle
+ */
+ int cleanup();
+
+private:
+ WANDongle m_dongle; //< Interface to USB connected WAN dongle
+
+ USBSerialStream m_atStream; //< Serial interface to AT channel on modem
+ USBSerialStream m_pppStream; //< Serial interface to PPP channel on modem
+
+ ATCommandsInterface m_at; //< Interface to AT commands processing
+
+ GSMSMSInterface m_sms; //< Interface to SMS manager (send/receive etc)
+ USSDInterface m_ussd; //< Interface to USSD manager (send etc)
+ LinkMonitor m_linkMonitor; //< Interface to link monitor (RSSI)
+
+ PPPIPInterface m_ppp; //< Interface to PPP conection manager (IP assignment etc)
+
+ bool m_dongleConnected; //< Is the dongle physically connected (does the USB stack respond)? true/false
+ bool m_ipInit; //< Has PPIPInterface object (m_ppp) been initialised? true/false
+ bool m_smsInit; //< Has SMSInterface object (m_sms) been initialised? true/false
+ bool m_ussdInit; //< Has USSDInterface object (m_ussd) been initialised? true/false
+ bool m_linkMonitorInit; //< Has LinkMonitor object (m_linkMonitor) been initialised? true/false
+ bool m_atOpen; //< Is the interface to the ATCommandsInterface open? true/false
+
+ PinName m_powerGatingPin; //< Pin which toggles power gating
+ bool m_powerGatingOnWhenPinHigh; //< Semantics of power gating (whether high or low toggles power gating)
+};
+
+
+#endif /* UBLOXMODEM_H_ */