PHS module SMA-01 library. see: https://developer.mbed.org/users/phsfan/notebook/abitusbmodem/
Dependencies: Socket lwip-sys lwip
Dependents: AbitUSBModem_HTTPTest AbitUSBModem_MQTTTest AbitUSBModem_WebsocketTest AbitUSBModem_SMSTest
Fork of VodafoneUSBModem by
ip/PPPIPInterface.cpp
- Committer:
- donatien
- Date:
- 2012-07-11
- Revision:
- 12:66dc2c8eba2d
- Parent:
- 11:565b2ec40dea
- Child:
- 18:1789a11d1892
File content as of revision 12:66dc2c8eba2d:
/* PPPIPInterface.cpp */ /* Copyright (C) 2012 ARM Limited. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define MSISDN "*99#" #define CONNECT_CMD "ATD " MSISDN "\x0D" #define EXPECTED_RESP CONNECT_CMD "\x0D" "\x0A" "CONNECT" "\x0D" "\x0A" #define OK_RESP #define __DEBUG__ 0 //Maximum verbosity #ifndef __MODULE__ #define __MODULE__ "PPPIPInterface.cpp" #endif #include "core/fwk.h" #include "rtos.h" #include "PPPIPInterface.h" extern "C" { #include "lwip/ip_addr.h" #include "lwip/inet.h" #include "netif/ppp/ppp.h" } PPPIPInterface::PPPIPInterface(IOStream* pStream) : LwIPInterface(), m_linkStatusSphre(1), m_pppErrCode(0), m_pStream(pStream), m_streamAvail(true), m_pppd(-1) { m_linkStatusSphre.wait(); } /*virtual*/ PPPIPInterface::~PPPIPInterface() { } /*virtual*/ int PPPIPInterface::init() //Init PPP-specific stuff, create the right bindings, etc { DBG("Initializing LwIP"); LwIPInterface::init(); //Init LwIP, NOT including PPP DBG("Initializing PPP"); pppInit(); DBG("Done"); return OK; } int PPPIPInterface::setup(const char* user, const char* pw) { DBG("Configuring PPP authentication method"); pppSetAuth(PPPAUTHTYPE_ANY, user, pw); DBG("Done"); return OK; } /*virtual*/ int PPPIPInterface::connect() { int ret; char buf[32]; size_t len; DBG("Trying to connect with PPP"); do //Clear buf { ret = m_pStream->read((uint8_t*)buf, &len, 32, 0); } while( (ret == OK) && (len > 0) ); DBG("Sending %s", CONNECT_CMD); ret = m_pStream->write((uint8_t*)CONNECT_CMD, strlen(CONNECT_CMD), osWaitForever); if( ret != OK ) { return NET_UNKNOWN; } DBG("Expect %s [len %d]", EXPECTED_RESP, strlen(EXPECTED_RESP)); len = 0; while(len < strlen(EXPECTED_RESP)) { size_t readLen; ret = m_pStream->read((uint8_t*)buf + len, &readLen, strlen(EXPECTED_RESP) - len, 10000); if( ret != OK ) { return NET_UNKNOWN; } len += readLen; } buf[len]=0; DBG("Got %s[len %d]", buf, len); if( memcmp(EXPECTED_RESP, buf, strlen(EXPECTED_RESP)) != 0 ) { //Discard buffer do //Clear buf { ret = m_pStream->read((uint8_t*)buf, &len, 32, 0); } while( (ret == OK) && (len > 0) ); return NET_CONN; } DBG("Transport link open"); m_linkStatusSphre.wait(0); if((m_pppd != -1) && (m_pppErrCode == 0)) //Already connected { return NET_INVALID; } ret = pppOverSerialOpen(this, PPPIPInterface::linkStatusCb, this); if(ret < 0) { switch(ret) { case PPPERR_OPEN: default: return NET_FULL; //All available resources are already used } } m_pppd = ret; //PPP descriptor m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there if(m_pppErrCode != PPPERR_NONE) { m_pppd = -1; } switch(m_pppErrCode) { case PPPERR_NONE: //Connected OK return OK; case PPPERR_CONNECT: //Connection lost return NET_INTERRUPTED; case PPPERR_AUTHFAIL: //Authentication failed return NET_AUTH; case PPPERR_PROTOCOL: //Protocol error return NET_PROTOCOL; default: return NET_UNKNOWN; } } /*virtual*/ int PPPIPInterface::disconnect() { int ret = m_linkStatusSphre.wait(0); if(ret > 0) //Already disconnected? { m_pppd = -1; //Discard PPP descriptor switch(m_pppErrCode) { case PPPERR_CONNECT: //Connection terminated case PPPERR_AUTHFAIL: //Authentication failed case PPPERR_PROTOCOL: //Protocol error case PPPERR_USER: return OK; default: return NET_UNKNOWN; } } else { if(m_pppd == -1) { return NET_INVALID; } pppClose(m_pppd); do { m_linkStatusSphre.wait(); //Block indefinitely; there should be a timeout there DBG("Received PPP err code %d", m_pppErrCode); } while(m_pppErrCode != PPPERR_USER); m_pppd = -1; //Discard PPP descriptor } return OK; } /*static*/ void PPPIPInterface::linkStatusCb(void *ctx, int errCode, void *arg) //PPP link status { PPPIPInterface* pIf = (PPPIPInterface*)ctx; struct ppp_addrs* addrs = (struct ppp_addrs*) arg; switch(errCode) { case PPPERR_NONE: WARN("Connected via PPP."); DBG("Local IP address: %s", inet_ntoa(addrs->our_ipaddr)); DBG("Netmask: %s", inet_ntoa(addrs->netmask)); DBG("Remote IP address: %s", inet_ntoa(addrs->his_ipaddr)); DBG("Primary DNS: %s", inet_ntoa(addrs->dns1)); DBG("Secondary DNS: %s", inet_ntoa(addrs->dns2)); pIf->setConnected(true); pIf->setIPAddress(inet_ntoa(addrs->our_ipaddr)); break; case PPPERR_CONNECT: //Connection lost WARN("Connection lost/terminated"); pIf->setConnected(false); break; case PPPERR_AUTHFAIL: //Authentication failed WARN("Authentication failed"); pIf->setConnected(false); break; case PPPERR_PROTOCOL: //Protocol error WARN("Protocol error"); pIf->setConnected(false); break; case PPPERR_USER: WARN("Disconnected by user"); pIf->setConnected(false); break; default: WARN("Unknown error (%d)", errCode); pIf->setConnected(false); break; } pIf->m_linkStatusSphre.wait(0); //If previous event has not been handled, "delete" it now pIf->m_pppErrCode = errCode; pIf->m_linkStatusSphre.release(); } //LwIP PPP implementation extern "C" { /** * Writes to the serial device. * * @param fd serial device handle * @param data pointer to data to send * @param len length (in bytes) of data to send * @return number of bytes actually sent * * @note This function will block until all data can be sent. */ u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len) { DBG("sio_write"); PPPIPInterface* pIf = (PPPIPInterface*)fd; int ret; if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further { return 0; } ret = pIf->m_pStream->write(data, len, osWaitForever); //Blocks until all data is sent or an error happens if(ret != OK) { return 0; } return len; } /** * Reads from the serial device. * * @param fd serial device handle * @param data pointer to data buffer for receiving * @param len maximum length (in bytes) of data to receive * @return number of bytes actually received - may be 0 if aborted by sio_read_abort * * @note This function will block until data can be received. The blocking * can be cancelled by calling sio_read_abort(). */ u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len) { DBG("sio_read"); PPPIPInterface* pIf = (PPPIPInterface*)fd; int ret; size_t readLen; if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further { WARN("EXIT NOT AVAIL"); return 0; } ret = pIf->m_pStream->read(data, &readLen, len, osWaitForever); //Blocks until some data is received or an error happens if(ret != OK) { return 0; } DBG("ret"); return readLen; } /** * Aborts a blocking sio_read() call. * * @param fd serial device handle */ void sio_read_abort(sio_fd_t fd) { DBG("sio_read_abort"); PPPIPInterface* pIf = (PPPIPInterface*)fd; if(!pIf->m_streamAvail) //If stream is not available (it is a shared resource) don't go further { return; } pIf->m_pStream->abortRead(); DBG("ret"); } }