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.
VodafoneK3770.cpp
00001 /* VodafoneK3770.cpp */ 00002 /* 00003 Copyright (C) 2012 ARM Limited. 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy of 00006 this software and associated documentation files (the "Software"), to deal in 00007 the Software without restriction, including without limitation the rights to 00008 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 00009 of the Software, and to permit persons to whom the Software is furnished to do 00010 so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in all 00013 copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00021 SOFTWARE. 00022 */ 00023 00024 #define __DEBUG__ 4 00025 #ifndef __MODULE__ 00026 #define __MODULE__ "VodafoneK3770.cpp" 00027 #endif 00028 00029 #include "core/fwk.h" 00030 00031 #include "VodafoneK3770.h" 00032 00033 VodafoneK3770::VodafoneK3770() : m_dongle(), 00034 m_stream(m_dongle), m_at(&m_stream), 00035 m_ppp(&m_stream), m_sms(&m_at), 00036 m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false) 00037 { 00038 00039 } 00040 00041 class CREGProcessor : public IATCommandsProcessor 00042 { 00043 public: 00044 CREGProcessor() : status(STATUS_REGISTERING) 00045 { 00046 00047 } 00048 enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK, STATUS_FAILED }; 00049 REGISTERING_STATUS getStatus() 00050 { 00051 return status; 00052 } 00053 private: 00054 virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) 00055 { 00056 int r; 00057 if( sscanf(line, "+CREG: %*d,%d", &r) == 1 ) 00058 { 00059 switch(r) 00060 { 00061 case 1: 00062 case 5: 00063 status = STATUS_OK; 00064 break; 00065 case 0: 00066 case 2: 00067 status = STATUS_REGISTERING; 00068 break; 00069 case 3: 00070 default: 00071 status = STATUS_FAILED; 00072 break; 00073 } 00074 } 00075 return OK; 00076 } 00077 virtual int onNewEntryPrompt(ATCommandsInterface* pInst) 00078 { 00079 return OK; 00080 } 00081 volatile REGISTERING_STATUS status; 00082 }; 00083 00084 class COPSProcessor : public IATCommandsProcessor 00085 { 00086 public: 00087 COPSProcessor() : valid(false) 00088 { 00089 network[0] = '\0'; 00090 apn[0] = '\0'; 00091 bearer[0] = '\0'; 00092 } 00093 char* getNetwork() 00094 { 00095 return network; 00096 } 00097 char* getAPN() 00098 { 00099 return apn; 00100 } 00101 char* getBearer() 00102 { 00103 return bearer; 00104 } 00105 bool isValid() 00106 { 00107 return valid; 00108 } 00109 private: 00110 virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) 00111 { 00112 int networkId; 00113 int bearerId; 00114 int s = sscanf(line, "+COPS: %*d,%*d,\"%d\",%d", &networkId, &bearerId); 00115 if( s == 2 ) 00116 { 00117 switch(networkId) 00118 { 00119 case 23415: 00120 strcpy(network, "Vodafone UK"); 00121 strcpy(apn, "pp.vodafone.co.uk"); 00122 valid = true; 00123 break; 00124 case 20810: 00125 strcpy(network, "SFR FR"); 00126 strcpy(apn, "websfr"); 00127 valid = true; 00128 break; 00129 default: 00130 break; 00131 } 00132 } 00133 else 00134 { 00135 return OK; 00136 } 00137 switch(bearerId) 00138 { 00139 case 0: strcpy(bearer, "GSM"); break; 00140 case 1: strcpy(bearer, "GSM Compact"); break; 00141 case 2: strcpy(bearer, "UTRAN"); break; 00142 case 3: strcpy(bearer, "GSM w/EGPRS"); break; 00143 case 4: strcpy(bearer, "UTRAN w/HSDPA"); break; 00144 case 5: strcpy(bearer, "UTRAN w/HSUPA"); break; 00145 case 6: strcpy(bearer, "UTRAN w/HSDPA and HSUPA"); break; 00146 case 7: strcpy(bearer, "E-UTRAN"); break; 00147 00148 default: 00149 break; 00150 } 00151 return OK; 00152 } 00153 virtual int onNewEntryPrompt(ATCommandsInterface* pInst) 00154 { 00155 return OK; 00156 } 00157 char network[24]; 00158 char bearer[24]; 00159 char apn[24]; 00160 volatile bool valid; 00161 }; 00162 00163 00164 int VodafoneK3770::connect(const char* apn, const char* user, const char* password) 00165 { 00166 if( !m_ipInit ) 00167 { 00168 m_ipInit = true; 00169 m_ppp.init(); 00170 } 00171 m_ppp.setup(user, password); 00172 00173 int ret = init(); 00174 if(ret) 00175 { 00176 return ret; 00177 } 00178 00179 m_smsInit = false; //SMS status reset 00180 00181 ATCommandsInterface::ATResult result; 00182 00183 #if 0 00184 //Get network info & select corresponding APN 00185 COPSProcessor copsProcessor; 00186 DBG("Get network info & select APN from DB"); 00187 ret = m_at.execute("AT+COPS=,2;+COPS?", &copsProcessor, &result); //Configure to get operator's info in numeric code & get operator's id 00188 DBG("Result of command: Err code=%d", ret); 00189 DBG("ATResult: AT return=%d (code %d)", result.result, result.code); 00190 00191 if(!copsProcessor.isValid()) 00192 { 00193 WARN("Connected to an unknown network, try to connect with default parameters"); 00194 DBG("Connected with %s", copsProcessor.getBearer()); 00195 } 00196 else 00197 { 00198 DBG("Connected to %s with %s", copsProcessor.getNetwork(), copsProcessor.getBearer()); 00199 char cmd[48]; 00200 sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", copsProcessor.getAPN()); 00201 ret = m_at.executeSimple(cmd, &result); 00202 DBG("Result of command: Err code=%d", ret); 00203 DBG("ATResult: AT return=%d (code %d)", result.result, result.code); 00204 DBG("APN set to %s", copsProcessor.getAPN()); 00205 } 00206 #else 00207 if(apn != NULL) 00208 { 00209 char cmd[48]; 00210 sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn); 00211 ret = m_at.executeSimple(cmd, &result); 00212 DBG("Result of command: Err code=%d", ret); 00213 DBG("ATResult: AT return=%d (code %d)", result.result, result.code); 00214 DBG("APN set to %s", apn); 00215 } 00216 #endif 00217 00218 00219 //Connect 00220 DBG("Connecting"); 00221 ret = m_at.executeSimple("ATDT *99#", &result); 00222 DBG("Result of command: Err code=%d", ret); 00223 DBG("ATResult: AT return=%d (code %d)", result.result, result.code); 00224 m_at.close(); // Closing AT parser 00225 m_atOpen = false; //Will need to be reinitialized afterwards 00226 00227 DBG("AT Parser closed"); 00228 if( (ret!=NET_MOREINFO) || (result.result != ATCommandsInterface::ATResult::AT_CONNECT)) 00229 { 00230 ERR("Could not connect"); 00231 return ret; //Could not connect 00232 } 00233 DBG("Connecting PPP"); 00234 00235 ret = m_ppp.connect(); 00236 DBG("Result of connect: Err code=%d", ret); 00237 return ret; 00238 } 00239 00240 00241 int VodafoneK3770::disconnect() 00242 { 00243 DBG("Disconnecting from PPP"); 00244 int ret = m_ppp.disconnect(); 00245 if(ret) 00246 { 00247 ERR("Disconnect returned %d, still trying to disconnect", ret); 00248 } 00249 00250 //Ugly but leave dongle time to recover 00251 Thread::wait(500); 00252 00253 ATCommandsInterface::ATResult result; 00254 DBG("Starting AT thread"); 00255 ret = m_at.open(); 00256 if(ret) 00257 { 00258 return ret; 00259 } 00260 00261 DBG("Trying to hangup"); 00262 00263 #if 0 //Does not appear to work 00264 int tries = 10; 00265 do 00266 { 00267 ret = m_at.executeSimple("+++", &result, 1000); 00268 DBG("Result of command: Err code=%d\n", ret); 00269 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code); 00270 } while(tries-- && ret); 00271 if(!ret) 00272 { 00273 ret = m_at.executeSimple("ATH", &result); 00274 DBG("Result of command: Err code=%d\n", ret); 00275 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code); 00276 } 00277 #endif 00278 00279 //Reinit AT parser 00280 ret = m_at.init(); 00281 DBG("Result of command: Err code=%d\n", ret); 00282 if(ret) 00283 { 00284 m_at.close(); // Closing AT parser 00285 DBG("AT Parser closed, could not complete disconnection"); 00286 return NET_TIMEOUT; 00287 } 00288 00289 m_at.close(); // Closing AT parser 00290 DBG("AT Parser closed"); 00291 return OK; 00292 } 00293 00294 int VodafoneK3770::sendSM(const char* number, const char* message) 00295 { 00296 int ret = init(); 00297 if(ret) 00298 { 00299 return ret; 00300 } 00301 00302 if(!m_smsInit) 00303 { 00304 ret = m_sms.init(); 00305 if(ret) 00306 { 00307 return ret; 00308 } 00309 m_smsInit = true; 00310 } 00311 00312 ret = m_sms.send(number, message); 00313 if(ret) 00314 { 00315 return ret; 00316 } 00317 00318 return OK; 00319 } 00320 00321 int VodafoneK3770::getSM(char* number, char* message, size_t maxLength) 00322 { 00323 int ret = init(); 00324 if(ret) 00325 { 00326 return ret; 00327 } 00328 00329 if(!m_smsInit) 00330 { 00331 ret = m_sms.init(); 00332 if(ret) 00333 { 00334 return ret; 00335 } 00336 m_smsInit = true; 00337 } 00338 00339 ret = m_sms.get(number, message, maxLength); 00340 if(ret) 00341 { 00342 return ret; 00343 } 00344 00345 return OK; 00346 } 00347 00348 int VodafoneK3770::getSMCount(size_t* pCount) 00349 { 00350 int ret = init(); 00351 if(ret) 00352 { 00353 return ret; 00354 } 00355 00356 if(!m_smsInit) 00357 { 00358 ret = m_sms.init(); 00359 if(ret) 00360 { 00361 return ret; 00362 } 00363 m_smsInit = true; 00364 } 00365 00366 ret = m_sms.getCount(pCount); 00367 if(ret) 00368 { 00369 return ret; 00370 } 00371 00372 return OK; 00373 } 00374 00375 00376 int VodafoneK3770::init() 00377 { 00378 if( !m_dongleConnected ) 00379 { 00380 m_dongleConnected = true; 00381 while( !m_dongle.connected() ) 00382 { 00383 m_dongle.tryConnect(); 00384 Thread::wait(10); 00385 } 00386 } 00387 00388 if(m_atOpen) 00389 { 00390 return OK; 00391 } 00392 00393 DBG("Starting AT thread if needed"); 00394 int ret = m_at.open(); 00395 if(ret) 00396 { 00397 return ret; 00398 } 00399 00400 DBG("Sending initialisation commands"); 00401 ret = m_at.init(); 00402 if(ret) 00403 { 00404 return ret; 00405 } 00406 00407 DBG("Configuring unsolicited result codes support properly"); 00408 //Configuring port 00409 ret = m_at.executeSimple("AT^CURC=0;^PORTSEL=1", NULL); //Huawei-specific, not 3GPP-compliant 00410 if(ret != OK) 00411 { 00412 return NET_PROTOCOL; 00413 } 00414 00415 ATCommandsInterface::ATResult result; 00416 00417 //Wait for network registration 00418 CREGProcessor cregProcessor; 00419 do 00420 { 00421 DBG("Waiting for network registration"); 00422 ret = m_at.execute("AT+CREG?", &cregProcessor, &result); 00423 DBG("Result of command: Err code=%d\n", ret); 00424 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code); 00425 if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING) 00426 { 00427 Thread::wait(3000); 00428 } 00429 } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING); 00430 if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED) 00431 { 00432 ERR("Registration denied"); 00433 return NET_AUTH; 00434 } 00435 00436 m_atOpen = true; 00437 00438 return OK; 00439 } 00440 00441
Generated on Tue Jul 12 2022 17:50:57 by
