b9e0ea0 Merge commit '7fa9d8bdea3773d1195b04d98fcf27cf48ddd81d' as 'tool/mbed/mbed-sdk' 7fa9d8b Squashed 'tool/mbed/mbed-sdk/' content from commit 7c21ce5 git-subtree-dir: tmk_core git-subtree-split: b9e0ea08cb940de20b3610ecdda18e9d8cd7c552
351 lines
8.1 KiB
C++
351 lines
8.1 KiB
C++
/* CDMASMSInterface.cpp */
|
|
/* Copyright (C) 2012 mbed.org, MIT License
|
|
*
|
|
* 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__ 0
|
|
#ifndef __MODULE__
|
|
#define __MODULE__ "CDMASMSInterface.cpp"
|
|
#endif
|
|
|
|
#include "core/fwk.h"
|
|
|
|
#include "CDMASMSInterface.h"
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
using std::sscanf;
|
|
|
|
#define DEFAULT_TIMEOUT 10000
|
|
|
|
CDMASMSInterface::CDMASMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL)
|
|
{
|
|
}
|
|
|
|
int CDMASMSInterface::init()
|
|
{
|
|
m_state = SMS_IDLE;
|
|
|
|
DBG("Get number of messages in the different inboxes");
|
|
int ret = updateInbox();
|
|
if(ret)
|
|
{
|
|
return NET_PROTOCOL;
|
|
}
|
|
|
|
DBG("Initialization done");
|
|
return OK;
|
|
}
|
|
|
|
int CDMASMSInterface::send(const char* number, const char* message)
|
|
{
|
|
if( strlen(number) > 16 )
|
|
{
|
|
return NET_INVALID; //Number too long
|
|
}
|
|
|
|
int ret;
|
|
|
|
//Prepare infos
|
|
m_state = SMS_SEND_CMD_SENT;
|
|
|
|
bool intlNumber=(number[0]=='+'); //If the number starts with the + sign, replace it with 011 instead (int'l dialing code in the US)
|
|
|
|
DBG("Send SM");
|
|
//Send command
|
|
char cmd[32+strlen(message)];
|
|
std::sprintf(cmd, "AT!SSMS=0,%s%s,,\"%s\"",intlNumber?"011":"", intlNumber?(number+1):number, message); //Send with normal priority
|
|
ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
|
|
|
|
if(ret != OK)
|
|
{
|
|
WARN("ret %d", ret);
|
|
m_state = SMS_IDLE;
|
|
return NET_PROTOCOL;
|
|
}
|
|
|
|
DBG("Check status");
|
|
m_txState = SMS_PENDING;
|
|
|
|
int tries = 10;
|
|
while(tries--)
|
|
{
|
|
m_state = SMS_GET_TX_STATUS_CMD_SENT;
|
|
ret = m_pIf->execute("AT!SSMS?", this, NULL, DEFAULT_TIMEOUT);
|
|
if(ret)
|
|
{
|
|
m_state = SMS_IDLE;
|
|
return ret;
|
|
}
|
|
m_state = SMS_IDLE;
|
|
if(m_txState == SMS_PENDING) //Wait more
|
|
{
|
|
Thread::wait(1000);
|
|
continue;
|
|
}
|
|
else if(m_txState == SMS_FAILED)
|
|
{
|
|
ERR("The modem could not send the SM");
|
|
return NET_CONN; //Probably a conenction issue, the user can retry
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(!tries)
|
|
{
|
|
ERR("The is still trying to send the SM");
|
|
return NET_TIMEOUT;
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
|
|
int CDMASMSInterface::get(char* number, char* message, size_t maxLength)
|
|
{
|
|
if( maxLength < 1 )
|
|
{
|
|
return NET_INVALID; //Buffer too short
|
|
}
|
|
|
|
int ret;
|
|
|
|
DBG("Get next message");
|
|
if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0)
|
|
{
|
|
DBG("Message list count is 0 and needs updating. Running updateInbox.");
|
|
ret = updateInbox();
|
|
if (ret)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0)
|
|
{
|
|
DBG("Message list count is 0");
|
|
return NET_EMPTY; //No message to read
|
|
}
|
|
|
|
//Determine which index to use : 3 (read), then 1 (urgent), then 2 (regular)
|
|
int index;
|
|
if(m_msgInListsCount[2])
|
|
{
|
|
index = 3;
|
|
}
|
|
else if(m_msgInListsCount[0])
|
|
{
|
|
index = 1;
|
|
}
|
|
else //if(m_msgInListsCount[1])
|
|
{
|
|
index = 2;
|
|
}
|
|
|
|
//Prepare infos
|
|
m_state = SMS_GET_CMD_SENT;
|
|
m_msisdn = (char*) number;
|
|
m_msg = (char*) message;
|
|
m_maxMsgLength = maxLength;
|
|
m_headersToRead = 3;
|
|
|
|
m_msisdn[0] = '\0';
|
|
|
|
DBG("Get SMS");
|
|
//Read command
|
|
char cmd[32];
|
|
std::sprintf(cmd, "AT!GSMS?%d,1", index); //1 is the oldest message
|
|
ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
|
|
if( ret != OK )
|
|
{
|
|
WARN("AT!GSMS returned %d", ret);
|
|
m_state = SMS_IDLE;
|
|
return NET_PROTOCOL;
|
|
}
|
|
|
|
//If message is not read, it will be put at the end of the read list
|
|
int item;
|
|
if( index != 3 )
|
|
{
|
|
//Decrement count in relevant list
|
|
m_msgInListsCount[index-1]--;
|
|
//Increment count in read list
|
|
m_msgInListsCount[3-1]++;
|
|
item = m_msgInListsCount[3-1];
|
|
//Normally item should be equal to 1 as we'd have read any older messages first
|
|
if( item != 1 )
|
|
{
|
|
WARN("Still some older messages pending in the read inbox");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//The item is still the oldest one
|
|
item = 1;
|
|
}
|
|
|
|
DBG("Deleting message");
|
|
//Delete message from inbox
|
|
std::sprintf(cmd, "AT!DSMS=3"/*,%d", item*/); //FIXME why doesn't that work when specifying the index??
|
|
ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
|
|
if(ret != OK)
|
|
{
|
|
ERR("Could not delete message");
|
|
}
|
|
else
|
|
{
|
|
//Now we can decrease the number of read messages
|
|
m_msgInListsCount[3-1]--;
|
|
}
|
|
|
|
if (m_state != SMS_CMD_PROCESSED)
|
|
{
|
|
WARN("Message could not be retrieved properly");
|
|
m_state = SMS_IDLE;
|
|
return NET_EMPTY;
|
|
}
|
|
|
|
m_state = SMS_IDLE;
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
int CDMASMSInterface::getCount(size_t* pCount)
|
|
{
|
|
int ret = updateInbox();
|
|
if(ret)
|
|
{
|
|
return NET_PROTOCOL;
|
|
}
|
|
|
|
*pCount = m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]; //Urgent messages + regular messages + read messages
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
/*virtual*/ int CDMASMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
|
|
{
|
|
if(m_state == SMS_SEND_CMD_SENT)
|
|
{
|
|
DBG("SMS Send: %s", line);
|
|
}
|
|
else if(m_state == SMS_GET_TX_STATUS_CMD_SENT)
|
|
{
|
|
if(!strcmp(line, "sent"))
|
|
{
|
|
m_txState = SMS_SENT;
|
|
m_state = SMS_CMD_PROCESSED;
|
|
}
|
|
else if(!strcmp(line, "failed"))
|
|
{
|
|
m_txState = SMS_FAILED;
|
|
m_state = SMS_CMD_PROCESSED;
|
|
}
|
|
else if(!strcmp(line, "none"))
|
|
{
|
|
m_txState = SMS_NONE;
|
|
m_state = SMS_CMD_PROCESSED;
|
|
}
|
|
else if(!strcmp(line, "pending"))
|
|
{
|
|
m_txState = SMS_PENDING;
|
|
m_state = SMS_CMD_PROCESSED;
|
|
}
|
|
}
|
|
else if(m_state == SMS_GET_CMD_SENT)
|
|
{
|
|
DBG("Header: %s", line);
|
|
|
|
if(m_msisdn[0]=='\0')
|
|
{
|
|
sscanf(line, "From: %16s", m_msisdn);
|
|
}
|
|
|
|
m_headersToRead--;
|
|
|
|
if(m_headersToRead==0) //End of headers
|
|
{
|
|
if(m_msisdn[0]!='\0') //Checks that the incoming number has been retrieved
|
|
{
|
|
m_state = SMS_GET_HDR_RECEIVED;
|
|
}
|
|
else
|
|
{
|
|
m_state = SMS_IDLE; //Error, signal it
|
|
}
|
|
}
|
|
}
|
|
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("Inbox: %s", line);
|
|
int index;
|
|
size_t count;
|
|
if((strlen(line) > 16) && sscanf(line + 16, "{Index = %d}: %d", &index, &count) == 2)
|
|
{
|
|
if((index > 0) && (index <=4))
|
|
{
|
|
m_msgInListsCount[index-1] = count;
|
|
}
|
|
if(index == 4)
|
|
{
|
|
m_state = SMS_CMD_PROCESSED;
|
|
}
|
|
}
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
/*virtual*/ int CDMASMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
|
|
{
|
|
return OK;
|
|
}
|
|
|
|
|
|
int CDMASMSInterface::updateInbox()
|
|
{
|
|
//Get number of unread/read messages
|
|
|
|
DBG("Updating inbox");
|
|
m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Reset counts
|
|
|
|
//Get counts
|
|
m_state = SMS_GET_COUNT_CMD_SENT;
|
|
int ret = m_pIf->execute("AT!CNTSMS", this, NULL, DEFAULT_TIMEOUT);
|
|
if( ret != OK )
|
|
{
|
|
WARN("AT!CNTSMS returned %d", ret);
|
|
m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Invalidate counts
|
|
m_state = SMS_IDLE;
|
|
return NET_PROTOCOL;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|