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,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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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*/);
|
||||
}
|
||||
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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_ */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_ */
|
Loading…
Add table
Add a link
Reference in a new issue