diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c index d6c60a852b..ef7e0096ac 100644 --- a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/serial_api.c @@ -76,7 +76,7 @@ serial_t stdio_uart; struct serial_global_data_s { uint32_t serial_irq_id; gpio_t sw_rts, sw_cts; - uint8_t rx_irq_set_flow, rx_irq_set_api; + uint8_t count, rx_irq_set_flow, rx_irq_set_api; }; static struct serial_global_data_s uart_data[UART_NUM]; @@ -357,6 +357,7 @@ int serial_getc(serial_t *obj) { void serial_putc(serial_t *obj, int c) { while (!serial_writable(obj)); obj->uart->THR = c; + uart_data[obj->index].count++; } int serial_readable(serial_t *obj) { @@ -364,10 +365,16 @@ int serial_readable(serial_t *obj) { } int serial_writable(serial_t *obj) { + int isWritable = 1; if (NC != uart_data[obj->index].sw_cts.pin) - return (gpio_read(&uart_data[obj->index].sw_cts) == 0) && (obj->uart->LSR & 0x40); //If flow control: writable if CTS low + UART done - else - return obj->uart->LSR & 0x20; //No flow control: writable if space in holding register + isWritable = (gpio_read(&uart_data[obj->index].sw_cts) == 0) && (obj->uart->LSR & 0x40); + else { + if (obj->uart->LSR & 0x20) + uart_data[obj->index].count = 0; + else if (uart_data[obj->index].count >= 16) + isWritable = 0; + } + return isWritable; } void serial_clear(serial_t *obj) { diff --git a/libraries/net/cellular/CellularModem/at/ATCommandsInterface.cpp b/libraries/net/cellular/CellularModem/at/ATCommandsInterface.cpp index 90be0c2e65..9f711630ce 100644 --- a/libraries/net/cellular/CellularModem/at/ATCommandsInterface.cpp +++ b/libraries/net/cellular/CellularModem/at/ATCommandsInterface.cpp @@ -32,7 +32,7 @@ using std::memmove; #include "ATCommandsInterface.h" ATCommandsInterface::ATCommandsInterface(IOStream* pStream) : - m_pStream(pStream), m_open(false), m_env2AT(), m_AT2Env(), m_processingMtx(), + 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() { @@ -270,6 +270,7 @@ int ATCommandsInterface::executeInternal(const char* command, IATCommandsProcess } 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); @@ -285,6 +286,7 @@ int ATCommandsInterface::executeInternal(const char* command, IATCommandsProcess 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"); @@ -751,12 +753,13 @@ void ATCommandsInterface::enableEvents() { m_eventsHandlers[i]->onDispatchStart(); //Enable this kind of events - if(m_eventsHandlers[i]->getEventsEnableCommand() != NULL) + const char* cmd = m_eventsHandlers[i]->getEventsEnableCommand(); + if(cmd != NULL) { - int ret = executeInternal(m_eventsHandlers[i]->getEventsEnableCommand(), this, NULL); //Execute enable command + int ret = executeInternal(cmd, this, NULL); //Execute enable command if(ret) { - WARN("Events enabling command failed"); + WARN("Events enabling command \"%s\" failed", cmd); } } } @@ -775,12 +778,13 @@ void ATCommandsInterface::disableEvents() { m_eventsHandlers[i]->onDispatchStart(); //Disable this kind of events - if(m_eventsHandlers[i]->getEventsDisableCommand() != NULL) + const char* cmd = m_eventsHandlers[i]->getEventsDisableCommand(); + if(cmd != NULL) { - int ret = executeInternal(m_eventsHandlers[i]->getEventsDisableCommand(), this, NULL); //Execute disable command + int ret = executeInternal(cmd, this, NULL); //Execute disable command if(ret) { - WARN("Events disabling command failed"); + WARN("Events disabling command \"%s\" failed", cmd); } } } diff --git a/libraries/net/cellular/CellularModem/link/LinkMonitor.cpp b/libraries/net/cellular/CellularModem/link/LinkMonitor.cpp index 3646b1f7aa..612b376921 100644 --- a/libraries/net/cellular/CellularModem/link/LinkMonitor.cpp +++ b/libraries/net/cellular/CellularModem/link/LinkMonitor.cpp @@ -58,6 +58,8 @@ int LinkMonitor::init(bool gsm) /*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 { @@ -127,6 +129,13 @@ int LinkMonitor::init(bool gsm) 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; } @@ -150,3 +159,17 @@ int LinkMonitor::getState(int* pRssi, REGISTRATION_STATE* pRegistrationState, BE *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/libraries/net/cellular/CellularModem/link/LinkMonitor.h b/libraries/net/cellular/CellularModem/link/LinkMonitor.h index 527e3581d3..864909d6c5 100644 --- a/libraries/net/cellular/CellularModem/link/LinkMonitor.h +++ b/libraries/net/cellular/CellularModem/link/LinkMonitor.h @@ -73,6 +73,11 @@ public: */ 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); @@ -85,7 +90,7 @@ private: bool m_gsm; REGISTRATION_STATE m_registrationState; BEARER m_bearer; - + char m_phoneNumber[16]; }; #endif /* LINKMONITOR_H_ */ diff --git a/libraries/net/cellular/UbloxUSBModem/UbloxModem.cpp b/libraries/net/cellular/UbloxUSBModem/UbloxModem.cpp index 4b3939ecfa..a9fec4cbf0 100644 --- a/libraries/net/cellular/UbloxUSBModem/UbloxModem.cpp +++ b/libraries/net/cellular/UbloxUSBModem/UbloxModem.cpp @@ -41,23 +41,24 @@ UbloxModem::UbloxModem(IOStream* atStream, IOStream* pppStream) : m_linkMonitorInit(false), // LinkMonitor subsystem starts un-initialised m_atOpen(false), // ATCommandsInterface starts in a closed state m_onePort(pppStream == NULL), - m_gsm(true) + m_type(UNKNOWN) { } -class AtiProcessor : public IATCommandsProcessor -{ -public: - AtiProcessor() - { +genericAtProcessor::genericAtProcessor() +{ i = 0; str[0] = '\0'; - } - const char* getInfo(void) { return str; } -private: - virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) - { +} + +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; @@ -65,15 +66,12 @@ private: strcat(&str[i], line); i += l; return OK; - } - virtual int onNewEntryPrompt(ATCommandsInterface* pInst) - { +} + +int genericAtProcessor::onNewEntryPrompt(ATCommandsInterface* pInst) +{ return OK; - } -protected: - char str[256]; - int i; -}; +} class CREGProcessor : public IATCommandsProcessor { @@ -130,7 +128,7 @@ int UbloxModem::connect(const char* apn, const char* user, const char* password) m_ipInit = true; m_ppp.init(); } - m_ppp.setup(user, password, m_gsm ? DEFAULT_MSISDN_GSM : DEFAULT_MSISDN_CDMA); + m_ppp.setup(user, password, (m_type != LISA_C200) ? DEFAULT_MSISDN_GSM : DEFAULT_MSISDN_CDMA); int ret = init(); if(ret) @@ -231,8 +229,8 @@ int UbloxModem::sendSM(const char* number, const char* message) } ISMSInterface* sms; - if (m_gsm) sms = &m_GsmSms; - else sms = &m_CdmaSms; + if (m_type == LISA_C200) sms = &m_CdmaSms; + else sms = &m_GsmSms; if(!m_smsInit) { ret = sms->init(); @@ -261,8 +259,8 @@ int UbloxModem::getSM(char* number, char* message, size_t maxLength) } ISMSInterface* sms; - if (m_gsm) sms = &m_GsmSms; - else sms = &m_CdmaSms; + if (m_type == LISA_C200) sms = &m_CdmaSms; + else sms = &m_GsmSms; if(!m_smsInit) { ret = sms->init(); @@ -291,8 +289,8 @@ int UbloxModem::getSMCount(size_t* pCount) } ISMSInterface* sms; - if (m_gsm) sms = &m_GsmSms; - else sms = &m_CdmaSms; + if (m_type == LISA_C200) sms = &m_CdmaSms; + else sms = &m_GsmSms; if(!m_smsInit) { ret = sms->init(); @@ -337,25 +335,40 @@ int UbloxModem::init() { return ret; } - + + ATCommandsInterface::ATResult result; - AtiProcessor atiProcessor; - do - { - ret = m_at.execute("ATI", &atiProcessor, &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 } - while (ret != OK); - { - const char* info = atiProcessor.getInfo(); - DBG("Modem Identification [%s]", info); - if (strstr(info, "LISA-C200")) - { - m_gsm = false; // it is CDMA modem - 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; } - CREGProcessor cregProcessor(m_gsm); + // 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 { @@ -438,8 +451,7 @@ int UbloxModem::getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegis if(!m_linkMonitorInit) { - ret = m_linkMonitor.init(); - ret = m_linkMonitor.init(m_gsm); + ret = m_linkMonitor.init(m_type != LISA_C200); if(ret) { return ret; @@ -456,6 +468,33 @@ int UbloxModem::getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegis 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" @@ -485,11 +524,12 @@ int UbloxUSBModem::init() 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_gsm = false; + m_type = LISA_C200; m_onePort = true; } else @@ -510,9 +550,10 @@ int UbloxUSBModem::cleanup() UbloxSerModem::UbloxSerModem() : UbloxModem(&m_atStream, NULL), - m_Serial(P0_15,P0_16), + m_Serial(P0_15/*MDMTXD*/,P0_16/*MDMRXD*/), m_atStream(m_Serial) { - m_Serial.baud(115200); + m_Serial.baud(115200/*MDMBAUD*/); + m_Serial.set_flow_control(SerialBase::RTSCTS, P0_22/*MDMRTS*/, P0_17/*MDMCTS*/); } diff --git a/libraries/net/cellular/UbloxUSBModem/UbloxModem.h b/libraries/net/cellular/UbloxUSBModem/UbloxModem.h index 153942785c..dc0e1205a4 100644 --- a/libraries/net/cellular/UbloxUSBModem/UbloxModem.h +++ b/libraries/net/cellular/UbloxUSBModem/UbloxModem.h @@ -30,6 +30,19 @@ #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 @@ -92,6 +105,8 @@ public: */ 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 */ @@ -130,7 +145,7 @@ private: bool m_atOpen; //< Is the interface to the ATCommandsInterface open? true/false protected: bool m_onePort; - bool m_gsm; + enum { LISA_C200, LISA_U200, SARA_G350, UNKNOWN } m_type; }; #include "WANDongle.h"