Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
UbloxUSBCDMAModem.cpp
00001 /* UbloxUSBCDMAModem.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__ 4 00021 #ifndef __MODULE__ 00022 #define __MODULE__ "UbloxUSBCDMAModem.cpp" 00023 #endif 00024 00025 #include "core/fwk.h" 00026 00027 #include "UbloxUSBCDMAModem.h" 00028 #include "UbloxCDMAModemInitializer.h" 00029 #include "USBHost.h" 00030 00031 #define USE_ONE_PORT 1 00032 00033 UbloxUSBCDMAModem::UbloxUSBCDMAModem(PinName powerGatingPin /*= NC*/, bool powerGatingOnWhenPinHigh /* = true*/, int serial /* 0 */) : m_dongle(), 00034 m_stream(m_dongle.getSerial(serial)), 00035 m_at(&m_stream), 00036 m_sms(&m_at), m_ppp(&m_stream), 00037 m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false), 00038 m_powerGatingPin(powerGatingPin), m_powerGatingOnWhenPinHigh(powerGatingOnWhenPinHigh) 00039 { 00040 USBHost* host = USBHost::getHostInst(); 00041 m_dongle.addInitializer(new UbloxCDMAModemInitializer(host)); 00042 if( m_powerGatingPin != NC ) 00043 { 00044 power(false); //Dongle will have to be powered on manually 00045 } 00046 } 00047 00048 class CSSProcessor : public IATCommandsProcessor 00049 { 00050 public: 00051 CSSProcessor() : status(STATUS_REGISTERING) 00052 { 00053 00054 } 00055 enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK }; 00056 REGISTERING_STATUS getStatus() 00057 { 00058 return status; 00059 } 00060 private: 00061 virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) 00062 { 00063 char b; 00064 char bc[3] = ""; 00065 int sid = 99999; 00066 00067 //if( sscanf(line, "%*d, %c", &r) == 1 ) 00068 if(sscanf(line, "%*s %c,%2s,%d", &b,bc,&sid)==3) 00069 { 00070 if(strcmp("Z", bc) == 0) 00071 status = STATUS_REGISTERING; 00072 else 00073 status = STATUS_OK; 00074 } 00075 return OK; 00076 } 00077 virtual int onNewEntryPrompt(ATCommandsInterface* pInst) 00078 { 00079 return OK; 00080 } 00081 volatile REGISTERING_STATUS status; 00082 }; 00083 00084 int UbloxUSBCDMAModem::connect(const char* apn, const char* user, const char* password) 00085 { 00086 if( !m_ipInit ) 00087 { 00088 m_ipInit = true; 00089 m_ppp.init(); 00090 } 00091 m_ppp.setup(user, password, DEFAULT_MSISDN_CDMA); 00092 00093 int ret = init(); 00094 if(ret) 00095 { 00096 return ret; 00097 } 00098 00099 #if USE_ONE_PORT 00100 m_smsInit = false; //SMS status reset 00101 //m_ussdInit = false; //USSD status reset 00102 //m_linkMonitorInit = false; //Link monitor status reset 00103 #endif 00104 00105 ATCommandsInterface::ATResult result; 00106 00107 if(apn != NULL) 00108 { 00109 char cmd[48]; 00110 sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn); 00111 ret = m_at.executeSimple(cmd, &result); 00112 DBG("Result of command: Err code=%d", ret); 00113 DBG("ATResult: AT return=%d (code %d)", result.result, result.code); 00114 DBG("APN set to %s", apn); 00115 } 00116 00117 00118 //Connect 00119 DBG("Connecting"); 00120 #if USE_ONE_PORT 00121 m_at.close(); // Closing AT parser 00122 m_atOpen = false; //Will need to be reinitialized afterwards 00123 #endif 00124 00125 DBG("Connecting PPP"); 00126 00127 ret = m_ppp.connect(); 00128 DBG("Result of connect: Err code=%d", ret); 00129 return ret; 00130 } 00131 00132 00133 int UbloxUSBCDMAModem::disconnect() 00134 { 00135 DBG("Disconnecting from PPP"); 00136 int ret = m_ppp.disconnect(); 00137 if(ret) 00138 { 00139 ERR("Disconnect returned %d, still trying to disconnect", ret); 00140 } 00141 00142 //Ugly but leave dongle time to recover 00143 Thread::wait(500); 00144 00145 #if USE_ONE_PORT 00146 ATCommandsInterface::ATResult result; 00147 DBG("Starting AT thread"); 00148 ret = m_at.open(); 00149 if(ret) 00150 { 00151 return ret; 00152 } 00153 #endif 00154 00155 DBG("Trying to hangup"); 00156 00157 #if 0 //Does not appear to work 00158 int tries = 10; 00159 do 00160 { 00161 ret = m_at.executeSimple("+++", &result, 1000); 00162 DBG("Result of command: Err code=%d\n", ret); 00163 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code); 00164 } while(tries-- && ret); 00165 if(!ret) 00166 { 00167 ret = m_at.executeSimple("ATH", &result); 00168 DBG("Result of command: Err code=%d\n", ret); 00169 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code); 00170 } 00171 #endif 00172 00173 #if USE_ONE_PORT 00174 //Reinit AT parser 00175 ret = m_at.init(); 00176 DBG("Result of command: Err code=%d\n", ret); 00177 if(ret) 00178 { 00179 m_at.close(); // Closing AT parser 00180 DBG("AT Parser closed, could not complete disconnection"); 00181 return NET_TIMEOUT; 00182 } 00183 00184 #if 0 00185 m_at.close(); // Closing AT parser 00186 DBG("AT Parser closed"); 00187 #endif 00188 #endif 00189 return OK; 00190 } 00191 00192 int UbloxUSBCDMAModem::sendSM(const char* number, const char* message) 00193 { 00194 int ret = init(); 00195 if(ret) 00196 { 00197 return ret; 00198 } 00199 00200 if(!m_smsInit) 00201 { 00202 ret = m_sms.init(); 00203 if(ret) 00204 { 00205 return ret; 00206 } 00207 m_smsInit = true; 00208 } 00209 00210 ret = m_sms.send(number, message); 00211 if(ret) 00212 { 00213 return ret; 00214 } 00215 00216 return OK; 00217 } 00218 00219 int UbloxUSBCDMAModem::getSM(char* number, char* message, size_t maxLength) 00220 { 00221 int ret = init(); 00222 if(ret) 00223 { 00224 return ret; 00225 } 00226 00227 if(!m_smsInit) 00228 { 00229 ret = m_sms.init(); 00230 if(ret) 00231 { 00232 return ret; 00233 } 00234 m_smsInit = true; 00235 } 00236 00237 ret = m_sms.get(number, message, maxLength); 00238 if(ret) 00239 { 00240 return ret; 00241 } 00242 00243 return OK; 00244 } 00245 00246 int UbloxUSBCDMAModem::getSMCount(size_t* pCount) 00247 { 00248 int ret = init(); 00249 if(ret) 00250 { 00251 return ret; 00252 } 00253 00254 if(!m_smsInit) 00255 { 00256 ret = m_sms.init(); 00257 if(ret) 00258 { 00259 return ret; 00260 } 00261 m_smsInit = true; 00262 } 00263 00264 ret = m_sms.getCount(pCount); 00265 if(ret) 00266 { 00267 return ret; 00268 } 00269 00270 return OK; 00271 } 00272 00273 ATCommandsInterface* UbloxUSBCDMAModem::getATCommandsInterface() 00274 { 00275 return &m_at; 00276 } 00277 00278 int UbloxUSBCDMAModem::power(bool enable) 00279 { 00280 if( m_powerGatingPin == NC ) 00281 { 00282 return NET_INVALID; //A pin name has not been provided in the constructor 00283 } 00284 00285 if(!enable) //Will force components to re-init 00286 { 00287 cleanup(); 00288 } 00289 00290 DigitalOut powerGatingOut(m_powerGatingPin); 00291 powerGatingOut = m_powerGatingOnWhenPinHigh?enable:!enable; 00292 00293 return OK; 00294 } 00295 00296 bool UbloxUSBCDMAModem::power() 00297 { 00298 if( m_powerGatingPin == NC ) 00299 { 00300 return true; //Assume power is always on 00301 } 00302 00303 DigitalOut powerGatingOut(m_powerGatingPin); 00304 return m_powerGatingOnWhenPinHigh?powerGatingOut:!powerGatingOut; 00305 } 00306 00307 int UbloxUSBCDMAModem::init() 00308 { 00309 if( !m_dongleConnected ) 00310 { 00311 if(!power()) 00312 { 00313 //Obviously cannot initialize the dongle if it is disconnected... 00314 ERR("Power is off"); 00315 return NET_INVALID; 00316 } 00317 m_dongleConnected = true; 00318 while( !m_dongle.connected() ) 00319 { 00320 m_dongle.tryConnect(); 00321 Thread::wait(100); 00322 } 00323 } 00324 00325 if(m_atOpen) 00326 { 00327 return OK; 00328 } 00329 00330 DBG("Starting AT thread if needed"); 00331 int ret = m_at.open(); 00332 if(ret) 00333 { 00334 return ret; 00335 } 00336 00337 DBG("Sending initialisation commands"); 00338 ret = m_at.init(); 00339 if(ret) 00340 { 00341 return ret; 00342 } 00343 00344 if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAC200) 00345 { 00346 INFO("Using a UBLOX C200 Dongle"); 00347 } 00348 else 00349 { 00350 WARN("Using an Unknown Dongle"); 00351 } 00352 00353 ATCommandsInterface::ATResult result; 00354 00355 //Wait for network registration 00356 CSSProcessor cssProcessor; 00357 do 00358 { 00359 DBG("Waiting for network registration"); 00360 ret = m_at.execute("AT+CSS?", &cssProcessor, &result); 00361 DBG("Result of command: Err code=%d\n", ret); 00362 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code); 00363 if(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING) 00364 { 00365 Thread::wait(3000); 00366 } 00367 } while(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING); 00368 00369 m_atOpen = true; 00370 00371 return OK; 00372 } 00373 00374 int UbloxUSBCDMAModem::cleanup() 00375 { 00376 if(m_ppp.isConnected()) 00377 { 00378 WARN("Data connection is still open"); //Try to encourage good behaviour from the user 00379 m_ppp.disconnect(); 00380 } 00381 00382 m_smsInit = false; 00383 // m_linkMonitorInit = false; 00384 //We don't reset m_ipInit as PPPIPInterface::init() only needs to be called once 00385 00386 if(m_atOpen) 00387 { 00388 m_at.close(); 00389 m_atOpen = false; 00390 } 00391 00392 m_dongle.disconnect(); 00393 m_dongleConnected = false; 00394 00395 return OK; 00396 } 00397 00398
Generated on Tue Jul 12 2022 13:16:17 by
