local fork

Dependencies:   Socket USBHostWANDongle_bleedingedge lwip-sys lwip

Dependents:   Encrypted

Fork of VodafoneUSBModem_bleedingedge by Donatien Garnier

Revision:
8:04b6a042595f
Parent:
0:3b2f052c333b
Child:
12:66dc2c8eba2d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sms/SMSInterface.cpp	Tue Jun 26 13:44:59 2012 +0000
@@ -0,0 +1,390 @@
+/* SMSInterface.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 __DEBUG__ 4
+#ifndef __MODULE__
+#define __MODULE__ "SMSInterface.cpp"
+#endif
+
+#include "core/fwk.h"
+
+#include "SMSInterface.h"
+
+#include <cstdio>
+
+#define DEFAULT_TIMEOUT 10000
+
+SMSInterface::SMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL), /*m_msgCount(0),*/
+m_msgRefListCount(0), m_needsUpdate(true), m_state(SMS_IDLE)
+{
+  m_pIf->registerEventsHandler(this); //Add us to the unsolicited result codes handlers
+}
+
+int SMSInterface::init()
+{
+  DBG("Set format");
+  //Set Text mode format
+  int ret = m_pIf->executeSimple("AT+CMGF=1", NULL, DEFAULT_TIMEOUT);
+  if(ret != OK)
+  {
+    return NET_PROTOCOL;
+  }
+
+  DBG("Setup new messages indication");
+  //Setup new messages indication
+  ret = m_pIf->executeSimple("AT+CNMI=2,1,0,0,0", NULL, DEFAULT_TIMEOUT);
+  if(ret != OK)
+  {
+    return NET_PROTOCOL;
+  }
+
+  DBG("Try to fetch inbox");
+  m_inboxMtx.lock();
+  if( m_needsUpdate )
+  {
+    ret = updateInbox(); //Fetch existing messages references
+    if(ret)
+    {
+      m_inboxMtx.unlock();
+      return NET_PROTOCOL;
+    }
+  }
+  m_inboxMtx.unlock();
+
+  DBG("Initialization done");
+  return OK;
+}
+
+int SMSInterface::send(const char* number, const char* message)
+{
+  if( strlen(number) > 16 )
+  {
+    return NET_INVALID; //Number too long to match 3GPP spec
+  }
+
+  int ret;
+
+  //Prepare infos
+  m_state = SMS_SEND_CMD_SENT;
+  m_msg = (char*) message;
+
+  DBG("Send SM");
+  //Send command
+  char cmd[32];
+  std::sprintf(cmd, "AT+CMGS=\"%s\"", number);
+  ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
+
+  if( (ret != OK) || (m_state != SMS_CMD_PROCESSED) )
+  {
+    WARN("ret %d, state %d", ret, m_state);
+    m_state = SMS_IDLE;
+    return NET_PROTOCOL;
+  }
+
+  DBG("SM sent");
+  m_state = SMS_IDLE;
+  return OK;
+}
+
+
+int SMSInterface::get(char* number, char* message, size_t maxLength)
+{
+  if( maxLength < 1  )
+  {
+    return NET_INVALID; //Buffer too short
+  }
+
+  int ret;
+
+  DBG("Get next message");
+  m_inboxMtx.lock();
+  if(m_msgRefListCount == 0 && m_needsUpdate)
+  {
+    ret = updateInbox();
+    if (ret)
+    {
+      m_inboxMtx.unlock();
+      return ret;
+    }
+  }
+
+  if(m_msgRefListCount == 0)
+  {
+    m_inboxMtx.unlock();
+    return NET_EMPTY; //No message to read
+  }
+
+  //Prepare infos
+  m_state = SMS_GET_CMD_SENT;
+  m_msisdn = (char*) number;
+  m_msg = (char*) message;
+  m_maxMsgLength = maxLength;
+
+  DBG("Get SMS");
+  //List command
+  char cmd[32];
+  std::sprintf(cmd, "AT+CMGR=%d", m_msgRefList[0]);
+  ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
+  if( ret != OK )
+  {
+    WARN("AT+CMGR returned %d", ret);
+    m_state = SMS_IDLE;
+    m_inboxMtx.unlock();
+    return NET_PROTOCOL;
+  }
+
+  if (m_state != SMS_CMD_PROCESSED)
+  {
+    m_state = SMS_IDLE;
+    m_inboxMtx.unlock();
+    return NET_EMPTY;
+  }
+
+  m_state = SMS_IDLE;
+
+  DBG("Deleting message");
+  //Delete message from outbox
+  std::sprintf(cmd, "AT+CMGD=%d", m_msgRefList[0]);
+  ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
+  if(ret != OK)
+  {
+    m_inboxMtx.unlock();
+    WARN("Could not delete message");
+  }
+
+  //Remove message from list
+  std::memmove(m_msgRefList, m_msgRefList+1, m_msgRefListCount-1);
+  m_msgRefListCount--;
+
+  m_inboxMtx.unlock();
+
+  return OK;
+}
+
+
+int SMSInterface::getCount(size_t* pCount)
+{
+  int ret;
+
+  m_inboxMtx.lock();
+  if( m_needsUpdate )
+  {
+    ret = updateInbox();
+    if(ret)
+    {
+      m_inboxMtx.unlock();
+      return NET_PROTOCOL;
+    }
+  }
+
+  *pCount = m_msgRefListCount;
+  m_inboxMtx.unlock();
+
+  return OK;
+}
+
+
+/*virtual*/ int SMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
+{
+  if(m_state == SMS_SEND_CMD_SENT)
+  {
+    if( std::sscanf(line, "+CMGS: %*d") == 0 )
+    {
+      DBG("SM sent");
+      m_state = SMS_CMD_PROCESSED;
+    }
+  }
+  else if(m_state == SMS_GET_CMD_SENT)
+  {
+    DBG("Header: %s", line);
+    if( std::sscanf(line, "+CMGR: %*[^,],\"%16[^\"]\"", m_msisdn) == 1 ) //Get message ref
+    {
+      m_state = SMS_GET_HDR_RECEIVED;
+    }
+  }
+  else if(m_state == SMS_GET_HDR_RECEIVED)
+  {
+    DBG("Message: %s", line);
+    size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 );
+    std::memcpy( m_msg, line, cpyLen );
+    m_msg[cpyLen] = '\0';
+    m_state = SMS_CMD_PROCESSED;
+  }
+  else if(m_state == SMS_GET_COUNT_CMD_SENT)
+  {
+    DBG("Header: %s", line);
+    int msgRef;
+    if( std::sscanf(line, "+CMGL: %d", &msgRef) == 1 )
+    {
+      m_state = SMS_GET_COUNT_HDR_RECEIVED;
+      //Add message to list
+      if(m_msgRefListCount < MAX_SM)
+      {
+        m_msgRefList[m_msgRefListCount] = msgRef;
+      }
+      m_msgRefListCount++; //Always count message
+      DBG("m_msgRefListCount=%d",m_msgRefListCount);
+    }
+  }
+  else if(m_state == SMS_GET_COUNT_HDR_RECEIVED)
+  {
+    DBG("Message (debug only): %s", line); //For debug only
+    m_state = SMS_GET_COUNT_CMD_SENT;
+  }
+  return OK;
+}
+
+/*virtual*/ int SMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
+{
+  if(m_state == SMS_SEND_CMD_SENT)
+  {
+    char* crPtr = strchr(m_msg, CR);
+    if(crPtr != NULL)
+    {
+      int crPos = crPtr - m_msg;
+      //Replace m_inputBuf[crPos] with null-terminating char
+      m_msg[crPos] = '\x0';
+
+      //If there is a CR char, split message there
+
+      //Do print the message
+      int ret = pInst->sendData(m_msg);
+      if(ret)
+      {
+        return ret;
+      }
+
+      char cr[2] = {CR, '\0'};
+      ret = pInst->sendData(cr);
+      if(ret)
+      {
+        return ret;
+      }
+
+      m_msg += crPos;
+
+      if(m_msg[0] == LF)
+      {
+        m_msg++; //Discard LF char as well
+      }
+
+      return NET_MOREINFO;
+    }
+    else
+    {
+      //Do print the message
+      pInst->sendData(m_msg);
+      return OK;
+    }
+  }
+
+  return OK;
+}
+
+/*virtual*/ bool SMSInterface::isATCodeHandled(const char* atCode) //Is this AT code handled
+{
+  DBG("AT code is %s", atCode);
+  if( strcmp("+CMTI", atCode) == 0 )
+  {
+    return true;
+  }
+
+  DBG("Not handled");
+  return false;
+}
+
+/*virtual*/ void SMSInterface::onDispatchStart()
+{
+
+
+}
+
+/*virtual*/ void SMSInterface::onDispatchStop()
+{
+
+}
+
+/*virtual*/ void SMSInterface::onEvent(const char* atCode, const char* evt)
+{
+  if( strcmp("+CMTI", atCode) != 0 )
+  {
+    return; //Not supported
+  }
+
+  DBG("Unsollicited result code: %s - %s", atCode, evt);
+
+  //Get index
+  int msgRef;
+  if( std::sscanf(evt, "\"SM\",%d", &msgRef) == 1 )
+  {
+    DBG("Adding message to list (ref %d)", msgRef);
+    m_inboxMtx.lock();
+    //Add message to list
+    if(m_msgRefListCount < MAX_SM)
+    {
+      m_msgRefList[m_msgRefListCount] = msgRef;
+    }
+    else
+    {
+      m_needsUpdate = true;
+    }
+    m_msgRefListCount++; //Always count message
+    m_inboxMtx.unlock();
+  }
+}
+
+int SMSInterface::updateInbox()
+{
+  //Get memory indexes of unread messages
+  m_state = SMS_GET_COUNT_CMD_SENT;
+
+  DBG("Updating inbox");
+  m_msgRefListCount = 0; //Reset list
+
+  int ret = m_pIf->execute("AT+CMGL=\"REC UNREAD\"", this, NULL, DEFAULT_TIMEOUT);
+  if( ret != OK )
+  {
+    WARN("AT+CMGL returned %d", ret);
+    m_state = SMS_IDLE;
+    m_msgRefListCount = 0; //List could be invalid
+    m_needsUpdate = true;
+    return NET_PROTOCOL;
+  }
+
+  DBG("%d incoming messages in inbox", m_msgRefListCount);
+
+  if( m_msgRefListCount > MAX_SM )
+  {
+    m_needsUpdate = true;
+  }
+  else
+  {
+    m_needsUpdate = false;
+  }
+
+  m_state = SMS_IDLE;
+
+  return OK;
+}
+
+