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 SprintUSBModemHTTPClientTest by
PPPIPInterface.cpp
00001 /* PPPIPInterface.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__ 0 00021 #ifndef __MODULE__ 00022 #define __MODULE__ "PPPIPInterface.cpp" 00023 #endif 00024 00025 #include "core/fwk.h" 00026 #include "rtos.h" 00027 00028 #include "PPPIPInterface.h" 00029 00030 #define MSISDN "#777" 00031 //TODO Pass this as parameter (*99# is used by GSM systems, #777 by CDMA systems--well at least Sprint!) 00032 00033 #define CONNECT_CMD "ATD " MSISDN "\x0D" 00034 #define EXPECTED_RESP CONNECT_CMD "\x0D" "\x0A" "CONNECT" "\x0D" "\x0A" 00035 #define EXPECTED_RESP_DATARATE CONNECT_CMD "\x0D" "\x0A" "CONNECT %d" "\x0D" "\x0A" 00036 #define EXPECTED_RESP_MIN_LEN 20 00037 #define OK_RESP "\x0D" "\x0A" "OK" "\x0D" "\x0A" 00038 #define ESCAPE_SEQ "+++" 00039 #define HANGUP_CMD "ATH" "\x0D" 00040 #define NO_CARRIER_RESP "\x0D" "\x0A" "NO CARRIER" "\x0D" "\x0A" 00041 extern "C" { 00042 #include "lwip/ip_addr.h" 00043 #include "lwip/inet.h" 00044 #include "netif/ppp/ppp.h" 00045 } 00046 00047 PPPIPInterface::PPPIPInterface(IOStream* pStream) : LwIPInterface(), m_linkStatusSphre(1), m_pppErrCode(0), m_pStream(pStream), m_streamAvail(true), m_pppd(-1) 00048 { 00049 m_linkStatusSphre.wait(); 00050 } 00051 00052 /*virtual*/ PPPIPInterface::~PPPIPInterface() 00053 { 00054 00055 } 00056 00057 /*virtual*/ int PPPIPInterface::init() //Init PPP-specific stuff, create the right bindings, etc 00058 { 00059 DBG("Initializing LwIP"); 00060 LwIPInterface::init(); //Init LwIP, NOT including PPP 00061 DBG("Initializing PPP"); 00062 pppInit(); 00063 DBG("Done"); 00064 return OK; 00065 } 00066 00067 int PPPIPInterface::setup(const char* user, const char* pw) 00068 { 00069 DBG("Configuring PPP authentication method"); 00070 pppSetAuth(PPPAUTHTYPE_ANY, user, pw); 00071 DBG("Done"); 00072 return OK; 00073 } 00074 00075 /*virtual*/ int PPPIPInterface::connect() 00076 { 00077 int ret; 00078 char buf[32]; 00079 size_t len; 00080 DBG("Trying to connect with PPP"); 00081 00082 cleanupLink(); 00083 00084 DBG("Sending %s", CONNECT_CMD); 00085 00086 ret = m_pStream->write((uint8_t*)CONNECT_CMD, strlen(CONNECT_CMD), osWaitForever); 00087 if( ret != OK ) 00088 { 00089 return NET_UNKNOWN; 00090 } 00091 00092 DBG("Expect %s", EXPECTED_RESP); 00093 00094 len = 0; 00095 size_t readLen; 00096 ret = m_pStream->read((uint8_t*)buf + len, &readLen, EXPECTED_RESP_MIN_LEN, 10000); 00097 if( ret != OK ) 00098 { 00099 return NET_UNKNOWN; 00100 } 00101 len += readLen; 00102 while( (len < EXPECTED_RESP_MIN_LEN) || (buf[len-1] != LF) ) 00103 { 00104 ret = m_pStream->read((uint8_t*)buf + len, &readLen, 1, 10000); 00105 if( ret != OK ) 00106 { 00107 return NET_UNKNOWN; 00108 } 00109 len += readLen; 00110 } 00111 00112 buf[len]=0; 00113 00114 DBG("Got %s[len %d]", buf, len); 00115 00116 int datarate = 0; 00117 if( (sscanf( buf, EXPECTED_RESP_DATARATE, &datarate ) != 1) && (strcmp(EXPECTED_RESP, buf) != 0) ) 00118 { 00119 //Discard buffer 00120 do //Clear buf 00121 { 00122 ret = m_pStream->read((uint8_t*)buf, &len, 32, 0); 00123 } while( (ret == OK) && (len > 0) ); 00124 return NET_CONN; 00125 } 00126 00127 DBG("Transport link open"); 00128 if(datarate != 0) 00129 { 00130 DBG("Datarate: %d bps", datarate); 00131 } 00132 m_linkStatusSphre.wait(0); 00133 if((m_pppd != -1) && (m_pppErrCode == 0)) //Already connected 00134 { 00135 return NET_INVALID; 00136 } 00137 00138 ret = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this); 00139 if(ret < 0) 00140 { 00141 switch(ret) 00142 { 00143 case PPPERR_OPEN: 00144 default: 00145 return NET_FULL; //All available resources are already used 00146 } 00147 } 00148 m_pppd = ret; //PPP descriptor 00149 m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there 00150 if(m_pppErrCode != PPPERR_NONE) 00151 { 00152 m_pppd = -1; 00153 } 00154 switch(m_pppErrCode) 00155 { 00156 case PPPERR_NONE: //Connected OK 00157 return OK; 00158 case PPPERR_CONNECT: //Connection lost 00159 return NET_INTERRUPTED; 00160 case PPPERR_AUTHFAIL: //Authentication failed 00161 return NET_AUTH; 00162 case PPPERR_PROTOCOL: //Protocol error 00163 return NET_PROTOCOL; 00164 default: 00165 return NET_UNKNOWN; 00166 } 00167 } 00168 00169 /*virtual*/ int PPPIPInterface::disconnect() 00170 { 00171 int ret = m_linkStatusSphre.wait(0); 00172 if(ret > 0) //Already disconnected? 00173 { 00174 m_pppd = -1; //Discard PPP descriptor 00175 switch(m_pppErrCode) 00176 { 00177 case PPPERR_CONNECT: //Connection terminated 00178 case PPPERR_AUTHFAIL: //Authentication failed 00179 case PPPERR_PROTOCOL: //Protocol error 00180 case PPPERR_USER: 00181 return OK; 00182 default: 00183 return NET_UNKNOWN; 00184 } 00185 } 00186 else 00187 { 00188 if(m_pppd == -1) 00189 { 00190 return NET_INVALID; 00191 } 00192 pppClose(m_pppd); 00193 do 00194 { 00195 m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there 00196 DBG("Received PPP err code %d", m_pppErrCode); 00197 } while(m_pppErrCode != PPPERR_USER); 00198 m_pppd = -1; //Discard PPP descriptor 00199 } 00200 00201 Thread::wait(500); 00202 00203 DBG("Sending %s", ESCAPE_SEQ); 00204 00205 ret = m_pStream->write((uint8_t*)ESCAPE_SEQ, strlen(ESCAPE_SEQ), osWaitForever); 00206 if( ret != OK ) 00207 { 00208 return NET_UNKNOWN; 00209 } 00210 00211 Thread::wait(500); 00212 00213 cleanupLink(); 00214 00215 return OK; 00216 } 00217 00218 00219 int PPPIPInterface::cleanupLink() 00220 { 00221 int ret; 00222 char buf[32]; 00223 size_t len; 00224 00225 do //Clear buf 00226 { 00227 ret = m_pStream->read((uint8_t*)buf, &len, 32, 100); 00228 if(ret == OK) 00229 { 00230 buf[len] = '\0'; 00231 DBG("Got %s", buf); 00232 } 00233 } while( (ret == OK) && (len > 0) ); 00234 00235 DBG("Sending %s", HANGUP_CMD); 00236 00237 ret = m_pStream->write((uint8_t*)HANGUP_CMD, strlen(HANGUP_CMD), osWaitForever); 00238 if( ret != OK ) 00239 { 00240 return NET_UNKNOWN; 00241 } 00242 00243 size_t readLen; 00244 00245 //Hangup 00246 DBG("Expect %s", HANGUP_CMD); 00247 00248 len = 0; 00249 while( len < strlen(HANGUP_CMD) ) 00250 { 00251 ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(HANGUP_CMD) - len, 100); 00252 if( ret != OK ) 00253 { 00254 break; 00255 } 00256 len += readLen; 00257 ///// 00258 buf[len]=0; 00259 DBG("Got %s", buf); 00260 } 00261 00262 buf[len]=0; 00263 00264 DBG("Got %s[len %d]", buf, len); 00265 00266 //OK response 00267 DBG("Expect %s", OK_RESP); 00268 00269 len = 0; 00270 while( len < strlen(OK_RESP) ) 00271 { 00272 ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(OK_RESP) - len, 100); 00273 if( ret != OK ) 00274 { 00275 break; 00276 } 00277 len += readLen; 00278 ///// 00279 buf[len]=0; 00280 DBG("Got %s", buf); 00281 } 00282 00283 buf[len]=0; 00284 00285 DBG("Got %s[len %d]", buf, len); 00286 00287 //NO CARRIER event 00288 DBG("Expect %s", NO_CARRIER_RESP); 00289 00290 len = 0; 00291 while( len < strlen(NO_CARRIER_RESP) ) 00292 { 00293 ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(NO_CARRIER_RESP) - len, 100); 00294 if( ret != OK ) 00295 { 00296 break; 00297 } 00298 len += readLen; 00299 ///// 00300 buf[len]=0; 00301 DBG("Got %s", buf); 00302 } 00303 00304 buf[len]=0; 00305 00306 DBG("Got %s[len %d]", buf, len); 00307 00308 do //Clear buf 00309 { 00310 ret = m_pStream->read((uint8_t*)buf, &len, 32, 100); 00311 if(ret == OK) 00312 { 00313 buf[len] = '\0'; 00314 DBG("Got %s", buf); 00315 } 00316 } while( (ret == OK) && (len > 0) ); 00317 00318 00319 return OK; 00320 } 00321 00322 /*static*/ void PPPIPInterface::linkStatusCb(void *ctx, int errCode, void *arg) //PPP link status 00323 { 00324 PPPIPInterface* pIf = (PPPIPInterface*)ctx; 00325 struct ppp_addrs* addrs = (struct ppp_addrs*) arg; 00326 00327 switch(errCode) 00328 { 00329 case PPPERR_NONE: 00330 WARN("Connected via PPP."); 00331 DBG("Local IP address: %s", inet_ntoa(addrs->our_ipaddr)); 00332 DBG("Netmask: %s", inet_ntoa(addrs->netmask)); 00333 DBG("Remote IP address: %s", inet_ntoa(addrs->his_ipaddr)); 00334 DBG("Primary DNS: %s", inet_ntoa(addrs->dns1)); 00335 DBG("Secondary DNS: %s", inet_ntoa(addrs->dns2)); 00336 pIf->setConnected(true); 00337 pIf->setIPAddress(inet_ntoa(addrs->our_ipaddr)); 00338 break; 00339 case PPPERR_CONNECT: //Connection lost 00340 WARN("Connection lost/terminated"); 00341 pIf->setConnected(false); 00342 break; 00343 case PPPERR_AUTHFAIL: //Authentication failed 00344 WARN("Authentication failed"); 00345 pIf->setConnected(false); 00346 break; 00347 case PPPERR_PROTOCOL: //Protocol error 00348 WARN("Protocol error"); 00349 pIf->setConnected(false); 00350 break; 00351 case PPPERR_USER: 00352 WARN("Disconnected by user"); 00353 pIf->setConnected(false); 00354 break; 00355 default: 00356 WARN("Unknown error (%d)", errCode); 00357 pIf->setConnected(false); 00358 break; 00359 } 00360 00361 pIf->m_linkStatusSphre.wait(0); //If previous event has not been handled, "delete" it now 00362 pIf->m_pppErrCode = errCode; 00363 pIf->m_linkStatusSphre.release(); 00364 } 00365 00366 //LwIP PPP implementation 00367 extern "C" 00368 { 00369 00370 /** 00371 * Writes to the serial device. 00372 * 00373 * @param fd serial device handle 00374 * @param data pointer to data to send 00375 * @param len length (in bytes) of data to send 00376 * @return number of bytes actually sent 00377 * 00378 * @note This function will block until all data can be sent. 00379 */ 00380 u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len) 00381 { 00382 DBG("sio_write"); 00383 PPPIPInterface* pIf = (PPPIPInterface*)fd; 00384 int ret; 00385 if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further 00386 { 00387 return 0; 00388 } 00389 ret = pIf->m_pStream->write(data, len, osWaitForever); //Blocks until all data is sent or an error happens 00390 if(ret != OK) 00391 { 00392 return 0; 00393 } 00394 return len; 00395 } 00396 00397 /** 00398 * Reads from the serial device. 00399 * 00400 * @param fd serial device handle 00401 * @param data pointer to data buffer for receiving 00402 * @param len maximum length (in bytes) of data to receive 00403 * @return number of bytes actually received - may be 0 if aborted by sio_read_abort 00404 * 00405 * @note This function will block until data can be received. The blocking 00406 * can be cancelled by calling sio_read_abort(). 00407 */ 00408 u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len) 00409 { 00410 DBG("sio_read"); 00411 PPPIPInterface* pIf = (PPPIPInterface*)fd; 00412 int ret; 00413 size_t readLen; 00414 if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further 00415 { 00416 WARN("EXIT NOT AVAIL"); 00417 return 0; 00418 } 00419 ret = pIf->m_pStream->read(data, &readLen, len, osWaitForever); //Blocks until some data is received or an error happens 00420 if(ret != OK) 00421 { 00422 return 0; 00423 } 00424 DBG("ret"); 00425 return readLen; 00426 } 00427 00428 /** 00429 * Aborts a blocking sio_read() call. 00430 * 00431 * @param fd serial device handle 00432 */ 00433 void sio_read_abort(sio_fd_t fd) 00434 { 00435 DBG("sio_read_abort"); 00436 PPPIPInterface* pIf = (PPPIPInterface*)fd; 00437 if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further 00438 { 00439 return; 00440 } 00441 pIf->m_pStream->abortRead(); 00442 DBG("ret"); 00443 } 00444 00445 } 00446
Generated on Tue Jul 12 2022 13:16:05 by
1.7.2
