Squashed 'tmk_core/' changes from 7967731..b9e0ea0
b9e0ea0 Merge commit '7fa9d8bdea3773d1195b04d98fcf27cf48ddd81d' as 'tool/mbed/mbed-sdk' 7fa9d8b Squashed 'tool/mbed/mbed-sdk/' content from commit 7c21ce5 git-subtree-dir: tmk_core git-subtree-split: b9e0ea08cb940de20b3610ecdda18e9d8cd7c552
This commit is contained in:
parent
a20ef7052c
commit
1fe4406f37
4198 changed files with 2016457 additions and 0 deletions
|
@ -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*/);
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue