├── .gitignore
├── README.md
├── gprs.h
└── gprs.c
/.gitignore:
--------------------------------------------------------------------------------
1 | epsilon.ses
2 |
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | GPRS module for lwIP
2 |
3 | Require lwIP 1.5.x and the sio interface implementation.
4 |
5 | Supported and tested modem typs :
6 |
7 | - Cineterion Mc55i
8 | - SIMCOM SIM800
9 |
10 |
11 |
--------------------------------------------------------------------------------
/gprs.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file gprs.h
3 | * @brief Gprs interface for lwIP/ppp_new()
4 | *
5 | * lwipopts.h Requirement :
6 | *
7 | * - PPP_SUPPORT 1
8 | * - PPP_INPROC_OWNTHREAD 0
9 | * - GPRS_SUUPPORT 1
10 | *
11 | * Other requirement :
12 | *
13 | * - Architecture dependent sio implementation.
14 | * - gprs_arch_modem_on() & gprs_arch_modem_off() to turn the modem on
15 | * off.
16 | *
17 | * For other configuration options check gprs.h
18 | *
19 | *
20 | * Example to be include in your main after lwIP initialization :
21 | *
22 | * ...
23 | * gprs_t * gprs;
24 | *
25 | * ppp_init(); // Initialize the PPP sub systems
26 | * gprs = gprs_new(3); // Create a new gprs interface on serial port # 3
27 | * gprs_open(gprs); // Start the gprs connection
28 | * ...
29 | *
30 | *
31 | * @author Mario Viara
32 | * @version 1.00
33 | *
34 | * @copyright Copyright Mario Viara 2015 - License Open Source (LGPL)
35 | * This is a free software and is opened for education, research and commercial
36 | * developments under license policy of following terms:
37 | * - This is a free software and there is NO WARRANTY.
38 | * - No restriction on use. You can use, modify and redistribute it for personal,
39 | * non-profit or commercial product UNDER YOUR RESPONSIBILITY.
40 | * - Redistributions of source code must retain the above copyright notice.
41 | *
42 | */
43 | #ifndef GPRS_H
44 | #define GPRS_H
45 | #include "lwip/opt.h"
46 | #include "lwip/sio.h"
47 | #include "lwip/timers.h"
48 | #include "lwip/tcpip.h"
49 | #include "netif/ppp/ppp.h"
50 | #include "netif/ppp/pppos.h"
51 |
52 | #ifdef __cplusplus
53 | extern "C" {
54 | #endif
55 |
56 |
57 | /**
58 | * As default GPRS is not configured
59 | */
60 | #ifndef GPRS_SUPPORT
61 | #define GPRS_SUPPORT 0
62 | #endif
63 |
64 |
65 | /**
66 | * Include only if configured
67 | */
68 | #if GPRS_SUPPORT
69 |
70 |
71 | /**
72 | * If set to 1 the modem TYPE is read before starting the connection
73 | */
74 | #ifndef GPRS_TYPE
75 | #define GPRS_TYPE 0
76 | #endif
77 |
78 | /**
79 | * If set to 1 the sim CCID read before starting the connection
80 | */
81 | #ifndef GPRS_ICCID
82 | #define GPRS_ICCID 0
83 | #endif
84 |
85 | /**
86 | * GPRS debug options
87 | */
88 | #ifndef GPRS_DEBUG
89 | #define GPRS_DEBUG LWIP_DBG_OFF
90 | #endif
91 |
92 |
93 | /**
94 | * Modem debug options
95 | */
96 | #ifndef MODEM_DEBUG
97 | #define MODEM_DEBUG LWIP_DBG_OFF
98 | #endif
99 |
100 |
101 |
102 | /**
103 | * Is set GPRS will run in own thread otherwise the function
104 | * gprs_input() must be called when data are available from the serial port.
105 | */
106 | #ifndef GPRS_OWNTHREAD
107 | #define GPRS_OWNTHREAD 1
108 | #endif
109 |
110 | /**
111 | * If multi threading is used define the platform specific thread options.
112 | */
113 | #if GPRS_OWNTHREAD
114 | #ifndef GPRS_THREAD_NAME
115 | #define GPRS_THREAD_NAME "GPRS"
116 | #endif
117 |
118 | #ifndef GPRS_THREAD_STACKSIZE
119 | #define GPRS_THREAD_STACKSIZE 0
120 | #endif
121 |
122 | #ifndef GPRS_THREAD_PRIO
123 | #define GPRS_THREAD_PRIO 1
124 | #endif
125 |
126 | #endif
127 |
128 |
129 | /**
130 | * Serial statistics
131 | */
132 | #ifndef GPRS_SERIAL_STAT
133 | #define GPRS_SERIAL_STAT 0
134 | #endif
135 |
136 |
137 | /**
138 | * Buffer size for the reply buffer of the modem
139 | */
140 | #ifndef GPRS_REPLY_BUFFER_SIZE
141 | #define GPRS_REPLY_BUFFER_SIZE 128
142 | #endif
143 |
144 | /**
145 | * How much milliseconds the modem must be power off
146 | */
147 | #ifndef GPRS_MODEM_OFF_TIME
148 | #define GPRS_MODEM_OFF_TIME 1500
149 | #endif
150 |
151 | /**
152 | * Delay before using the modem after power on
153 | */
154 | #ifndef GPRS_MODEM_ON_DELAY
155 | #define GPRS_MODEM_ON_DELAY 2500
156 | #endif
157 |
158 | /**
159 | * Buffer size of serial interface
160 | */
161 | #ifndef GPRS_MODEM_BUFFER_SIZE
162 | #define GPRS_MODEM_BUFFER_SIZE 1024
163 | #endif
164 |
165 | /**
166 | * Delay between command during init
167 | */
168 | #ifndef GPRS_INIT_COMMAND_DELAY
169 | #define GPRS_INIT_COMMAND_DELAY 500
170 | #endif
171 |
172 | /**
173 | * Timeout in milliseconds for modem commands.
174 | */
175 | #ifndef GPRS_COMMAND_TIMEOUT
176 | #define GPRS_COMMAND_TIMEOUT 500
177 | #endif
178 |
179 |
180 | /**
181 | * Timeout in milliseconds for data connection
182 | */
183 | #ifndef GPRS_DIAL_TIMEOUT
184 | #define GPRS_DIAL_TIMEOUT 120000
185 | #endif
186 |
187 | /**
188 | * Timeout for network registration
189 | */
190 | #define GPRS_REGISTRATION_TIMEOUT 60000
191 |
192 |
193 | /**
194 | * Timeout for modem alive
195 | */
196 | #define GPRS_ALIVE_TIMEOUT 10000
197 | /**
198 | * Operator APN
199 | */
200 | #ifndef GPRS_APN
201 | #define GPRS_APN "internet"
202 | #endif
203 |
204 | /**
205 | * If set the APN can be changed in runtime
206 | */
207 | #ifndef GPRS_RUNTIME_APN
208 | #define GPRS_RUNTIME_APN 0
209 | #endif
210 |
211 |
212 | /**
213 | * If required define the maximum size of the APN
214 | */
215 | #if GPRS_RUNTIME_APN
216 | #ifndef GPRS_APN_SIZE
217 | #define GPRS_APN_SIZE 16
218 | #endif
219 | #endif
220 |
221 |
222 | /**
223 | * MC55i require a minimum delay of 100 milliseconds between command
224 | * set to 0 to disable this feature.
225 | */
226 | #ifndef GPRS_COMMAND_DELAY
227 | #define GPRS_COMMAND_DELAY 1000
228 | #endif
229 |
230 |
231 |
232 | /**
233 | * Not registered
234 | *
235 | * - no SIM card available
236 | * - no PIN entered
237 | * - no valid PLMN entry found on the SIM
238 | */
239 | #define GPRS_NETWORK_ERROR 0
240 |
241 | /**
242 | * Registered in the home network
243 | */
244 | #define GPRS_NETWORK_HOME 1
245 |
246 | /**
247 | * Not registered searching for new operator
248 | */
249 | #define GPRS_NETWORK_SEARCH 2
250 |
251 | /**
252 | * Not registered registration denied
253 | */
254 | #define GPRS_NETWORK_DENIED 3
255 |
256 | /**
257 | * Not registered unknown state
258 | */
259 | #define GPRS_NETWORK_UNKNOWN 4
260 |
261 | /**
262 | * Registered in roaming network
263 | */
264 | #define GPRS_NETWORK_ROAMING 5
265 |
266 | #define GPRS_NETWORK_INVALID 0xFF
267 |
268 | #define GSM_CSQ_INVALID 0xFF
269 |
270 | /**
271 | * Modem command state
272 | */
273 | typedef enum
274 | {
275 | /**
276 | * Not managed state
277 | */
278 | MODEM_STATE_NONE,
279 |
280 | /**
281 | * Check the echo of the sent command.
282 | */
283 | MODEM_STATE_ECHO,
284 |
285 | /**
286 | * Wait for EOL after echo
287 | */
288 | MODEM_STATE_WAITEOL,
289 |
290 | /**
291 | * check reply from the modem
292 | */
293 | MODEM_STATE_REPLY
294 |
295 | } modem_state_t;
296 |
297 | /**
298 | * GPRS Modem state
299 | */
300 | typedef enum
301 | {
302 | GPRS_STATE_MODEM_OFF,
303 | GPRS_STATE_MODEM_ON,
304 | GPRS_STATE_MODEM_WAKEUP,
305 | GPRS_STATE_MODEM_ALIVE,
306 | GPRS_STATE_MODEM_IDENTIFY,
307 | GPRS_STATE_MODEM_IMEI,
308 | #if GPRS_ICCID
309 | GPRS_STATE_MODEM_CCID,
310 | #endif
311 | GPRS_STATE_GSM_NETWORK,
312 | GPRS_STATE_GPRS_NETWORK,
313 | GPRS_STATE_MODEM_INIT,
314 | GPRS_STATE_MODEM_DIAL,
315 | GPRS_STATE_CONNECTING,
316 | GPRS_STATE_CONNECTED,
317 | GPRS_STATE_DISCONNECTED,
318 | } gprs_state_t;
319 |
320 |
321 | /**
322 | * Structure to hold GPRS data
323 | */
324 | typedef struct
325 | {
326 | /**
327 | * Sio device number
328 | */
329 | u8_t device;
330 |
331 | /**
332 | * GSM signal quality
333 | */
334 | u8_t csq;
335 |
336 | /**
337 | * CGREG flag if set the GPRS network registration status is checked
338 | */
339 | u8_t cgreg;
340 |
341 | /**
342 | * GPRS network registration code
343 | */
344 | u8_t gprsNetwork;
345 |
346 | /**
347 | * Set when the dial command have CONNECT as reply
348 | */
349 | u8_t connected;
350 |
351 | /**
352 | * GSM network registration code
353 | */
354 | u8_t gsmNetwork;
355 |
356 | /**
357 | * Set from the user to enable roaming
358 | */
359 | u8_t roaming;
360 |
361 | /**
362 | * Time of the last change state
363 | */
364 | u32_t stateTime;
365 |
366 | #if GPRS_COMMAND_DELAY > 0
367 | u8_t delayedEol;
368 |
369 | /**
370 | * Time of the last sent command.
371 | */
372 | u32_t commandTime;
373 |
374 | /**
375 | * Command to be sent after the delay
376 | */
377 | const char * delayedCommand;
378 | #endif
379 |
380 | /**
381 | * Point to last sent command
382 | */
383 | const char * sentCommand;
384 |
385 | /**
386 | * Sio device descriptor
387 | */
388 | sio_fd_t fd;
389 |
390 | /**
391 | * Internal state machine
392 | */
393 | gprs_state_t state;
394 |
395 | /**
396 | * Modem state machine
397 | */
398 | modem_state_t modem;
399 |
400 | /**
401 | * Modem state machine number of processed char
402 | */
403 | unsigned modemCount;
404 |
405 | /**
406 | * Internal machine sub state code
407 | */
408 | int subState;
409 |
410 | /**
411 | * Buffer for reply from the modem
412 | */
413 | char replyBuffer[GPRS_REPLY_BUFFER_SIZE];
414 |
415 | /**
416 | * Current pointer in the replyBuffer
417 | */
418 | char * replyPtr;
419 |
420 | #if GPRS_RUNTIME_APN
421 | /**
422 | * Runtime APN
423 | */
424 | char apn[GPRS_APN_SIZE];
425 | #endif
426 |
427 | /**
428 | * Modem IMEI
429 | */
430 | char imei[15+1];
431 |
432 | #if GPRS_TYPE
433 | /**
434 | * Modem TYPE
435 | */
436 | char type[32+1];
437 | #endif
438 |
439 | #if GPRS_ICCID
440 | /**
441 | * Sim CCID
442 | */
443 | char ccid[20+1];
444 |
445 | char ccidChksum;
446 | #endif
447 |
448 | /**
449 | * PPP structure
450 | */
451 | ppp_pcb *pcb;
452 |
453 | /**
454 | * PP network interface
455 | */
456 | struct netif pppif;
457 |
458 |
459 | #if GPRS_OWNTHREAD
460 | /**
461 | * GPRS thread
462 | */
463 | sys_thread_t thread;
464 |
465 | /**
466 | * Serial recv buffer
467 | */
468 | u8_t recvBuffer[GPRS_MODEM_BUFFER_SIZE];
469 |
470 | /**
471 | * Recv buffer length
472 | */
473 | u32_t recvLen;
474 |
475 | /**
476 | * semaphore to process received data
477 | */
478 | sys_sem_t recvSem;
479 | #endif
480 |
481 |
482 | #if GPRS_SERIAL_STAT
483 | u32_t rcvdBtes;
484 | u32_t sentBytes;
485 | #endif
486 |
487 | } gprs_t;
488 |
489 |
490 | #if GPRS_OWNTHREAD == 0
491 | /**
492 | * Called when data are available from the serial port
493 | *
494 | * @param gprs- Gprs descriptor.
495 | * @param data- Pointer to the data
496 | * @param length - Length of the data.
497 | */
498 | void gprs_input(gprs_t * gprs,u8_t * data,u32_t length);
499 | #endif
500 |
501 | /**
502 | * Create a GPRS Control modem
503 | *
504 | * @param device Device number for sio functions.
505 | *
506 | * @return A pointer to GPRS control or 0 on error.
507 | */
508 | gprs_t * gprs_new(u8_t device);
509 |
510 | /**
511 | * Open a new GPRS connection
512 | *
513 | * @param gprs - GPRS control returned from a call of gprs_new()
514 | */
515 | void gprs_open(gprs_t * gprs);
516 |
517 | /**
518 | * Close a GPRS connection
519 | *
520 | * @param gprs - GPRS control returned from a call of gprs_new()
521 | */
522 | void gprs_close(gprs_t * gprs);
523 |
524 |
525 | /**
526 | * Disconnect the GPRS
527 | *
528 | * @param gprs - GPRS control returned from a call of gprs_new()
529 | */
530 | void gprs_disconnect(gprs_t * gprs);
531 |
532 |
533 | /**
534 | * Connect the GPRS
535 | *
536 | * @param gprs - GPRS control returned from a call of gprs_new()
537 | */
538 | void gprs_connect(gprs_t * gprs);
539 |
540 | /**
541 | * Return the current network status
542 | *
543 | * @return Current network status
544 | */
545 | int gprs_get_network(gprs_t *gprs);
546 |
547 | /**
548 | * Get the roaming flag
549 | *
550 | * If set connection are made also in roaming.
551 | *
552 | * @return roaming flag
553 | */
554 | u8_t gprs_get_roaming(gprs_t * gprs);
555 |
556 | /**
557 | * Set the roaming flag.
558 | *
559 | * If not 0 connection are also made in roaming
560 | *
561 | * @param roaming - Roaming flag.
562 | */
563 | void gprs_set_roaming(gprs_t * gprs,u8_t roaming);
564 |
565 | /**
566 | * Get the GSM modem IMEI.
567 | *
568 | * @return IMEI
569 | */
570 | const char * gprs_get_imei(gprs_t * gprs);
571 |
572 | /**
573 | * Get the GSM signal quality before connection is initiated.
574 | *
575 | * @return csq (0 - 31)
576 | */
577 | u8_t gprs_get_csq(gprs_t * gprs);
578 |
579 | #if GPRS_RUNTIME_APN
580 |
581 | /**
582 | * Set the APN
583 | *
584 | * @param gprs - GPRS control
585 | * @param name - Name of the new apn
586 | *
587 | * @see GPRS_APN_SIZE
588 | */
589 | void gprs_set_apn(gprs_t *gprs,const char *name);
590 |
591 | /**
592 | * Get the current APN
593 | *
594 | * @return The current APN
595 | */
596 | const char * gprs_get_apn(gprs_t * gprs);
597 |
598 | #endif
599 |
600 | /**
601 | * System depending function to turn on the modem
602 | *
603 | * @param device - Sio device number.
604 | */
605 | #ifndef gprs_arch_modem_on
606 | void gprs_arch_modem_on(u8_t device);
607 | #endif
608 |
609 | /**
610 | * System depending function to turo off the modem
611 | *
612 | * @param device - Sio device number.
613 | */
614 |
615 | #ifndef gprs_arch_modem_off
616 | void gprs_arch_modem_off(u8_t device);
617 | #endif
618 |
619 |
620 | #if GPRS_SERIAL_STAT
621 | /**
622 | * Get serial statistics from gprs.
623 | *
624 | * @param sent - Number of sent bytes.
625 | * @param rcvd - Number of received bytes
626 | */
627 | void gprs_get_stat(gprs_t * gprs,u32_t * sent,u32_t * rcvd);
628 | #endif
629 | #endif /* GPRS_SUPPPORT */
630 |
631 | #if GPRS_TYPE
632 | /**
633 | * Return the GSM modem TYPE
634 | *
635 | * @return TYPE
636 | */
637 | const char * gprs_get_type(gprs_t * gprs);
638 | #endif
639 |
640 | #if GPRS_ICCID
641 | /**
642 | * Return the SIM ICCID
643 | *
644 | * The CCID is a unique number that identify a SIM up to 22 digit length filled with hex digit F,
645 | *
646 | * @param check - Will set to the removed check digit (ASCII code 0x30-0x39 or 0 if not valid)
647 | *
648 | * @return The SIM ICCID without filler and check digit if valid.
649 | */
650 | const char * gprs_get_iccid(gprs_t * gprs,char *check);
651 | #endif
652 |
653 | #ifdef __cplusplus
654 | }
655 | #endif
656 |
657 | #endif /* GPRS_H */
658 |
--------------------------------------------------------------------------------
/gprs.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @file gprs.c
3 | * @brief Gprs interface for lwIP/ppp_new()
4 | *
5 | *
6 | * @author Mario Viara
7 | * @version 1.00
8 | *
9 | * @copyright Copyright Mario Viara 2014 - License Open Source (LGPL)
10 | * This is a free software and is opened for education, research and commercial
11 | * developments under license policy of following terms:
12 | * - This is a free software and there is NO WARRANTY.
13 | * - No restriction on use. You can use, modify and redistribute it for personal,
14 | * non-profit or commercial product UNDER YOUR RESPONSIBILITY.
15 | * - Redistributions of source code must retain the above copyright notice.
16 | *
17 | * Supported and tested modem types :
18 | */
19 | #include
20 | #include "gprs.h"
21 |
22 | #include "lwip/pbuf.h"
23 | #include "lwip/dns.h"
24 |
25 |
26 | /**
27 | * Compile only if enabled
28 | */
29 | #if GPRS_SUPPORT
30 |
31 | #define TIMEOUT(x) sys_timeout(x,gprs_timeout,gprs)
32 | #define UNTIMEOUT() sys_untimeout(gprs_timeout,gprs)
33 | #define TIMEOUT1(x) sys_timeout(x,gprs_command_delayed,gprs)
34 | #define UNTIMEOUT1() sys_untimeout(gprs_command_delayed,gprs)
35 |
36 | static void gprs_input_internal(gprs_t * gprs,u8_t * data,u32_t length);
37 | static void gprs_do_start(gprs_t * gprs);
38 |
39 |
40 | /**
41 | * Safe strcpy
42 | */
43 | static void sstrcpy(char *dest,const char * source,size_t size)
44 | {
45 | size_t length = strlen(source);
46 | size_t i;
47 |
48 | if (length + 1 > size)
49 | {
50 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: sstrcpy() String too short size=%u required=%u\n",size,length+1));
51 | LWIP_ASSERT("gprs: sstrcpy()",length + 1 <= size);
52 | length = size - 1;
53 |
54 | }
55 |
56 | for (i = 0 ; i < length ; i++)
57 | {
58 | *dest ++ = *source++;
59 | }
60 |
61 | *dest = 0;
62 |
63 |
64 | }
65 |
66 | /**
67 | * Safe strcat
68 | */
69 | static void sstrcat(char *dest,const char*source,size_t size)
70 | {
71 | size_t length = strlen(dest);
72 |
73 | if (length < size)
74 | {
75 | sstrcpy(dest+length,source,size - length);
76 | }
77 | else
78 | {
79 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: sstrcat() String overflow short size=%u length=%u",size,length));
80 | LWIP_ASSERT("gprs: sstrcat()",length < size);
81 |
82 | }
83 | }
84 | /**
85 | * Called when a gprs timeout expire
86 | *
87 | * @param arg - Gprs connection
88 | */
89 | static void gprs_timeout(void * arg);
90 |
91 |
92 | /**
93 | * Set the new state of the modem machine.
94 | */
95 | static void modem_set_state(gprs_t * gprs,modem_state_t state)
96 | {
97 | gprs->modem = state;
98 |
99 | // LWIP_DEBUGF(GPRS_DEBUG,("gprs: modem_set_state: %d\n",gprs->modem));
100 | gprs->modemCount = 0;
101 |
102 | }
103 |
104 | /**
105 | * No reply received
106 | */
107 | #define MODEM_REPLY_NONE 0
108 |
109 | /**
110 | * OK reply received
111 | */
112 | #define MODEM_REPLY_OK 1
113 |
114 | /**
115 | * Error reply received
116 | */
117 | #define MODEM_REPLY_ERROR 2
118 |
119 | /**
120 | * Check reply from the modem.
121 | *
122 | * @return 0 - No valid reply received
123 | * @return 1 - OK received
124 | * @return 2 - Error received.
125 | */
126 | static int modem_check_reply(gprs_t * gprs,const u8_t *data,u32_t length,void (*callback)(gprs_t * gprs,const char *reply))
127 | {
128 | u8_t c;
129 | int reply = MODEM_REPLY_NONE;
130 |
131 |
132 | while (length-- > 0 && reply == MODEM_REPLY_NONE)
133 | {
134 | c = *data++;
135 |
136 | switch (gprs->modem)
137 | {
138 | default:
139 | case MODEM_STATE_NONE:
140 | break;
141 |
142 | case MODEM_STATE_ECHO:
143 | if (gprs->sentCommand[gprs->modemCount] == c)
144 | {
145 | if (gprs->sentCommand[++gprs->modemCount] < 32)
146 | {
147 |
148 | modem_set_state(gprs,MODEM_STATE_WAITEOL);
149 | }
150 | }
151 | else
152 | {
153 | gprs->modemCount = 0;
154 | }
155 | break;
156 |
157 | case MODEM_STATE_WAITEOL:
158 | if (c < 32)
159 | {
160 | //LWIP_DEBUGF(GPRS_DEBUG,("Modem_check_reply: echo received\n"));
161 | modem_set_state(gprs,MODEM_STATE_REPLY);
162 | }
163 | break;
164 |
165 | case MODEM_STATE_REPLY:
166 | if (c < 32)
167 | {
168 | if (gprs->modemCount > 0)
169 | {
170 | gprs->replyBuffer[gprs->modemCount] = 0;
171 | LWIP_DEBUGF(MODEM_DEBUG,("gprs: Modem reply '%s'\n",gprs->replyBuffer));
172 | gprs->modemCount = 0;
173 | if (!strcmp(gprs->replyBuffer,"OK"))
174 | {
175 | #if GPRS_COMMAND_DELAY > 0
176 | gprs->commandTime = sys_now();
177 | #endif
178 | //LWIP_DEBUGF(MODEM_DEBUG,("modem_check_reply: OK received\n"));
179 | reply = MODEM_REPLY_OK;
180 | }
181 | else if(!strncmp(gprs->replyBuffer,"ERROR",5))
182 | {
183 | #if GPRS_COMMAND_DELAY > 0
184 | gprs->commandTime = sys_now();
185 | #endif
186 | LWIP_DEBUGF(MODEM_DEBUG,("gprs: Modem reply ERROR ERROR received\n"));
187 | reply = MODEM_REPLY_ERROR;
188 | }
189 | else
190 | {
191 |
192 | if (callback != 0)
193 | {
194 | (*callback)(gprs,gprs->replyBuffer);
195 | }
196 | }
197 |
198 | }
199 | }
200 | else
201 | {
202 | if (gprs->modemCount < sizeof(gprs->replyBuffer) - 1)
203 | {
204 | gprs->replyBuffer[gprs->modemCount++] = c;
205 | }
206 | else
207 | {
208 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: GPRS_REPLY_BUFFER_SIZE too short"));
209 | }
210 |
211 | }
212 | break;
213 | }
214 | }
215 |
216 | return reply;
217 | }
218 |
219 | /**
220 | * Check if we have received a OK from the modem.
221 | *
222 | * @return 1 if OK is received.
223 | */
224 | static int modem_check_ok_reply(gprs_t * gprs,const u8_t * data,u32_t length)
225 | {
226 | return modem_check_reply(gprs,data,length,0) == MODEM_REPLY_OK;
227 |
228 | }
229 |
230 | /**
231 | * Output data to the serial port
232 | *
233 | * @param data - Data to be sent
234 | * @param length - Length of ata
235 | */
236 | static void gprs_serial_output(gprs_t * gprs,u8_t * data,u32_t length)
237 | {
238 | u32_t sent;
239 |
240 | sent = sio_write(gprs->fd,data,length);
241 |
242 | if (sent != length)
243 | {
244 | LWIP_DEBUGF(MODEM_DEBUG,("gprs: send: failed lenth=%u\n",(unsigned)length));
245 | }
246 |
247 | #if GPRS_SERIAL_STAT
248 | gprs->sentBytes += length;
249 | #endif
250 | }
251 |
252 | /**
253 | * Set the state of the gprs machine.
254 | *
255 | * @param newState - New state.
256 | */
257 | static void gprs_set_state(gprs_t * gprs,gprs_state_t newState)
258 | {
259 | u32_t now;
260 |
261 | if (gprs->state != newState)
262 | {
263 | now = sys_now();
264 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: new state %d elapsed %lu\n",newState,(unsigned long)(now - gprs->stateTime)));
265 |
266 |
267 | gprs->stateTime = now;
268 | gprs->state = newState;
269 | gprs->subState = 0;
270 | }
271 |
272 |
273 | }
274 |
275 | /**
276 | * Return the number of milliseconds elapsed form the start of the current state.
277 | *
278 | * @return elapsed milliseconds.
279 | */
280 | static u32_t gprs_state_elapsed(gprs_t * gprs)
281 | {
282 | return sys_now() - gprs->stateTime;
283 |
284 | }
285 |
286 |
287 | /**
288 | * PPP callback
289 | */
290 | static void gprs_callback(ppp_pcb *pcb,int err_code,void *ctx)
291 | {
292 | gprs_t * gprs = (gprs_t *)ctx;
293 |
294 | (void)pcb;
295 |
296 | if (err_code)
297 | {
298 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: Callback: disconnected (%d)\n",err_code));
299 |
300 | switch (err_code)
301 | {
302 | case PPPERR_USER:
303 | gprs_set_state(gprs, GPRS_STATE_DISCONNECTED);
304 | break;
305 |
306 | default:
307 | gprs_do_start(gprs);
308 | break;
309 | }
310 |
311 | }
312 | else
313 | {
314 | // UNTIMEOUT();
315 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: gprs_callback: connected\n"));
316 |
317 | //LWIP_DEBUGF(GPRS_DEBUG,("IP %s\n",ip_ntoa(&gprs->pcb->addrs.our_ipaddr)));
318 | //LWIP_DEBUGF(GPRS_DEBUG,("MASK %s\n",ip_ntoa(&gprs->pcb->addrs.netmask)));
319 | //LWIP_DEBUGF(GPRS_DEBUG,("DNS1 %s\n",ip_ntoa(&gprs->pcb->addrs.dns1)));
320 | //LWIP_DEBUGF(GPRS_DEBUG,("DNS2 %s\n",ip_ntoa(&gprs->pcb->addrs.dns2)));
321 | gprs_set_state(gprs, GPRS_STATE_CONNECTED);
322 | ppp_set_default(gprs->pcb);
323 |
324 | /*
325 | * Update DNS if configured
326 | */
327 | #if LWIP_DNS
328 | //dns_setserver(0,&gprs->pcb->addrs.dns1);
329 | //dns_setserver(1,&gprs->pcb->addrs.dns2);
330 |
331 | #endif
332 | }
333 |
334 | }
335 |
336 | #if GPRS_OWNTHREAD
337 | /**
338 | * Callback function called in the lwIP thread to process incoming data from the serial port
339 | */
340 | static void gprs_input_callback(void *arg)
341 | {
342 | gprs_t * gprs = (gprs_t *)arg;
343 |
344 | /* LWIP_DEBUGF(GPRS_DEBUG,("gprs_input_callback: %u\n",p->len));*/
345 | gprs_input_internal(gprs,(u8_t *)gprs->recvBuffer,gprs->recvLen);
346 | sys_sem_signal(&gprs->recvSem);
347 | }
348 |
349 |
350 | /**
351 | * Dedicated thread to read data from the serial port.
352 | */
353 | static void gprs_thread(void *arg)
354 | {
355 | gprs_t * gprs = (gprs_t *)arg;
356 |
357 |
358 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: Thread: Started on device %d size %u\n",gprs->device,GPRS_MODEM_BUFFER_SIZE));
359 |
360 |
361 | for (;;)
362 | {
363 | gprs->recvLen = sio_read(gprs->fd,(u8_t *)gprs->recvBuffer,GPRS_MODEM_BUFFER_SIZE);
364 |
365 | if (gprs->recvLen > 0)
366 | {
367 | #if GPRS_SERIAL_STAT
368 | gprs->rcvdBtes += gprs->recvLen;
369 | #endif
370 |
371 | if (tcpip_callback(gprs_input_callback,(void *)gprs) != ERR_OK)
372 | {
373 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: Thread tcpip_callback() failed\n"));
374 | }
375 | else
376 | {
377 | sys_sem_wait(&gprs->recvSem);
378 | }
379 |
380 | }
381 |
382 | }
383 | }
384 | #else
385 | /**
386 | * Must be called from the user when data are available from the serial port.
387 | *
388 | */
389 | void gprs_input(gprs_t * gprs,u8_t * data,u32_t length)
390 | {
391 | gprs_input_internal(gprs,data,length);
392 | }
393 |
394 | #endif
395 |
396 |
397 | /**
398 | * PPOS output function
399 | */
400 | static u32_t gprs_pppos_output(ppp_pcb *pcb,u8_t * data,u32_t length,void *ctx)
401 | {
402 | gprs_t * gprs = (gprs_t *)ctx;
403 |
404 | (void)pcb;
405 |
406 | gprs_serial_output(gprs,data,length);
407 |
408 | return length;
409 |
410 | }
411 | /**
412 | * Create a new gprs connection
413 | *
414 | * @param device - Serial device number.
415 | */
416 | gprs_t * gprs_new(u8_t device)
417 | {
418 | gprs_t * gprs;
419 |
420 | gprs = (gprs_t *) mem_malloc(sizeof(gprs_t));
421 |
422 | if (gprs != 0)
423 | {
424 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: new on device %d size %u\n",device,(unsigned)sizeof(gprs_t)));
425 | gprs->device = device;
426 | gprs->fd = sio_open(device);
427 | gprs->stateTime = sys_now();
428 |
429 | #if GPRS_COMMAND_DELAY > 0
430 | gprs->commandTime = gprs->stateTime;
431 | #endif
432 |
433 | gprs->imei[0] = 0;
434 |
435 | gprs->csq = GSM_CSQ_INVALID;
436 |
437 |
438 | if (gprs->fd != 0)
439 | {
440 | gprs->pcb = pppos_create(&gprs->pppif,gprs_pppos_output,gprs_callback,(void *)gprs);
441 |
442 | if (gprs->pcb)
443 |
444 | {
445 | gprs_set_state(gprs,GPRS_STATE_DISCONNECTED);
446 |
447 | #if GPRS_RUNTIME_APN
448 | gprs_set_apn(gprs,GPRS_APN);
449 | #endif
450 |
451 | #if GPRS_OWNTHREAD
452 | sys_sem_new(&gprs->recvSem,0);
453 | gprs->thread = sys_thread_new(GPRS_THREAD_NAME,gprs_thread,(void *)gprs,GPRS_THREAD_STACKSIZE,GPRS_THREAD_PRIO);
454 | #endif
455 | }
456 | else
457 | {
458 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: pppos__create failed\n"));
459 | mem_free(gprs);
460 | gprs = (gprs_t *)0;
461 | }
462 | }
463 | else
464 | {
465 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: _new failed sio_open(%d)\n",device));
466 | mem_free(gprs);
467 | gprs = (gprs_t *)0;
468 | }
469 | }
470 | else
471 | {
472 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: malloc failed\n"));
473 | }
474 |
475 | return gprs;
476 | }
477 |
478 |
479 | /**
480 | * Send a string to the modem.
481 | *
482 | * @param cmd - String to be sent
483 | * @param eol - If not 0 is sent as line delimiter.
484 | */
485 | static void gprs_raw_send(gprs_t* gprs,const char * cmd,u8_t eol)
486 | {
487 |
488 | u32_t length;
489 |
490 |
491 | length = strlen(cmd);
492 |
493 | LWIP_DEBUGF(MODEM_DEBUG,("gprs: Sent: '%s' (eol=%d)\n",cmd,eol));
494 |
495 | gprs_serial_output(gprs,(u8_t *)cmd,length);
496 |
497 |
498 | if (eol)
499 | {
500 | gprs_serial_output(gprs,&eol,1);
501 | }
502 |
503 | }
504 |
505 | #if GPRS_COMMAND_DELAY
506 | /**
507 | * Callback function for delayed command.
508 | *
509 | * Called when the delay between 2 command expire.
510 | */
511 | static void gprs_command_delayed(void *arg)
512 | {
513 | //LWIP_DEBUGF(GPRS_DEBUG,("gprs_command_delayed: timeout\n"));
514 | gprs_t * gprs = (gprs_t *)arg;
515 | gprs_raw_send(gprs,gprs->delayedCommand,gprs->delayedEol);
516 | modem_set_state(gprs,MODEM_STATE_ECHO);
517 |
518 | }
519 | #endif
520 |
521 | /**
522 | * Start a new gprs connection
523 | */
524 | static void gprs_do_start(gprs_t * gprs)
525 | {
526 | UNTIMEOUT();
527 |
528 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: set modem off\n"));
529 |
530 | gprs_arch_modem_off(gprs->device);
531 | gprs_set_state(gprs,GPRS_STATE_MODEM_OFF);
532 | TIMEOUT(GPRS_MODEM_OFF_TIME);
533 | }
534 |
535 | /**
536 | * Send a new command to the modem.
537 | *
538 | * @param cmd - Pointer to the command
539 | * @param eol - Optional EOL char
540 | * @param timeout - Timeout of the operation in milliseconds.
541 | */
542 | static void gprs_command_timeout(gprs_t * gprs,const char * cmd,u8_t eol,u32_t timeout)
543 | {
544 | #if GPRS_COMMAND_DELAY
545 | u32_t delay = sys_now() - gprs->commandTime;
546 | #endif
547 |
548 | gprs->sentCommand = cmd;
549 |
550 | #if GPRS_COMMAND_DELAY
551 | if (delay < GPRS_COMMAND_DELAY)
552 | {
553 | delay = GPRS_COMMAND_DELAY - delay;
554 | timeout += delay;
555 | TIMEOUT(timeout);
556 | modem_set_state(gprs,MODEM_STATE_NONE);
557 | //LWIP_DEBUGF(GPRS_DEBUG,("gprs_command_timeout: Delayed %lu milliseconds\n",delay));
558 | TIMEOUT1(delay);
559 | gprs->delayedCommand = cmd;
560 | gprs->delayedEol = eol;
561 |
562 | }
563 | else
564 | {
565 | TIMEOUT(timeout);
566 | modem_set_state(gprs,MODEM_STATE_ECHO);
567 | gprs_raw_send(gprs,cmd,eol);
568 | }
569 | #else
570 | TIMEOUT(timeout);
571 | modem_set_state(gprs,MODEM_STATE_ECHO);
572 | gprs_raw_send(gprs,cmd,eol);
573 |
574 | #endif
575 | }
576 |
577 | /**
578 | * Send a command to the modem using the default timeout
579 | *
580 | * @param cmd - Pointer to the command
581 | * @param eol - Optional EOL char
582 | */
583 | static void gprs_command(gprs_t * gprs,const char *cmd,u8_t eol)
584 | {
585 | gprs_command_timeout(gprs,cmd,eol,GPRS_COMMAND_TIMEOUT);
586 | }
587 |
588 |
589 | /**
590 | * Return the next token from a modem reply.
591 | *
592 | * @return 0 If no token are available or a pointer to the token.
593 | */
594 | static const char * modem_next_token(gprs_t * gprs)
595 | {
596 | char * ptr = gprs->replyPtr;
597 | char * result;
598 |
599 | /**
600 | * Skip ' ' and ,
601 | */
602 | while (*ptr == ' ' || * ptr == ',')
603 | {
604 | ptr++;
605 | }
606 |
607 | result = ptr;
608 |
609 | while (*ptr && *ptr != ' ' && *ptr != ',')
610 | {
611 | ptr++;
612 | }
613 |
614 | if (*ptr)
615 | {
616 | *ptr = 0;
617 | ptr++;
618 | }
619 |
620 | gprs->replyPtr = ptr;
621 |
622 | //LWIP_DEBUGF(MODEM_DEBUG,("modem_next_token = '%s'\n",result));
623 |
624 | return *result ? result : 0;
625 | }
626 |
627 | /**
628 | * Set the command line received from the modem and return a
629 | * pointer to the fist one.
630 | *
631 | *
632 | * @return 0 or a pointer to the first token.
633 | */
634 | static const char * modem_first_token(gprs_t * gprs,const char * reply)
635 | {
636 | gprs->replyPtr = (char *)reply;
637 |
638 | return modem_next_token(gprs);
639 | }
640 |
641 |
642 | /**
643 | * Process reply from the identify command.
644 | *
645 | * This function identify the supported modem and set flag used during the connection.
646 | *
647 | * Supported devices :
648 | *
649 | * - SIM800 xxx Require gprs network registration flag.
650 | */
651 | static void do_modem_identify_reply(gprs_t * gprs,const char * reply)
652 | {
653 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: Identify: '%s'\n",reply));
654 |
655 | #if GPRS_TYPE
656 | sstrcpy(gprs->type,reply,sizeof(gprs->type));
657 | #endif
658 |
659 | if (!strncmp(reply,"SIM800",6))
660 | {
661 | gprs->cgreg = 1;
662 | }
663 | }
664 |
665 | /**
666 | * Send the modem identify command.
667 | */
668 | static void do_modem_identify(gprs_t * gprs)
669 | {
670 | UNTIMEOUT();
671 |
672 | #if GPRS_TYPE
673 | gprs->type[0] = 0;
674 | #endif
675 |
676 | gprs->cgreg = 0;
677 | gprs_set_state(gprs,GPRS_STATE_MODEM_IDENTIFY);
678 | gprs_command(gprs,"ATI",'\r');
679 | }
680 |
681 |
682 | /**
683 | * Process reply from the IMEI command
684 | */
685 | static void do_modem_imei_reply(gprs_t * gprs,const char * reply)
686 | {
687 | const char * result;
688 |
689 | result = modem_first_token(gprs,reply);
690 |
691 | if (result)
692 | {
693 |
694 | sstrcpy(gprs->imei,result,sizeof(gprs->imei));
695 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: IMEI='%s'\n",result));
696 | }
697 | }
698 |
699 | #if GPRS_ICCID
700 | /**
701 | * Send the get sim CCID command.
702 | */
703 | static void do_sim_iccid(gprs_t * gprs)
704 | {
705 | UNTIMEOUT();
706 |
707 | gprs->ccid[0] = 0;
708 | gprs_set_state(gprs,GPRS_STATE_MODEM_CCID);
709 | gprs_command(gprs,"AT+CCID",'\r');
710 | }
711 |
712 | static char gprs_mod10(const char *buff,size_t len)
713 | {
714 | size_t i,mod,sum;
715 | char digit;
716 |
717 | sum = 0;
718 | mod = len & 1;
719 |
720 | for( i = 0 ; i < len ; i ++)
721 | {
722 | digit = buff[i];
723 |
724 | if (digit >= '0' && digit <= '9')
725 | {
726 | digit -= '0';
727 | if ((i & 1) != mod)
728 | digit *= 2;
729 | if (digit > 9)
730 | digit -= 9;
731 | sum += digit;
732 | }
733 |
734 | }
735 |
736 | return((char)((( 10 - (sum % 10)) % 10) +'0'));
737 | }
738 |
739 | static void do_sim_iccid_reply(gprs_t * gprs,const char * reply)
740 | {
741 | const char * result;
742 | size_t length;
743 | char c;
744 |
745 | result = modem_first_token(gprs,reply);
746 |
747 | if (result)
748 | {
749 |
750 | sstrcpy(gprs->ccid,result,sizeof(gprs->ccid));
751 |
752 | /*
753 | * Remove the filler digit
754 | */
755 | for (length = strlen(gprs->ccid) ; length > 0 && (gprs->ccid[length - 1] == 'f' || gprs->ccid[length - 1] == 'F') ;)
756 | {
757 | gprs->ccid[length - 1] = 0;
758 | length = strlen(gprs->ccid);
759 | }
760 |
761 | gprs->ccidChksum = 0;
762 | if (length > 1)
763 | {
764 | c = gprs_mod10(gprs->ccid,length - 1);
765 | if (c == gprs->ccid[length - 1])
766 | {
767 | gprs->ccid[length - 1] = 0;
768 | gprs->ccidChksum = c;
769 | }
770 | }
771 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: ICCID='%s' length=%u chksum=%c\n",gprs->ccid,strlen(gprs->ccid),gprs->ccidChksum == 0 ? '?' : gprs->ccidChksum));
772 | }
773 | }
774 |
775 | const char * gprs_get_iccid(gprs_t * gprs,char *chksum)
776 | {
777 | if (chksum)
778 | {
779 | *chksum = gprs->ccidChksum;
780 | }
781 | return gprs->ccid;
782 | }
783 | #endif
784 |
785 | /**
786 | * Send the get IMEI command.
787 | */
788 | static void do_modem_imei(gprs_t * gprs)
789 | {
790 | UNTIMEOUT();
791 |
792 | gprs->imei[0] = 0;
793 | gprs_set_state(gprs,GPRS_STATE_MODEM_IMEI);
794 | gprs_command(gprs,"AT+GSN",'\r');
795 | }
796 |
797 |
798 | /**
799 | * Decode a network status reply from the modem.
800 | */
801 | static u8_t do_network_decode(gprs_t *gprs, char * reply)
802 | {
803 | int network = -1;
804 | const char * result;
805 |
806 | result = modem_first_token(gprs,reply);
807 |
808 | if (result)
809 | {
810 | result = modem_next_token(gprs);
811 | if (result)
812 | {
813 | result = modem_next_token(gprs);
814 | if (result)
815 | {
816 | network = atoi(result);
817 | }
818 | }
819 | }
820 |
821 | LWIP_DEBUGF(MODEM_DEBUG,("gprs: Decoded network=%d\n",network));
822 |
823 | return network;
824 | }
825 |
826 | /**
827 | * Decode a signal quality reply from the modem.
828 | */
829 | static u8_t do_signal_quality_decode(gprs_t *gprs, char * reply)
830 | {
831 | int csq = -1;
832 | const char * result;
833 |
834 | result = modem_first_token(gprs,reply);
835 |
836 | if (result)
837 | {
838 | result = modem_next_token(gprs);
839 | if (result)
840 | {
841 | csq = atoi(result);
842 | }
843 | }
844 |
845 | LWIP_DEBUGF(MODEM_DEBUG,("gprs: Decoded signal quality=%d\n",csq));
846 |
847 | return csq;
848 |
849 |
850 | }
851 |
852 | /**
853 | * Process reply from the gsm registration command.
854 | */
855 | static void do_gsm_network_reply(gprs_t *gprs,const char *reply)
856 | {
857 | int network = do_network_decode(gprs,(char *)reply);
858 |
859 | if (network != gprs->gsmNetwork)
860 | {
861 | gprs->gsmNetwork = network;
862 | }
863 | }
864 |
865 | /**
866 | * Process reply from the gsm signal quality command.
867 | */
868 | static void do_gsm_signal_quality_reply(gprs_t *gprs,const char *reply)
869 | {
870 | gprs->csq = do_signal_quality_decode(gprs,(char *)reply);
871 | }
872 |
873 | /**
874 | * Send the gprs registration command
875 | *
876 | */
877 | static void do_gprs_network(gprs_t * gprs)
878 | {
879 | UNTIMEOUT();
880 |
881 | gprs_set_state(gprs,GPRS_STATE_GPRS_NETWORK);
882 |
883 | if (gprs->subState++ == 0)
884 | {
885 | gprs->gprsNetwork = GPRS_NETWORK_INVALID;
886 |
887 | }
888 |
889 | if (gprs_state_elapsed(gprs) > GPRS_REGISTRATION_TIMEOUT)
890 | {
891 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: GPRS Network registration timeout (%lu)\n",(unsigned long)GPRS_REGISTRATION_TIMEOUT));
892 | gprs_do_start(gprs);
893 | }
894 | else
895 | {
896 | gprs_command(gprs,"AT+CGREG?",'\r');
897 | }
898 | }
899 |
900 | /**
901 | * Process reply from the gprs registration command
902 | */
903 | static void do_gprs_network_reply(gprs_t *gprs,const char *reply)
904 | {
905 | int network = do_network_decode(gprs,(char *)reply);
906 |
907 | if (network != gprs->gprsNetwork)
908 | {
909 | gprs->gprsNetwork = network;
910 | }
911 | }
912 |
913 | /**
914 | * Process the modem reply for the dial command.
915 | */
916 | static void do_modem_dial_reply(gprs_t * gprs,const char *reply)
917 | {
918 | if (!strncmp(reply,"CONNECT",7))
919 | {
920 | gprs->connected =1;
921 | }
922 | }
923 |
924 | /**
925 | * Send the dial command to the modem.
926 | */
927 | static void do_modem_dial(gprs_t * gprs)
928 | {
929 |
930 | UNTIMEOUT();
931 |
932 | gprs_set_state(gprs,GPRS_STATE_MODEM_DIAL);
933 | gprs->connected = 0;
934 | gprs_command_timeout(gprs,"ATD*99***1#",'\r',GPRS_DIAL_TIMEOUT);
935 | }
936 |
937 | /**
938 | * Send the command to initialize the gprs of the modem.
939 | */
940 | static void do_modem_init(gprs_t * gprs)
941 | {
942 | UNTIMEOUT();
943 |
944 | gprs_set_state(gprs,GPRS_STATE_MODEM_INIT);
945 | sstrcpy(gprs->replyBuffer,"AT+CGDCONT=1,\"IP\",\"",sizeof(gprs->replyBuffer));
946 |
947 | #if GPRS_RUNTIME_APN
948 | sstrcat(gprs->replyBuffer,gprs->apn,sizeof(gprs->replyBuffer));
949 | #else
950 | sstrcat(gprs->replyBuffer,GPRS_APN,sizeof(gprs->replyBuffer));
951 | #endif
952 |
953 | sstrcat(gprs->replyBuffer,"\"",sizeof(gprs->replyBuffer));
954 |
955 | gprs_command(gprs,gprs->replyBuffer,'\r');
956 |
957 | }
958 |
959 | static void do_gprs_network_check(gprs_t *gprs,u8_t *data,u32_t length)
960 | {
961 | if (modem_check_reply(gprs,data,length,do_gprs_network_reply) == MODEM_REPLY_OK)
962 | {
963 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: GPRS Network is %d\n",gprs->gprsNetwork));
964 |
965 | if (gprs->gprsNetwork == GPRS_NETWORK_HOME || (gprs->gprsNetwork == GPRS_NETWORK_ROAMING && gprs->roaming))
966 | {
967 | do_modem_init(gprs);
968 | }
969 | else
970 | {
971 | do_gprs_network(gprs);
972 | }
973 | }
974 | }
975 |
976 |
977 | /**
978 | * Send alternatively the signal quality and the gsm network registration commands.
979 | */
980 | static void do_gsm_network(gprs_t *gprs)
981 | {
982 | UNTIMEOUT();
983 |
984 | gprs_set_state(gprs,GPRS_STATE_GSM_NETWORK);
985 |
986 | if (gprs->subState++ == 0)
987 | {
988 | gprs->gsmNetwork = GPRS_NETWORK_INVALID;
989 | }
990 |
991 | if (gprs_state_elapsed(gprs) > GPRS_REGISTRATION_TIMEOUT)
992 | {
993 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: GSM Network registration timeout (%lu)\n",(unsigned long)GPRS_REGISTRATION_TIMEOUT));
994 | gprs_do_start(gprs);
995 | }
996 | else
997 | {
998 | if (gprs->subState & 0x01)
999 | {
1000 | gprs_command(gprs,"AT+CSQ",'\r');
1001 | }
1002 | else
1003 | {
1004 | gprs_command(gprs,"AT+CREG?",'\r');
1005 | }
1006 | }
1007 | }
1008 |
1009 |
1010 | static void do_gsm_network_check(gprs_t *gprs,u8_t *data,u32_t length)
1011 | {
1012 | if (gprs->subState & 0x01)
1013 | {
1014 | if (modem_check_reply(gprs,data,length,do_gsm_signal_quality_reply) == MODEM_REPLY_OK)
1015 | {
1016 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: GSM Signal Quality is %d\n",gprs->csq));
1017 |
1018 | do_gsm_network(gprs);
1019 | }
1020 | }
1021 | else
1022 | {
1023 | if (modem_check_reply(gprs,data,length,do_gsm_network_reply) == MODEM_REPLY_OK)
1024 | {
1025 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: GSM Network is %d\n",gprs->gsmNetwork));
1026 |
1027 | if (gprs->gsmNetwork == GPRS_NETWORK_HOME || (gprs->gsmNetwork == GPRS_NETWORK_ROAMING && gprs->roaming))
1028 | {
1029 | if (gprs->cgreg)
1030 | {
1031 | do_gprs_network(gprs);
1032 | }
1033 | else
1034 | {
1035 | do_modem_init(gprs);
1036 |
1037 | }
1038 | }
1039 | else
1040 | {
1041 | do_gsm_network(gprs);
1042 | }
1043 | }
1044 | }
1045 | }
1046 |
1047 |
1048 | /**
1049 | * Send the modem alive command.
1050 | */
1051 | static void do_modem_alive(gprs_t * gprs)
1052 | {
1053 | UNTIMEOUT();
1054 |
1055 | gprs_set_state(gprs,GPRS_STATE_MODEM_ALIVE);
1056 |
1057 | if (gprs_state_elapsed(gprs) > GPRS_ALIVE_TIMEOUT)
1058 | {
1059 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: Modem alive timeout (%lu)\n",(unsigned long)GPRS_ALIVE_TIMEOUT));
1060 | gprs_do_start(gprs);
1061 | }
1062 | else
1063 | {
1064 | gprs_command(gprs,"AT",'\r');
1065 | }
1066 | }
1067 |
1068 | /**
1069 | * Send a sequence of command to the modem after power up
1070 | *
1071 | * The reply are not checked and the command only set the modem in the default state.
1072 | */
1073 | static void do_modem_wakeup(gprs_t * gprs)
1074 | {
1075 | static const char * inits[] = {"AT","AT","AT&F","ATE1"};
1076 |
1077 | gprs_set_state(gprs,GPRS_STATE_MODEM_WAKEUP);
1078 |
1079 | if (gprs->subState < (int)(sizeof(inits)/sizeof(char *)))
1080 | {
1081 | TIMEOUT(GPRS_INIT_COMMAND_DELAY);
1082 | gprs_raw_send(gprs,inits[gprs->subState++],'\r');
1083 | }
1084 | else
1085 | {
1086 | do_modem_alive(gprs);
1087 | }
1088 |
1089 | }
1090 |
1091 |
1092 | /**
1093 | * Start the PPP connection
1094 | */
1095 | static void gprs_do_connect(gprs_t * gprs)
1096 | {
1097 | UNTIMEOUT();
1098 | gprs_set_state(gprs,GPRS_STATE_CONNECTING);
1099 | ppp_connect(gprs->pcb,0);
1100 | }
1101 |
1102 | /**
1103 | * Handle timeout
1104 | */
1105 | static void gprs_timeout(void * arg)
1106 | {
1107 | gprs_t * gprs = (gprs_t *)arg;
1108 |
1109 |
1110 | switch (gprs->state)
1111 | {
1112 | default:
1113 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: Timeout state %d\n",gprs->state));
1114 | gprs_do_start(gprs);
1115 | break;
1116 |
1117 | case GPRS_STATE_MODEM_OFF:
1118 | gprs_arch_modem_on(gprs->device);
1119 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: set modem on\n"));
1120 | TIMEOUT(GPRS_MODEM_ON_DELAY);
1121 | gprs_set_state(gprs,GPRS_STATE_MODEM_ON);
1122 | break;
1123 |
1124 | case GPRS_STATE_MODEM_ON:
1125 | case GPRS_STATE_MODEM_WAKEUP:
1126 | do_modem_wakeup(gprs);
1127 | break;
1128 |
1129 | case GPRS_STATE_MODEM_ALIVE:
1130 | do_modem_alive(gprs);
1131 | break;
1132 |
1133 |
1134 |
1135 | }
1136 | }
1137 |
1138 |
1139 | /**
1140 | * This function process data from the serial interface and must run
1141 | * in the LWIP thread context.
1142 | *
1143 | * @param gprs - Pointer to the gprs structur7e.
1144 | * @param data- Data pointer
1145 | * @param length - Length of the data.
1146 | */
1147 |
1148 | static void gprs_input_internal(gprs_t * gprs,u8_t * data,u32_t length)
1149 | {
1150 |
1151 | if (length > 0)
1152 | {
1153 |
1154 | #if 0
1155 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: Got %lu bytes state=%d\n",(unsigned long)length,gprs->state));
1156 | #endif
1157 |
1158 | switch (gprs->state)
1159 | {
1160 | default:
1161 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: Ignored %lu bytes\n",(unsigned long)length));
1162 | break;
1163 |
1164 | case GPRS_STATE_MODEM_DIAL:
1165 | modem_check_reply(gprs,data,length,do_modem_dial_reply);
1166 | if (gprs->connected)
1167 | {
1168 | gprs_do_connect(gprs);
1169 | }
1170 | break;
1171 |
1172 | case GPRS_STATE_GPRS_NETWORK:
1173 | do_gprs_network_check(gprs,data,length);
1174 | break;
1175 |
1176 | case GPRS_STATE_GSM_NETWORK:
1177 | do_gsm_network_check(gprs,data,length);
1178 | break;
1179 |
1180 | case GPRS_STATE_MODEM_IMEI:
1181 | if (modem_check_reply(gprs,data,length,do_modem_imei_reply) == MODEM_REPLY_OK)
1182 | {
1183 | #if GPRS_ICCID
1184 | do_sim_iccid(gprs);
1185 | #else
1186 | do_gsm_network(gprs);
1187 | #endif
1188 | }
1189 | break;
1190 |
1191 | #if GPRS_ICCID
1192 | case GPRS_STATE_MODEM_CCID:
1193 | if (modem_check_reply(gprs,data,length,do_sim_iccid_reply) == MODEM_REPLY_OK)
1194 | {
1195 | do_gsm_network(gprs);
1196 | }
1197 | break;
1198 | #endif
1199 |
1200 | case GPRS_STATE_MODEM_IDENTIFY:
1201 | if (modem_check_reply(gprs,data,length,do_modem_identify_reply) == MODEM_REPLY_OK)
1202 | {
1203 | do_modem_imei(gprs);
1204 | }
1205 | break;
1206 |
1207 | case GPRS_STATE_MODEM_INIT:
1208 | if (modem_check_ok_reply(gprs,data,length))
1209 | {
1210 | do_modem_dial(gprs);
1211 | }
1212 | break;
1213 | case GPRS_STATE_MODEM_ALIVE:
1214 | if (modem_check_ok_reply(gprs,data,length))
1215 | {
1216 | do_modem_identify(gprs);
1217 | }
1218 | break;
1219 |
1220 | case GPRS_STATE_CONNECTING:
1221 | case GPRS_STATE_CONNECTED:
1222 | pppos_input(gprs->pcb,data,length);
1223 | break;
1224 |
1225 | }
1226 | }
1227 | }
1228 |
1229 |
1230 | /**
1231 | * Open the GPRS connection
1232 | */
1233 | void gprs_open(gprs_t * gprs)
1234 | {
1235 | gprs_do_start(gprs);
1236 | }
1237 |
1238 |
1239 | #if GPRS_RUNTIME_APN
1240 |
1241 | void gprs_set_apn(gprs_t * gprs,const char *name)
1242 | {
1243 | sstrcpy(gprs->apn,name,sizeof(gprs->apn));
1244 |
1245 | LWIP_DEBUGF(GPRS_DEBUG,("gprs: set_apn='%s'\n",gprs->apn));
1246 | }
1247 |
1248 |
1249 | const char * gprs_get_apn(gprs_t * gprs)
1250 | {
1251 | return gprs->apn;
1252 | }
1253 |
1254 | #endif
1255 |
1256 |
1257 | const char * gprs_get_imei(gprs_t * gprs)
1258 | {
1259 | return gprs->imei;
1260 | }
1261 |
1262 |
1263 | u8_t gprs_get_csq(gprs_t * gprs)
1264 | {
1265 | return gprs->csq;
1266 | }
1267 |
1268 |
1269 | void gprs_set_roaming(gprs_t * gprs,u8_t roaming)
1270 | {
1271 | gprs->roaming = roaming;
1272 | }
1273 |
1274 |
1275 | #if GPRS_TYPE
1276 | const char * gprs_get_type(gprs_t * gprs)
1277 | {
1278 | return gprs->type;
1279 | }
1280 | #endif
1281 |
1282 |
1283 | #if GPRS_SERIAL_STAT
1284 | void gprs_get_stat(gprs_t * gprs,u32_t * sent,u32_t * rcvd)
1285 | {
1286 | *sent = gprs->sentBytes;
1287 | *rcvd = gprs->rcvdBtes;
1288 | }
1289 | #endif
1290 |
1291 | #endif /* GPRS_SUPPPORT */
1292 |
--------------------------------------------------------------------------------