]> git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/net/cellular/CellularModem/sms/CDMASMSInterface.cpp
Merge commit '1fe4406f374291ab2e86e95a97341fd9c475fcb8'
[tmk_keyboard.git] / tmk_core / tool / mbed / mbed-sdk / libraries / net / cellular / CellularModem / sms / CDMASMSInterface.cpp
1 /* CDMASMSInterface.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
20 #define __DEBUG__ 0
21 #ifndef __MODULE__
22 #define __MODULE__ "CDMASMSInterface.cpp"
23 #endif
24
25 #include "core/fwk.h"
26
27 #include "CDMASMSInterface.h"
28
29 #include <cstdio>
30 #include <cstring>
31
32 using std::sscanf;
33
34 #define DEFAULT_TIMEOUT 10000
35
36 CDMASMSInterface::CDMASMSInterface(ATCommandsInterface* pIf) : m_pIf(pIf), m_msg(NULL), m_maxMsgLength(0), m_msisdn(NULL)
37 {
38 }
39
40 int CDMASMSInterface::init()
41 {
42 m_state = SMS_IDLE;
43
44 DBG("Get number of messages in the different inboxes");
45 int ret = updateInbox();
46 if(ret)
47 {
48 return NET_PROTOCOL;
49 }
50
51 DBG("Initialization done");
52 return OK;
53 }
54
55 int CDMASMSInterface::send(const char* number, const char* message)
56 {
57 if( strlen(number) > 16 )
58 {
59 return NET_INVALID; //Number too long
60 }
61
62 int ret;
63
64 //Prepare infos
65 m_state = SMS_SEND_CMD_SENT;
66
67 bool intlNumber=(number[0]=='+'); //If the number starts with the + sign, replace it with 011 instead (int'l dialing code in the US)
68
69 DBG("Send SM");
70 //Send command
71 char cmd[32+strlen(message)];
72 std::sprintf(cmd, "AT!SSMS=0,%s%s,,\"%s\"",intlNumber?"011":"", intlNumber?(number+1):number, message); //Send with normal priority
73 ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
74
75 if(ret != OK)
76 {
77 WARN("ret %d", ret);
78 m_state = SMS_IDLE;
79 return NET_PROTOCOL;
80 }
81
82 DBG("Check status");
83 m_txState = SMS_PENDING;
84
85 int tries = 10;
86 while(tries--)
87 {
88 m_state = SMS_GET_TX_STATUS_CMD_SENT;
89 ret = m_pIf->execute("AT!SSMS?", this, NULL, DEFAULT_TIMEOUT);
90 if(ret)
91 {
92 m_state = SMS_IDLE;
93 return ret;
94 }
95 m_state = SMS_IDLE;
96 if(m_txState == SMS_PENDING) //Wait more
97 {
98 Thread::wait(1000);
99 continue;
100 }
101 else if(m_txState == SMS_FAILED)
102 {
103 ERR("The modem could not send the SM");
104 return NET_CONN; //Probably a conenction issue, the user can retry
105 }
106 else
107 {
108 break;
109 }
110 }
111 if(!tries)
112 {
113 ERR("The is still trying to send the SM");
114 return NET_TIMEOUT;
115 }
116 return OK;
117 }
118
119
120 int CDMASMSInterface::get(char* number, char* message, size_t maxLength)
121 {
122 if( maxLength < 1 )
123 {
124 return NET_INVALID; //Buffer too short
125 }
126
127 int ret;
128
129 DBG("Get next message");
130 if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0)
131 {
132 DBG("Message list count is 0 and needs updating. Running updateInbox.");
133 ret = updateInbox();
134 if (ret)
135 {
136 return ret;
137 }
138 }
139
140 if( (m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]) == 0)
141 {
142 DBG("Message list count is 0");
143 return NET_EMPTY; //No message to read
144 }
145
146 //Determine which index to use : 3 (read), then 1 (urgent), then 2 (regular)
147 int index;
148 if(m_msgInListsCount[2])
149 {
150 index = 3;
151 }
152 else if(m_msgInListsCount[0])
153 {
154 index = 1;
155 }
156 else //if(m_msgInListsCount[1])
157 {
158 index = 2;
159 }
160
161 //Prepare infos
162 m_state = SMS_GET_CMD_SENT;
163 m_msisdn = (char*) number;
164 m_msg = (char*) message;
165 m_maxMsgLength = maxLength;
166 m_headersToRead = 3;
167
168 m_msisdn[0] = '\0';
169
170 DBG("Get SMS");
171 //Read command
172 char cmd[32];
173 std::sprintf(cmd, "AT!GSMS?%d,1", index); //1 is the oldest message
174 ret = m_pIf->execute(cmd, this, NULL, DEFAULT_TIMEOUT);
175 if( ret != OK )
176 {
177 WARN("AT!GSMS returned %d", ret);
178 m_state = SMS_IDLE;
179 return NET_PROTOCOL;
180 }
181
182 //If message is not read, it will be put at the end of the read list
183 int item;
184 if( index != 3 )
185 {
186 //Decrement count in relevant list
187 m_msgInListsCount[index-1]--;
188 //Increment count in read list
189 m_msgInListsCount[3-1]++;
190 item = m_msgInListsCount[3-1];
191 //Normally item should be equal to 1 as we'd have read any older messages first
192 if( item != 1 )
193 {
194 WARN("Still some older messages pending in the read inbox");
195 }
196 }
197 else
198 {
199 //The item is still the oldest one
200 item = 1;
201 }
202
203 DBG("Deleting message");
204 //Delete message from inbox
205 std::sprintf(cmd, "AT!DSMS=3"/*,%d", item*/); //FIXME why doesn't that work when specifying the index??
206 ret = m_pIf->executeSimple(cmd, NULL, DEFAULT_TIMEOUT);
207 if(ret != OK)
208 {
209 ERR("Could not delete message");
210 }
211 else
212 {
213 //Now we can decrease the number of read messages
214 m_msgInListsCount[3-1]--;
215 }
216
217 if (m_state != SMS_CMD_PROCESSED)
218 {
219 WARN("Message could not be retrieved properly");
220 m_state = SMS_IDLE;
221 return NET_EMPTY;
222 }
223
224 m_state = SMS_IDLE;
225
226 return OK;
227 }
228
229
230 int CDMASMSInterface::getCount(size_t* pCount)
231 {
232 int ret = updateInbox();
233 if(ret)
234 {
235 return NET_PROTOCOL;
236 }
237
238 *pCount = m_msgInListsCount[0] + m_msgInListsCount[1] + m_msgInListsCount[2]; //Urgent messages + regular messages + read messages
239
240 return OK;
241 }
242
243
244 /*virtual*/ int CDMASMSInterface::onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
245 {
246 if(m_state == SMS_SEND_CMD_SENT)
247 {
248 DBG("SMS Send: %s", line);
249 }
250 else if(m_state == SMS_GET_TX_STATUS_CMD_SENT)
251 {
252 if(!strcmp(line, "sent"))
253 {
254 m_txState = SMS_SENT;
255 m_state = SMS_CMD_PROCESSED;
256 }
257 else if(!strcmp(line, "failed"))
258 {
259 m_txState = SMS_FAILED;
260 m_state = SMS_CMD_PROCESSED;
261 }
262 else if(!strcmp(line, "none"))
263 {
264 m_txState = SMS_NONE;
265 m_state = SMS_CMD_PROCESSED;
266 }
267 else if(!strcmp(line, "pending"))
268 {
269 m_txState = SMS_PENDING;
270 m_state = SMS_CMD_PROCESSED;
271 }
272 }
273 else if(m_state == SMS_GET_CMD_SENT)
274 {
275 DBG("Header: %s", line);
276
277 if(m_msisdn[0]=='\0')
278 {
279 sscanf(line, "From: %16s", m_msisdn);
280 }
281
282 m_headersToRead--;
283
284 if(m_headersToRead==0) //End of headers
285 {
286 if(m_msisdn[0]!='\0') //Checks that the incoming number has been retrieved
287 {
288 m_state = SMS_GET_HDR_RECEIVED;
289 }
290 else
291 {
292 m_state = SMS_IDLE; //Error, signal it
293 }
294 }
295 }
296 else if(m_state == SMS_GET_HDR_RECEIVED)
297 {
298 DBG("Message: %s", line);
299 size_t cpyLen = MIN( std::strlen(line), m_maxMsgLength - 1 );
300 std::memcpy( m_msg, line, cpyLen );
301 m_msg[cpyLen] = '\0';
302 m_state = SMS_CMD_PROCESSED;
303 }
304 else if(m_state == SMS_GET_COUNT_CMD_SENT)
305 {
306 DBG("Inbox: %s", line);
307 int index;
308 size_t count;
309 if((strlen(line) > 16) && sscanf(line + 16, "{Index = %d}: %d", &index, &count) == 2)
310 {
311 if((index > 0) && (index <=4))
312 {
313 m_msgInListsCount[index-1] = count;
314 }
315 if(index == 4)
316 {
317 m_state = SMS_CMD_PROCESSED;
318 }
319 }
320 }
321 return OK;
322 }
323
324 /*virtual*/ int CDMASMSInterface::onNewEntryPrompt(ATCommandsInterface* pInst)
325 {
326 return OK;
327 }
328
329
330 int CDMASMSInterface::updateInbox()
331 {
332 //Get number of unread/read messages
333
334 DBG("Updating inbox");
335 m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Reset counts
336
337 //Get counts
338 m_state = SMS_GET_COUNT_CMD_SENT;
339 int ret = m_pIf->execute("AT!CNTSMS", this, NULL, DEFAULT_TIMEOUT);
340 if( ret != OK )
341 {
342 WARN("AT!CNTSMS returned %d", ret);
343 m_msgInListsCount[0] = m_msgInListsCount[1] = m_msgInListsCount[2] = m_msgInListsCount[3] = 0; //Invalidate counts
344 m_state = SMS_IDLE;
345 return NET_PROTOCOL;
346 }
347
348 return OK;
349 }
350
Imprint / Impressum