Simple test for USSD message.
Dependencies: CellularUSBModem
Fork of UbloxUSBModem by
UbloxModem.cpp
00001 /* UbloxModem.cpp */ 00002 /* Copyright (C) 2012 mbed.org, MIT License 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00005 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00006 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00007 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in all copies or 00011 * substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00014 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00015 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00016 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00018 */ 00019 00020 #define __DEBUG__ 3 00021 #ifndef __MODULE__ 00022 #define __MODULE__ "UbloxModem.cpp" 00023 #endif 00024 00025 #include "core/fwk.h" 00026 #include "sms/GSMSMSInterface.h" 00027 #include "sms/CDMASMSInterface.h" 00028 00029 #include "UbloxModem.h" 00030 00031 UbloxModem::UbloxModem(IOStream* atStream, IOStream* pppStream) : 00032 m_at(atStream), // Construct ATCommandsInterface with the AT serial channel 00033 m_CdmaSms(&m_at), // Construct SMSInterface with the ATCommandsInterface 00034 m_GsmSms(&m_at), // Construct SMSInterface with the ATCommandsInterface 00035 m_ussd(&m_at), // Construct USSDInterface with the ATCommandsInterface 00036 m_linkMonitor(&m_at), // Construct LinkMonitor with the ATCommandsInterface 00037 m_ppp(pppStream ? pppStream : atStream), // Construct PPPIPInterface with the PPP serial channel 00038 m_ipInit(false), // PPIPInterface connection is initially down 00039 m_smsInit(false), // SMSInterface starts un-initialised 00040 m_ussdInit(false), // USSDInterface starts un-initialised 00041 m_linkMonitorInit(false), // LinkMonitor subsystem starts un-initialised 00042 m_atOpen(false), // ATCommandsInterface starts in a closed state 00043 m_onePort(pppStream == NULL), 00044 m_gsm(true) 00045 { 00046 } 00047 00048 00049 class AtiProcessor : public IATCommandsProcessor 00050 { 00051 public: 00052 AtiProcessor() 00053 { 00054 i = 0; 00055 str[0] = '\0'; 00056 } 00057 const char* getInfo(void) { return str; } 00058 private: 00059 virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) 00060 { 00061 int l = strlen(line); 00062 if (i + l + 2 > sizeof(str)) 00063 return NET_OVERFLOW; 00064 if (i) str[i++] = ','; 00065 strcat(&str[i], line); 00066 i += l; 00067 return OK; 00068 } 00069 virtual int onNewEntryPrompt(ATCommandsInterface* pInst) 00070 { 00071 return OK; 00072 } 00073 protected: 00074 char str[256]; 00075 int i; 00076 }; 00077 00078 class CREGProcessor : public IATCommandsProcessor 00079 { 00080 public: 00081 CREGProcessor(bool gsm) : status(STATUS_REGISTERING) 00082 { 00083 m_gsm = gsm; 00084 } 00085 enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK, STATUS_FAILED }; 00086 REGISTERING_STATUS getStatus() 00087 { 00088 return status; 00089 } 00090 const char* getAtCommand() 00091 { 00092 return m_gsm ? "AT+CREG?" : "AT+CSS?"; 00093 } 00094 private: 00095 virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) 00096 { 00097 int r; 00098 if (m_gsm) 00099 { 00100 if( sscanf(line, "+CREG: %*d,%d", &r) == 1 ) 00101 { 00102 status = (r == 1 || r == 5) ? STATUS_OK : 00103 (r == 0 || r == 2) ? STATUS_REGISTERING : 00104 // (r == 3) ? STATUS_FAILED : 00105 STATUS_FAILED; 00106 } 00107 } 00108 else 00109 { 00110 char bc[3] = ""; 00111 if(sscanf(line, "%*s %*c,%2s,%*d",bc)==1) 00112 { 00113 status = (strcmp("Z", bc) == 0) ? STATUS_REGISTERING : STATUS_OK; 00114 } 00115 } 00116 return OK; 00117 } 00118 virtual int onNewEntryPrompt(ATCommandsInterface* pInst) 00119 { 00120 return OK; 00121 } 00122 volatile REGISTERING_STATUS status; 00123 bool m_gsm; 00124 }; 00125 00126 int UbloxModem::connect(const char* apn, const char* user, const char* password) 00127 { 00128 if( !m_ipInit ) 00129 { 00130 m_ipInit = true; 00131 m_ppp.init(); 00132 } 00133 m_ppp.setup(user, password, m_gsm ? DEFAULT_MSISDN_GSM : DEFAULT_MSISDN_CDMA); 00134 00135 int ret = init(); 00136 if(ret) 00137 { 00138 return ret; 00139 } 00140 00141 if (m_onePort) 00142 { 00143 m_smsInit = false; //SMS status reset 00144 m_ussdInit = false; //USSD status reset 00145 m_linkMonitorInit = false; //Link monitor status reset 00146 } 00147 00148 ATCommandsInterface::ATResult result; 00149 00150 if(apn != NULL) 00151 { 00152 char cmd[48]; 00153 int tries = 30; 00154 sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn); 00155 do //Try 30 times because for some reasons it can fail *a lot* with the K3772-Z dongle 00156 { 00157 ret = m_at.executeSimple(cmd, &result); 00158 DBG("Result of command: Err code=%d", ret); 00159 if(ret) 00160 { 00161 Thread::wait(500); 00162 } 00163 } while(ret && --tries); 00164 DBG("ATResult: AT return=%d (code %d)", result.result, result.code); 00165 DBG("APN set to %s", apn); 00166 } 00167 00168 //Connect 00169 DBG("Connecting"); 00170 if (m_onePort) 00171 { 00172 m_at.close(); // Closing AT parser 00173 m_atOpen = false; //Will need to be reinitialized afterwards 00174 } 00175 00176 DBG("Connecting PPP"); 00177 00178 ret = m_ppp.connect(); 00179 DBG("Result of connect: Err code=%d", ret); 00180 return ret; 00181 } 00182 00183 00184 int UbloxModem::disconnect() 00185 { 00186 DBG("Disconnecting from PPP"); 00187 int ret = m_ppp.disconnect(); 00188 if(ret) 00189 { 00190 ERR("Disconnect returned %d, still trying to disconnect", ret); 00191 } 00192 00193 //Ugly but leave dongle time to recover 00194 Thread::wait(500); 00195 00196 if (m_onePort) 00197 { 00198 //ATCommandsInterface::ATResult result; 00199 DBG("Starting AT thread"); 00200 ret = m_at.open(); 00201 if(ret) 00202 { 00203 return ret; 00204 } 00205 } 00206 00207 DBG("Trying to hangup"); 00208 00209 if (m_onePort) 00210 { 00211 //Reinit AT parser 00212 ret = m_at.init(false); 00213 DBG("Result of command: Err code=%d\n", ret); 00214 if(ret) 00215 { 00216 m_at.close(); // Closing AT parser 00217 DBG("AT Parser closed, could not complete disconnection"); 00218 return NET_TIMEOUT; 00219 } 00220 00221 } 00222 return OK; 00223 } 00224 00225 int UbloxModem::sendSM(const char* number, const char* message) 00226 { 00227 int ret = init(); 00228 if(ret) 00229 { 00230 return ret; 00231 } 00232 00233 ISMSInterface* sms; 00234 if (m_gsm) sms = &m_GsmSms; 00235 else sms = &m_CdmaSms; 00236 if(!m_smsInit) 00237 { 00238 ret = sms->init(); 00239 if(ret) 00240 { 00241 return ret; 00242 } 00243 m_smsInit = true; 00244 } 00245 00246 ret = sms->send(number, message); 00247 if(ret) 00248 { 00249 return ret; 00250 } 00251 00252 return OK; 00253 } 00254 00255 int UbloxModem::getSM(char* number, char* message, size_t maxLength) 00256 { 00257 int ret = init(); 00258 if(ret) 00259 { 00260 return ret; 00261 } 00262 00263 ISMSInterface* sms; 00264 if (m_gsm) sms = &m_GsmSms; 00265 else sms = &m_CdmaSms; 00266 if(!m_smsInit) 00267 { 00268 ret = sms->init(); 00269 if(ret) 00270 { 00271 return ret; 00272 } 00273 m_smsInit = true; 00274 } 00275 00276 ret = sms->get(number, message, maxLength); 00277 if(ret) 00278 { 00279 return ret; 00280 } 00281 00282 return OK; 00283 } 00284 00285 int UbloxModem::getSMCount(size_t* pCount) 00286 { 00287 int ret = init(); 00288 if(ret) 00289 { 00290 return ret; 00291 } 00292 00293 ISMSInterface* sms; 00294 if (m_gsm) sms = &m_GsmSms; 00295 else sms = &m_CdmaSms; 00296 if(!m_smsInit) 00297 { 00298 ret = sms->init(); 00299 if(ret) 00300 { 00301 return ret; 00302 } 00303 m_smsInit = true; 00304 } 00305 00306 ret = sms->getCount(pCount); 00307 if(ret) 00308 { 00309 return ret; 00310 } 00311 00312 return OK; 00313 } 00314 00315 ATCommandsInterface* UbloxModem::getATCommandsInterface() 00316 { 00317 return &m_at; 00318 } 00319 00320 int UbloxModem::init() 00321 { 00322 if(m_atOpen) 00323 { 00324 return OK; 00325 } 00326 00327 DBG("Starting AT thread if needed"); 00328 int ret = m_at.open(); 00329 if(ret) 00330 { 00331 return ret; 00332 } 00333 00334 DBG("Sending initialisation commands"); 00335 ret = m_at.init(false); 00336 if(ret) 00337 { 00338 return ret; 00339 } 00340 00341 ATCommandsInterface::ATResult result; 00342 AtiProcessor atiProcessor; 00343 do 00344 { 00345 ret = m_at.execute("ATI", &atiProcessor, &result); 00346 } 00347 while (ret != OK); 00348 { 00349 const char* info = atiProcessor.getInfo(); 00350 DBG("Modem Identification [%s]", info); 00351 if (strstr(info, "LISA-C200")) 00352 { 00353 m_gsm = false; // it is CDMA modem 00354 m_onePort = true; // force use of only one port 00355 } 00356 } 00357 00358 CREGProcessor cregProcessor(m_gsm); 00359 //Wait for network registration 00360 do 00361 { 00362 DBG("Waiting for network registration"); 00363 ret = m_at.execute(cregProcessor.getAtCommand(), &cregProcessor, &result); 00364 DBG("Result of command: Err code=%d\n", ret); 00365 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code); 00366 if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING) 00367 { 00368 Thread::wait(3000); 00369 } 00370 } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING); 00371 if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED) 00372 { 00373 ERR("Registration denied"); 00374 return NET_AUTH; 00375 } 00376 00377 m_atOpen = true; 00378 00379 return OK; 00380 } 00381 00382 int UbloxModem::cleanup() 00383 { 00384 if(m_ppp.isConnected()) 00385 { 00386 WARN("Data connection is still open"); //Try to encourage good behaviour from the user 00387 m_ppp.disconnect(); 00388 } 00389 00390 m_smsInit = false; 00391 m_ussdInit = false; 00392 m_linkMonitorInit = false; 00393 //We don't reset m_ipInit as PPPIPInterface::init() only needs to be called once 00394 00395 if(m_atOpen) 00396 { 00397 m_at.close(); 00398 m_atOpen = false; 00399 } 00400 00401 return OK; 00402 } 00403 00404 int UbloxModem::sendUSSD(const char* command, char* result, size_t maxLength) 00405 { 00406 int ret = init(); 00407 if(ret) 00408 { 00409 return ret; 00410 } 00411 00412 if(!m_ussdInit) 00413 { 00414 ret = m_ussd.init(); 00415 if(ret) 00416 { 00417 return ret; 00418 } 00419 m_ussdInit = true; 00420 } 00421 00422 ret = m_ussd.send(command, result, maxLength); 00423 if(ret) 00424 { 00425 return ret; 00426 } 00427 00428 return OK; 00429 } 00430 00431 int UbloxModem::getLinkState(int* pRssi, LinkMonitor::REGISTRATION_STATE* pRegistrationState, LinkMonitor::BEARER* pBearer) 00432 { 00433 int ret = init(); 00434 if(ret) 00435 { 00436 return ret; 00437 } 00438 00439 if(!m_linkMonitorInit) 00440 { 00441 ret = m_linkMonitor.init(); 00442 ret = m_linkMonitor.init(m_gsm); 00443 if(ret) 00444 { 00445 return ret; 00446 } 00447 m_linkMonitorInit = true; 00448 } 00449 00450 ret = m_linkMonitor.getState(pRssi, pRegistrationState, pBearer); 00451 if(ret) 00452 { 00453 return ret; 00454 } 00455 00456 return OK; 00457 } 00458 00459 #include "USBHost.h" 00460 #include "UbloxGSMModemInitializer.h" 00461 #include "UbloxCDMAModemInitializer.h" 00462 00463 UbloxUSBModem::UbloxUSBModem() : 00464 UbloxModem(&m_atStream, &m_pppStream), 00465 m_dongle(), // Construct WANDongle: USB interface with two serial channels to the modem (USBSerialStream objects) 00466 m_atStream(m_dongle.getSerial(1)), // AT commands are sent down one serial channel. 00467 m_pppStream(m_dongle.getSerial(0)), // PPP connections are managed via another serial channel. 00468 m_dongleConnected(false) // Dongle is initially not ready for anything 00469 { 00470 USBHost* host = USBHost::getHostInst(); 00471 m_dongle.addInitializer(new UbloxGSMModemInitializer(host)); 00472 m_dongle.addInitializer(new UbloxCDMAModemInitializer(host)); 00473 } 00474 00475 int UbloxUSBModem::init() 00476 { 00477 if( !m_dongleConnected ) 00478 { 00479 m_dongleConnected = true; 00480 while( !m_dongle.connected() ) 00481 { 00482 m_dongle.tryConnect(); 00483 Thread::wait(10); 00484 } 00485 if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAU200) 00486 { 00487 INFO("Using a u-blox LISA-U200 3G/WCDMA Modem"); 00488 } 00489 else if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAC200) 00490 { 00491 INFO("Using a u-blox LISA-C200 CDMA Modem"); 00492 m_gsm = false; 00493 m_onePort = true; 00494 } 00495 else 00496 { 00497 WARN("Using an Unknown Dongle"); 00498 } 00499 } 00500 return UbloxModem::init(); 00501 } 00502 00503 int UbloxUSBModem::cleanup() 00504 { 00505 UbloxModem::cleanup(); 00506 m_dongle.disconnect(); 00507 m_dongleConnected = false; 00508 return OK; 00509 } 00510 00511 UbloxSerModem::UbloxSerModem() : 00512 UbloxModem(&m_atStream, NULL), 00513 m_Serial(P0_15,P0_16), 00514 m_atStream(m_Serial) 00515 { 00516 m_Serial.baud(115200); 00517 } 00518
Generated on Thu Jul 21 2022 16:23:58 by 1.7.2