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 { struct serial_global_data_s {
uint32_t serial_irq_id; uint32_t serial_irq_id;
gpio_t sw_rts, sw_cts; 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]; 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) { void serial_putc(serial_t *obj, int c) {
while (!serial_writable(obj)); while (!serial_writable(obj));
obj->uart->THR = c; obj->uart->THR = c;
uart_data[obj->index].count++;
} }
int serial_readable(serial_t *obj) { int serial_readable(serial_t *obj) {
@ -364,10 +365,16 @@ int serial_readable(serial_t *obj) {
} }
int serial_writable(serial_t *obj) { int serial_writable(serial_t *obj) {
int isWritable = 1;
if (NC != uart_data[obj->index].sw_cts.pin) 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 isWritable = (gpio_read(&uart_data[obj->index].sw_cts) == 0) && (obj->uart->LSR & 0x40);
else else {
return obj->uart->LSR & 0x20; //No flow control: writable if space in holding register 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) { void serial_clear(serial_t *obj) {

View File

@ -32,7 +32,7 @@ using std::memmove;
#include "ATCommandsInterface.h" #include "ATCommandsInterface.h"
ATCommandsInterface::ATCommandsInterface(IOStream* pStream) : 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_processingThread(&ATCommandsInterface::staticCallback, this, (osPriority)AT_THREAD_PRIORITY, 4*192),
m_eventsMgmtMtx(), m_eventsProcessingMtx() m_eventsMgmtMtx(), m_eventsProcessingMtx()
{ {
@ -270,6 +270,7 @@ int ATCommandsInterface::executeInternal(const char* command, IATCommandsProcess
} while(msgResult != AT_TIMEOUT); } while(msgResult != AT_TIMEOUT);
WARN("Command returned no message"); WARN("Command returned no message");
WARN("Command \"%s\" returned no message", command);
return NET_TIMEOUT; return NET_TIMEOUT;
} }
DBG("Command returned with message %d", *msg); DBG("Command returned with message %d", *msg);
@ -285,6 +286,7 @@ int ATCommandsInterface::executeInternal(const char* command, IATCommandsProcess
if(ret != OK) if(ret != OK)
{ {
WARN("Command returned AT result %d with code %d", m_transactionResult.result, m_transactionResult.code); 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"); DBG("Command returned successfully");
@ -751,12 +753,13 @@ void ATCommandsInterface::enableEvents()
{ {
m_eventsHandlers[i]->onDispatchStart(); m_eventsHandlers[i]->onDispatchStart();
//Enable this kind of events //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) 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(); m_eventsHandlers[i]->onDispatchStart();
//Disable this kind of events //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) 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) /*virtual*/ int LinkMonitor::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
{ {
DBG("Line is %s", line); DBG("Line is %s", line);
char n[32] = "";
char s[32] = "";
int v; int v;
if( sscanf(line, "+CREG: %*d,%d", &v) >= 1 ) //Reg state is valid 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; 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; return OK;
} }
@ -150,3 +159,17 @@ int LinkMonitor::getState(int* pRssi, REGISTRATION_STATE* pRegistrationState, BE
*pBearer = m_bearer; *pBearer = m_bearer;
return OK; 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); 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: protected:
//IATCommandsProcessor //IATCommandsProcessor
virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line); virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line);
@ -85,7 +90,7 @@ private:
bool m_gsm; bool m_gsm;
REGISTRATION_STATE m_registrationState; REGISTRATION_STATE m_registrationState;
BEARER m_bearer; BEARER m_bearer;
char m_phoneNumber[16];
}; };
#endif /* LINKMONITOR_H_ */ #endif /* LINKMONITOR_H_ */

View File

@ -41,22 +41,23 @@ UbloxModem::UbloxModem(IOStream* atStream, IOStream* pppStream) :
m_linkMonitorInit(false), // LinkMonitor subsystem starts un-initialised m_linkMonitorInit(false), // LinkMonitor subsystem starts un-initialised
m_atOpen(false), // ATCommandsInterface starts in a closed state m_atOpen(false), // ATCommandsInterface starts in a closed state
m_onePort(pppStream == NULL), m_onePort(pppStream == NULL),
m_gsm(true) m_type(UNKNOWN)
{ {
} }
class AtiProcessor : public IATCommandsProcessor genericAtProcessor::genericAtProcessor()
{
public:
AtiProcessor()
{ {
i = 0; i = 0;
str[0] = '\0'; str[0] = '\0';
} }
const char* getInfo(void) { return str; }
private: const char* genericAtProcessor::getResponse(void)
virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) {
return str;
}
int genericAtProcessor::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
{ {
int l = strlen(line); int l = strlen(line);
if (i + l + 2 > sizeof(str)) if (i + l + 2 > sizeof(str))
@ -66,14 +67,11 @@ private:
i += l; i += l;
return OK; return OK;
} }
virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
int genericAtProcessor::onNewEntryPrompt(ATCommandsInterface* pInst)
{ {
return OK; return OK;
} }
protected:
char str[256];
int i;
};
class CREGProcessor : public IATCommandsProcessor class CREGProcessor : public IATCommandsProcessor
{ {
@ -130,7 +128,7 @@ int UbloxModem::connect(const char* apn, const char* user, const char* password)
m_ipInit = true; m_ipInit = true;
m_ppp.init(); 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(); int ret = init();
if(ret) if(ret)
@ -231,8 +229,8 @@ int UbloxModem::sendSM(const char* number, const char* message)
} }
ISMSInterface* sms; ISMSInterface* sms;
if (m_gsm) sms = &m_GsmSms; if (m_type == LISA_C200) sms = &m_CdmaSms;
else sms = &m_CdmaSms; else sms = &m_GsmSms;
if(!m_smsInit) if(!m_smsInit)
{ {
ret = sms->init(); ret = sms->init();
@ -261,8 +259,8 @@ int UbloxModem::getSM(char* number, char* message, size_t maxLength)
} }
ISMSInterface* sms; ISMSInterface* sms;
if (m_gsm) sms = &m_GsmSms; if (m_type == LISA_C200) sms = &m_CdmaSms;
else sms = &m_CdmaSms; else sms = &m_GsmSms;
if(!m_smsInit) if(!m_smsInit)
{ {
ret = sms->init(); ret = sms->init();
@ -291,8 +289,8 @@ int UbloxModem::getSMCount(size_t* pCount)
} }
ISMSInterface* sms; ISMSInterface* sms;
if (m_gsm) sms = &m_GsmSms; if (m_type == LISA_C200) sms = &m_CdmaSms;
else sms = &m_CdmaSms; else sms = &m_GsmSms;
if(!m_smsInit) if(!m_smsInit)
{ {
ret = sms->init(); ret = sms->init();
@ -338,24 +336,39 @@ int UbloxModem::init()
return ret; return ret;
} }
ATCommandsInterface::ATResult result; ATCommandsInterface::ATResult result;
AtiProcessor atiProcessor; genericAtProcessor atiProcessor;
do
{
ret = m_at.execute("ATI", &atiProcessor, &result); ret = m_at.execute("ATI", &atiProcessor, &result);
} if (OK != ret)
while (ret != OK); return ret;
{ const char* info = atiProcessor.getResponse();
const char* info = atiProcessor.getInfo(); INFO("Modem Identification [%s]", info);
DBG("Modem Identification [%s]", info); if (strstr(info, "LISA-C200")) {
if (strstr(info, "LISA-C200")) m_type = LISA_C200;
{
m_gsm = false; // it is CDMA modem
m_onePort = true; // force use of only one port 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 //Wait for network registration
do do
{ {
@ -438,8 +451,7 @@ int UbloxModem::getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegis
if(!m_linkMonitorInit) if(!m_linkMonitorInit)
{ {
ret = m_linkMonitor.init(); ret = m_linkMonitor.init(m_type != LISA_C200);
ret = m_linkMonitor.init(m_gsm);
if(ret) if(ret)
{ {
return ret; return ret;
@ -456,6 +468,33 @@ int UbloxModem::getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegis
return OK; 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 "USBHost.h"
#include "UbloxGSMModemInitializer.h" #include "UbloxGSMModemInitializer.h"
#include "UbloxCDMAModemInitializer.h" #include "UbloxCDMAModemInitializer.h"
@ -485,11 +524,12 @@ int UbloxUSBModem::init()
if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAU200) if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAU200)
{ {
INFO("Using a u-blox LISA-U200 3G/WCDMA Modem"); INFO("Using a u-blox LISA-U200 3G/WCDMA Modem");
m_type = LISA_U200;
} }
else if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAC200) else if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAC200)
{ {
INFO("Using a u-blox LISA-C200 CDMA Modem"); INFO("Using a u-blox LISA-C200 CDMA Modem");
m_gsm = false; m_type = LISA_C200;
m_onePort = true; m_onePort = true;
} }
else else
@ -510,9 +550,10 @@ int UbloxUSBModem::cleanup()
UbloxSerModem::UbloxSerModem() : UbloxSerModem::UbloxSerModem() :
UbloxModem(&m_atStream, NULL), UbloxModem(&m_atStream, NULL),
m_Serial(P0_15,P0_16), m_Serial(P0_15/*MDMTXD*/,P0_16/*MDMRXD*/),
m_atStream(m_Serial) 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 "link/LinkMonitor.h"
#include "CellularModem.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) /** u-blox WCDMA modem (LISA-U200)
*/ */
class UbloxModem: public CellularModem class UbloxModem: public CellularModem
@ -92,6 +105,8 @@ public:
*/ */
int getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegistrationState, LinkMonitor::BEARER* pBearer); int getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegistrationState, LinkMonitor::BEARER* pBearer);
int getPhoneNumber(char* phoneNumber);
/** Get the ATCommandsInterface instance /** Get the ATCommandsInterface instance
@return Pointer to 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 bool m_atOpen; //< Is the interface to the ATCommandsInterface open? true/false
protected: protected:
bool m_onePort; bool m_onePort;
bool m_gsm; enum { LISA_C200, LISA_U200, SARA_G350, UNKNOWN } m_type;
}; };
#include "WANDongle.h" #include "WANDongle.h"