├── .gitignore ├── README.md ├── gprs.c └── gprs.h /.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.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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------