]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/net/cellular/UbloxUSBModem/UbloxUSBCDMAModem.cpp
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[tmk_keyboard.git] / tool / mbed / mbed-sdk / libraries / net / cellular / UbloxUSBModem / UbloxUSBCDMAModem.cpp
1 /* UbloxUSBCDMAModem.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__ 4
21 #ifndef __MODULE__
22 #define __MODULE__ "UbloxUSBCDMAModem.cpp"
23 #endif
24
25 #include "core/fwk.h"
26
27 #include "UbloxUSBCDMAModem.h"
28 #include "UbloxCDMAModemInitializer.h"
29 #include "USBHost.h"
30
31 #define USE_ONE_PORT 1
32
33 UbloxUSBCDMAModem::UbloxUSBCDMAModem(PinName powerGatingPin /*= NC*/, bool powerGatingOnWhenPinHigh /* = true*/, int serial /* 0 */) : m_dongle(),
34 m_stream(m_dongle.getSerial(serial)),
35 m_at(&m_stream),
36 m_sms(&m_at), m_ppp(&m_stream),
37 m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false),
38 m_powerGatingPin(powerGatingPin), m_powerGatingOnWhenPinHigh(powerGatingOnWhenPinHigh)
39 {
40 USBHost* host = USBHost::getHostInst();
41 m_dongle.addInitializer(new UbloxCDMAModemInitializer(host));
42 if( m_powerGatingPin != NC )
43 {
44 power(false); //Dongle will have to be powered on manually
45 }
46 }
47
48 class CSSProcessor : public IATCommandsProcessor
49 {
50 public:
51 CSSProcessor() : status(STATUS_REGISTERING)
52 {
53
54 }
55 enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK };
56 REGISTERING_STATUS getStatus()
57 {
58 return status;
59 }
60 private:
61 virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
62 {
63 char b;
64 char bc[3] = "";
65 int sid = 99999;
66
67 //if( sscanf(line, "%*d, %c", &r) == 1 )
68 if(sscanf(line, "%*s %c,%2s,%d", &b,bc,&sid)==3)
69 {
70 if(strcmp("Z", bc) == 0)
71 status = STATUS_REGISTERING;
72 else
73 status = STATUS_OK;
74 }
75 return OK;
76 }
77 virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
78 {
79 return OK;
80 }
81 volatile REGISTERING_STATUS status;
82 };
83
84 int UbloxUSBCDMAModem::connect(const char* apn, const char* user, const char* password)
85 {
86 if( !m_ipInit )
87 {
88 m_ipInit = true;
89 m_ppp.init();
90 }
91 m_ppp.setup(user, password, DEFAULT_MSISDN_CDMA);
92
93 int ret = init();
94 if(ret)
95 {
96 return ret;
97 }
98
99 #if USE_ONE_PORT
100 m_smsInit = false; //SMS status reset
101 //m_ussdInit = false; //USSD status reset
102 //m_linkMonitorInit = false; //Link monitor status reset
103 #endif
104
105 ATCommandsInterface::ATResult result;
106
107 if(apn != NULL)
108 {
109 char cmd[48];
110 sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
111 ret = m_at.executeSimple(cmd, &result);
112 DBG("Result of command: Err code=%d", ret);
113 DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
114 DBG("APN set to %s", apn);
115 }
116
117
118 //Connect
119 DBG("Connecting");
120 #if USE_ONE_PORT
121 m_at.close(); // Closing AT parser
122 m_atOpen = false; //Will need to be reinitialized afterwards
123 #endif
124
125 DBG("Connecting PPP");
126
127 ret = m_ppp.connect();
128 DBG("Result of connect: Err code=%d", ret);
129 return ret;
130 }
131
132
133 int UbloxUSBCDMAModem::disconnect()
134 {
135 DBG("Disconnecting from PPP");
136 int ret = m_ppp.disconnect();
137 if(ret)
138 {
139 ERR("Disconnect returned %d, still trying to disconnect", ret);
140 }
141
142 //Ugly but leave dongle time to recover
143 Thread::wait(500);
144
145 #if USE_ONE_PORT
146 ATCommandsInterface::ATResult result;
147 DBG("Starting AT thread");
148 ret = m_at.open();
149 if(ret)
150 {
151 return ret;
152 }
153 #endif
154
155 DBG("Trying to hangup");
156
157 #if 0 //Does not appear to work
158 int tries = 10;
159 do
160 {
161 ret = m_at.executeSimple("+++", &result, 1000);
162 DBG("Result of command: Err code=%d\n", ret);
163 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
164 } while(tries-- && ret);
165 if(!ret)
166 {
167 ret = m_at.executeSimple("ATH", &result);
168 DBG("Result of command: Err code=%d\n", ret);
169 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
170 }
171 #endif
172
173 #if USE_ONE_PORT
174 //Reinit AT parser
175 ret = m_at.init();
176 DBG("Result of command: Err code=%d\n", ret);
177 if(ret)
178 {
179 m_at.close(); // Closing AT parser
180 DBG("AT Parser closed, could not complete disconnection");
181 return NET_TIMEOUT;
182 }
183
184 #if 0
185 m_at.close(); // Closing AT parser
186 DBG("AT Parser closed");
187 #endif
188 #endif
189 return OK;
190 }
191
192 int UbloxUSBCDMAModem::sendSM(const char* number, const char* message)
193 {
194 int ret = init();
195 if(ret)
196 {
197 return ret;
198 }
199
200 if(!m_smsInit)
201 {
202 ret = m_sms.init();
203 if(ret)
204 {
205 return ret;
206 }
207 m_smsInit = true;
208 }
209
210 ret = m_sms.send(number, message);
211 if(ret)
212 {
213 return ret;
214 }
215
216 return OK;
217 }
218
219 int UbloxUSBCDMAModem::getSM(char* number, char* message, size_t maxLength)
220 {
221 int ret = init();
222 if(ret)
223 {
224 return ret;
225 }
226
227 if(!m_smsInit)
228 {
229 ret = m_sms.init();
230 if(ret)
231 {
232 return ret;
233 }
234 m_smsInit = true;
235 }
236
237 ret = m_sms.get(number, message, maxLength);
238 if(ret)
239 {
240 return ret;
241 }
242
243 return OK;
244 }
245
246 int UbloxUSBCDMAModem::getSMCount(size_t* pCount)
247 {
248 int ret = init();
249 if(ret)
250 {
251 return ret;
252 }
253
254 if(!m_smsInit)
255 {
256 ret = m_sms.init();
257 if(ret)
258 {
259 return ret;
260 }
261 m_smsInit = true;
262 }
263
264 ret = m_sms.getCount(pCount);
265 if(ret)
266 {
267 return ret;
268 }
269
270 return OK;
271 }
272
273 ATCommandsInterface* UbloxUSBCDMAModem::getATCommandsInterface()
274 {
275 return &m_at;
276 }
277
278 int UbloxUSBCDMAModem::power(bool enable)
279 {
280 if( m_powerGatingPin == NC )
281 {
282 return NET_INVALID; //A pin name has not been provided in the constructor
283 }
284
285 if(!enable) //Will force components to re-init
286 {
287 cleanup();
288 }
289
290 DigitalOut powerGatingOut(m_powerGatingPin);
291 powerGatingOut = m_powerGatingOnWhenPinHigh?enable:!enable;
292
293 return OK;
294 }
295
296 bool UbloxUSBCDMAModem::power()
297 {
298 if( m_powerGatingPin == NC )
299 {
300 return true; //Assume power is always on
301 }
302
303 DigitalOut powerGatingOut(m_powerGatingPin);
304 return m_powerGatingOnWhenPinHigh?powerGatingOut:!powerGatingOut;
305 }
306
307 int UbloxUSBCDMAModem::init()
308 {
309 if( !m_dongleConnected )
310 {
311 if(!power())
312 {
313 //Obviously cannot initialize the dongle if it is disconnected...
314 ERR("Power is off");
315 return NET_INVALID;
316 }
317 m_dongleConnected = true;
318 while( !m_dongle.connected() )
319 {
320 m_dongle.tryConnect();
321 Thread::wait(100);
322 }
323 }
324
325 if(m_atOpen)
326 {
327 return OK;
328 }
329
330 DBG("Starting AT thread if needed");
331 int ret = m_at.open();
332 if(ret)
333 {
334 return ret;
335 }
336
337 DBG("Sending initialisation commands");
338 ret = m_at.init();
339 if(ret)
340 {
341 return ret;
342 }
343
344 if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAC200)
345 {
346 INFO("Using a UBLOX C200 Dongle");
347 }
348 else
349 {
350 WARN("Using an Unknown Dongle");
351 }
352
353 ATCommandsInterface::ATResult result;
354
355 //Wait for network registration
356 CSSProcessor cssProcessor;
357 do
358 {
359 DBG("Waiting for network registration");
360 ret = m_at.execute("AT+CSS?", &cssProcessor, &result);
361 DBG("Result of command: Err code=%d\n", ret);
362 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
363 if(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING)
364 {
365 Thread::wait(3000);
366 }
367 } while(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING);
368
369 m_atOpen = true;
370
371 return OK;
372 }
373
374 int UbloxUSBCDMAModem::cleanup()
375 {
376 if(m_ppp.isConnected())
377 {
378 WARN("Data connection is still open"); //Try to encourage good behaviour from the user
379 m_ppp.disconnect();
380 }
381
382 m_smsInit = false;
383 // m_linkMonitorInit = false;
384 //We don't reset m_ipInit as PPPIPInterface::init() only needs to be called once
385
386 if(m_atOpen)
387 {
388 m_at.close();
389 m_atOpen = false;
390 }
391
392 m_dongle.disconnect();
393 m_dongleConnected = false;
394
395 return OK;
396 }
397
398
Imprint / Impressum