Base library for cellular modem implementations

Dependencies:   Socket lwip-sys lwip

Dependents:   CellularUSBModem CellularUSBModem

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USSDInterface.cpp Source File

USSDInterface.cpp

00001 /* USSDInterface.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__ "USSDInterface.cpp"
00023 #endif
00024 
00025 #include "core/fwk.h"
00026 
00027 #include "USSDInterface.h"
00028 
00029 #include <cstdio>
00030 
00031 #define DEFAULT_TIMEOUT 10000
00032 #define USSD_TIMEOUT 15000
00033 
00034 USSDInterface::USSDInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_responseMtx(), m_responseSphre(1), m_result(NULL), m_maxResultLength(0)
00035 {
00036   m_responseSphre.wait(0); //Take ownership of the semaphore
00037   m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
00038 }
00039 
00040 int USSDInterface::init()
00041 {
00042   DBG("Initialization done");
00043   return OK;
00044 }
00045 
00046 int USSDInterface::send(const char* command, char* result, size_t maxLength)
00047 {
00048   if (strlen(command) > 20) //Prevent buffer overflow
00049   {
00050     return NET_TOOSMALL;
00051   }
00052 
00053   m_responseMtx.lock();
00054   m_result = result;
00055   m_maxResultLength = maxLength;
00056   m_responseMtx.unlock();
00057 
00058   m_responseSphre.wait(0); //Make sure there is not a pending result that needs to be discarded
00059 
00060   DBG("Send USSD command & register for unsolicited result codes");
00061   //Send USSD command to the network
00062   char cmd[32];
00063   std::sprintf(cmd, "AT+CUSD=1,\"%s\"", command);
00064   int ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
00065   if( ret != OK )
00066   {
00067     return NET_PROTOCOL;
00068   }
00069   
00070   //Did we already get a response (3GPP rev < 6) ?
00071 
00072   //Now wait for response
00073   int res = m_responseSphre.wait(USSD_TIMEOUT);
00074 
00075   //Reset data
00076   m_responseMtx.lock();
00077   m_result = NULL;
00078   m_maxResultLength = 0;
00079   m_responseMtx.unlock();
00080 
00081   if(res <= 0)
00082   {
00083     DBG("No result received");
00084     ret = m_pIf->executeSimple("AT+CUSD=2", NULL, DEFAULT_TIMEOUT); //Cancel command
00085     if( ret != OK )
00086     {
00087       return NET_PROTOCOL;
00088     }
00089     return NET_TIMEOUT;
00090   }
00091 
00092   DBG("Result received: %s", result);
00093 
00094   return OK;
00095 }
00096 
00097 /*virtual*/ int USSDInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
00098 {
00099   const char* pSemicol = strchr(line, ':');
00100   if( ( (pSemicol - line) != strlen("+CUSD") ) || ( memcmp(line, "+CUSD", strlen("+CUSD")) != 0) )
00101   {
00102     WARN("Unknown code");
00103     return OK;
00104   }
00105 
00106   const char* pData = NULL;
00107   if( pSemicol != NULL ) //Split the identifier & the result code (if it exists)
00108   {
00109     pData = pSemicol + 1;
00110     if(pData[0]==' ')
00111     {
00112       pData++; //Suppress whitespace
00113     }
00114     processResult(pData);
00115   }
00116   return OK;
00117 }
00118 
00119 /*virtual*/ int USSDInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
00120 {
00121   return OK;
00122 }
00123 
00124 /*virtual*/ bool USSDInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
00125 {
00126   DBG("AT code is %s", atCode);
00127   if( strcmp("+CUSD", atCode) == 0 )
00128   {
00129     return true;
00130   }
00131 
00132   DBG("Not handled");
00133   return false;
00134 }
00135 
00136 /*virtual*/ void USSDInterface::onDispatchStart()
00137 {
00138 
00139 
00140 }
00141 
00142 /*virtual*/ void USSDInterface::onDispatchStop()
00143 {
00144 
00145 }
00146 
00147 /*virtual*/ char* USSDInterface::getEventsEnableCommand()
00148 {
00149   return NULL; //No need to disable events here
00150 }
00151 
00152 /*virtual*/ char* USSDInterface::getEventsDisableCommand()
00153 {
00154   return NULL; //No need to re-enable events here
00155 }
00156 
00157 /*virtual*/ void USSDInterface::onEvent(const char* atCode, const char* evt)
00158 {
00159   if( strcmp("+CUSD", atCode) != 0 )
00160   {
00161     WARN("Wrong AT Code");
00162     return; //Not supported
00163   }
00164 
00165   processResult(evt);
00166 }
00167 
00168 void USSDInterface::processResult(const char* data)
00169 {
00170   char* pStart = (char*) strchr(data,'\"');
00171   if(pStart==NULL)
00172   {
00173     WARN("Could not find opening quote");
00174     return; //Invalid/incomplete response
00175   }
00176   pStart++; //Point to first char of response
00177   char* pEnd = (char*) strchr(pStart,'\"');
00178   if(pEnd==NULL)
00179   {
00180     WARN("Could not find closing quote");
00181     return; //Invalid/incomplete response
00182   }
00183   m_responseMtx.lock();
00184   if(m_maxResultLength == 0) //No pending command
00185   {
00186     WARN("No pending command");
00187     m_responseMtx.unlock();
00188     return;
00189   }
00190   size_t cpyLen = MIN( pEnd - pStart, m_maxResultLength - 1 );
00191   memcpy((void*)m_result, pStart, cpyLen);
00192   m_result[cpyLen] = '\0';
00193   DBG("Got USSD response: %s", m_result);
00194   m_responseMtx.unlock();
00195   m_responseSphre.release(); //Signal user thread that response is ready
00196 }