USSDInterface.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* USSDInterface.cpp */
  2. /* Copyright (C) 2012 mbed.org, MIT License
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  5. * and associated documentation files (the "Software"), to deal in the Software without restriction,
  6. * including without limitation the rights to use, copy, modify, merge, publish, distribute,
  7. * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in all copies or
  11. * substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
  14. * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  16. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  18. */
  19. #define __DEBUG__ 0
  20. #ifndef __MODULE__
  21. #define __MODULE__ "USSDInterface.cpp"
  22. #endif
  23. #include "core/fwk.h"
  24. #include "USSDInterface.h"
  25. #include <cstdio>
  26. #define DEFAULT_TIMEOUT 10000
  27. #define USSD_TIMEOUT 15000
  28. USSDInterface::USSDInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_responseMtx(), m_responseSphre(1), m_result(NULL), m_maxResultLength(0)
  29. {
  30. m_responseSphre.wait(0); //Take ownership of the semaphore
  31. m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
  32. }
  33. int USSDInterface::init()
  34. {
  35. DBG("Initialization done");
  36. return OK;
  37. }
  38. int USSDInterface::send(const char* command, char* result, size_t maxLength)
  39. {
  40. if (strlen(command) > 20) //Prevent buffer overflow
  41. {
  42. return NET_TOOSMALL;
  43. }
  44. m_responseMtx.lock();
  45. m_result = result;
  46. m_maxResultLength = maxLength;
  47. m_responseMtx.unlock();
  48. m_responseSphre.wait(0); //Make sure there is not a pending result that needs to be discarded
  49. DBG("Send USSD command & register for unsolicited result codes");
  50. //Send USSD command to the network
  51. char cmd[32];
  52. std::sprintf(cmd, "AT+CUSD=1,\"%s\"", command);
  53. int ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
  54. if( ret != OK )
  55. {
  56. return NET_PROTOCOL;
  57. }
  58. //Did we already get a response (3GPP rev < 6) ?
  59. //Now wait for response
  60. int res = m_responseSphre.wait(USSD_TIMEOUT);
  61. //Reset data
  62. m_responseMtx.lock();
  63. m_result = NULL;
  64. m_maxResultLength = 0;
  65. m_responseMtx.unlock();
  66. if(res <= 0)
  67. {
  68. DBG("No result received");
  69. ret = m_pIf->executeSimple("AT+CUSD=2", NULL, DEFAULT_TIMEOUT); //Cancel command
  70. if( ret != OK )
  71. {
  72. return NET_PROTOCOL;
  73. }
  74. return NET_TIMEOUT;
  75. }
  76. DBG("Result received: %s", result);
  77. return OK;
  78. }
  79. /*virtual*/ int USSDInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
  80. {
  81. const char* pSemicol = strchr(line, ':');
  82. if( ( (pSemicol - line) != strlen("+CUSD") ) || ( memcmp(line, "+CUSD", strlen("+CUSD")) != 0) )
  83. {
  84. WARN("Unknown code");
  85. return OK;
  86. }
  87. const char* pData = NULL;
  88. if( pSemicol != NULL ) //Split the identifier & the result code (if it exists)
  89. {
  90. pData = pSemicol + 1;
  91. if(pData[0]==' ')
  92. {
  93. pData++; //Suppress whitespace
  94. }
  95. processResult(pData);
  96. }
  97. return OK;
  98. }
  99. /*virtual*/ int USSDInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
  100. {
  101. return OK;
  102. }
  103. /*virtual*/ bool USSDInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
  104. {
  105. DBG("AT code is %s", atCode);
  106. if( strcmp("+CUSD", atCode) == 0 )
  107. {
  108. return true;
  109. }
  110. DBG("Not handled");
  111. return false;
  112. }
  113. /*virtual*/ void USSDInterface::onDispatchStart()
  114. {
  115. }
  116. /*virtual*/ void USSDInterface::onDispatchStop()
  117. {
  118. }
  119. /*virtual*/ char* USSDInterface::getEventsEnableCommand()
  120. {
  121. return NULL; //No need to disable events here
  122. }
  123. /*virtual*/ char* USSDInterface::getEventsDisableCommand()
  124. {
  125. return NULL; //No need to re-enable events here
  126. }
  127. /*virtual*/ void USSDInterface::onEvent(const char* atCode, const char* evt)
  128. {
  129. if( strcmp("+CUSD", atCode) != 0 )
  130. {
  131. WARN("Wrong AT Code");
  132. return; //Not supported
  133. }
  134. processResult(evt);
  135. }
  136. void USSDInterface::processResult(const char* data)
  137. {
  138. char* pStart = (char*) strchr(data,'\"');
  139. if(pStart==NULL)
  140. {
  141. WARN("Could not find opening quote");
  142. return; //Invalid/incomplete response
  143. }
  144. pStart++; //Point to first char of response
  145. char* pEnd = (char*) strchr(pStart,'\"');
  146. if(pEnd==NULL)
  147. {
  148. WARN("Could not find closing quote");
  149. return; //Invalid/incomplete response
  150. }
  151. m_responseMtx.lock();
  152. if(m_maxResultLength == 0) //No pending command
  153. {
  154. WARN("No pending command");
  155. m_responseMtx.unlock();
  156. return;
  157. }
  158. size_t cpyLen = MIN( pEnd - pStart, m_maxResultLength - 1 );
  159. memcpy((void*)m_result, pStart, cpyLen);
  160. m_result[cpyLen] = '\0';
  161. DBG("Got USSD response: %s", m_result);
  162. m_responseMtx.unlock();
  163. m_responseSphre.release(); //Signal user thread that response is ready
  164. }