Merge pull request #195 from mazgch/master

Update of cellular modem
pull/197/merge
Bogdan Marinescu 2014-03-04 09:53:03 +00:00
commit e4faeb42a7
6 changed files with 154 additions and 59 deletions

View File

@ -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) {

View File

@ -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);
}
}
}

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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*/);
}

View File

@ -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"