at_socket_m26.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. /*
  2. * File : at_socket_m26.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2018-06-12 chenyong first version
  23. */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <rtthread.h>
  27. #include <sys/socket.h>
  28. #include <at.h>
  29. #include <at_socket.h>
  30. #if !defined(AT_SW_VERSION_NUM) || AT_SW_VERSION_NUM < 0x10200
  31. #error "This AT Client version is older, please check and update latest AT Client!"
  32. #endif
  33. #define LOG_TAG "at.m26|mc20"
  34. #include <at_log.h>
  35. #ifdef AT_DEVICE_M26
  36. #define M26_MODULE_SEND_MAX_SIZE 1460
  37. #define M26_WAIT_CONNECT_TIME 5000
  38. #define M26_THREAD_STACK_SIZE 1024
  39. #define M26_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX/2)
  40. /* set real event by current socket and current state */
  41. #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event))
  42. /* AT socket event type */
  43. #define M26_EVENT_CONN_OK (1L << 0)
  44. #define M26_EVENT_SEND_OK (1L << 1)
  45. #define M26_EVENT_RECV_OK (1L << 2)
  46. #define M26_EVNET_CLOSE_OK (1L << 3)
  47. #define M26_EVENT_CONN_FAIL (1L << 4)
  48. #define M26_EVENT_SEND_FAIL (1L << 5)
  49. static int cur_socket;
  50. static rt_event_t at_socket_event;
  51. static rt_mutex_t at_event_lock;
  52. static at_evt_cb_t at_evt_cb_set[] = {
  53. [AT_SOCKET_EVT_RECV] = NULL,
  54. [AT_SOCKET_EVT_CLOSED] = NULL,
  55. };
  56. static int at_socket_event_send(uint32_t event)
  57. {
  58. return (int) rt_event_send(at_socket_event, event);
  59. }
  60. static int at_socket_event_recv(uint32_t event, uint32_t timeout, rt_uint8_t option)
  61. {
  62. int result = 0;
  63. rt_uint32_t recved;
  64. result = rt_event_recv(at_socket_event, event, option | RT_EVENT_FLAG_CLEAR, timeout, &recved);
  65. if (result != RT_EOK)
  66. {
  67. return -RT_ETIMEOUT;
  68. }
  69. return recved;
  70. }
  71. /**
  72. * close socket by AT commands.
  73. *
  74. * @param current socket
  75. *
  76. * @return 0: close socket success
  77. * -1: send AT commands error
  78. * -2: wait socket event timeout
  79. * -5: no memory
  80. */
  81. static int m26_socket_close(int socket)
  82. {
  83. int result = 0;
  84. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  85. cur_socket = socket;
  86. if (at_exec_cmd(RT_NULL, "AT+QICLOSE=%d", socket) < 0)
  87. {
  88. result = -RT_ERROR;
  89. goto __exit;
  90. }
  91. if (at_socket_event_recv(SET_EVENT(socket, M26_EVNET_CLOSE_OK), rt_tick_from_millisecond(300*3), RT_EVENT_FLAG_AND) < 0)
  92. {
  93. LOG_E("socket (%d) close failed, wait close OK timeout.", socket);
  94. result = -RT_ETIMEOUT;
  95. goto __exit;
  96. }
  97. __exit:
  98. rt_mutex_release(at_event_lock);
  99. return result;
  100. }
  101. /**
  102. * create TCP/UDP client or server connect by AT commands.
  103. *
  104. * @param socket current socket
  105. * @param ip server or client IP address
  106. * @param port server or client port
  107. * @param type connect socket type(tcp, udp)
  108. * @param is_client connection is client
  109. *
  110. * @return 0: connect success
  111. * -1: connect failed, send commands error or type error
  112. * -2: wait socket event timeout
  113. * -5: no memory
  114. */
  115. static int m26_socket_connect(int socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client)
  116. {
  117. int result = 0, event_result = 0;
  118. rt_bool_t retryed = RT_FALSE;
  119. RT_ASSERT(ip);
  120. RT_ASSERT(port >= 0);
  121. /* lock AT socket connect */
  122. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  123. __retry:
  124. if (is_client)
  125. {
  126. switch (type)
  127. {
  128. case AT_SOCKET_TCP:
  129. /* send AT commands(eg: AT+QIOPEN=0,"TCP","x.x.x.x", 1234) to connect TCP server */
  130. if (at_exec_cmd(RT_NULL, "AT+QIOPEN=%d,\"TCP\",\"%s\",%d", socket, ip, port) < 0)
  131. {
  132. result = -RT_ERROR;
  133. goto __exit;
  134. }
  135. break;
  136. case AT_SOCKET_UDP:
  137. if (at_exec_cmd(RT_NULL, "AT+QIOPEN=%d,\"UDP\",\"%s\",%d", socket, ip, port) < 0)
  138. {
  139. result = -RT_ERROR;
  140. goto __exit;
  141. }
  142. break;
  143. default:
  144. LOG_E("Not supported connect type : %d.", type);
  145. return -RT_ERROR;
  146. }
  147. }
  148. /* waiting result event from AT URC, the device default connection timeout is 75 seconds, but it set to 10 seconds is convenient to use.*/
  149. if (at_socket_event_recv(SET_EVENT(socket, 0), rt_tick_from_millisecond(10 * 1000), RT_EVENT_FLAG_OR) < 0)
  150. {
  151. LOG_E("socket (%d) connect failed, wait connect result timeout.", socket);
  152. result = -RT_ETIMEOUT;
  153. goto __exit;
  154. }
  155. /* waiting OK or failed result */
  156. if ((event_result = at_socket_event_recv(M26_EVENT_CONN_OK | M26_EVENT_CONN_FAIL, rt_tick_from_millisecond(1 * 1000),
  157. RT_EVENT_FLAG_OR)) < 0)
  158. {
  159. LOG_E("socket (%d) connect failed, wait connect OK|FAIL timeout.", socket);
  160. result = -RT_ETIMEOUT;
  161. goto __exit;
  162. }
  163. /* check result */
  164. if (event_result & M26_EVENT_CONN_FAIL)
  165. {
  166. if (!retryed)
  167. {
  168. LOG_E("socket (%d) connect failed, maybe the socket was not be closed at the last time and now will retry.", socket);
  169. if (m26_socket_close(socket) < 0)
  170. {
  171. goto __exit;
  172. }
  173. retryed = RT_TRUE;
  174. goto __retry;
  175. }
  176. LOG_E("socket (%d) connect failed, failed to establish a connection.", socket);
  177. result = -RT_ERROR;
  178. goto __exit;
  179. }
  180. __exit:
  181. /* unlock AT socket connect */
  182. rt_mutex_release(at_event_lock);
  183. return result;
  184. }
  185. static int at_get_send_size(int socket, size_t *size, size_t *acked, size_t *nacked)
  186. {
  187. at_response_t resp = at_create_resp(64, 0, rt_tick_from_millisecond(5000));
  188. int result = 0;
  189. if (!resp)
  190. {
  191. LOG_E("No memory for response structure!");
  192. result = -RT_ENOMEM;
  193. goto __exit;
  194. }
  195. if (at_exec_cmd(resp, "AT+QISACK=%d", socket) < 0)
  196. {
  197. result = -RT_ERROR;
  198. goto __exit;
  199. }
  200. if (at_resp_parse_line_args_by_kw(resp, "+QISACK:", "+QISACK: %d, %d, %d", size, acked, nacked) <= 0)
  201. {
  202. result = -RT_ERROR;
  203. goto __exit;
  204. }
  205. __exit:
  206. if (resp)
  207. {
  208. at_delete_resp(resp);
  209. }
  210. return result;
  211. }
  212. static int at_wait_send_finish(int socket, size_t settings_size)
  213. {
  214. /* get the timeout by the input data size */
  215. rt_tick_t timeout = rt_tick_from_millisecond(settings_size);
  216. rt_tick_t last_time = rt_tick_get();
  217. size_t size = 0, acked = 0, nacked = 0xFFFF;
  218. while (rt_tick_get() - last_time <= timeout)
  219. {
  220. at_get_send_size(socket, &size, &acked, &nacked);
  221. if (nacked == 0)
  222. {
  223. return RT_EOK;
  224. }
  225. rt_thread_delay(rt_tick_from_millisecond(50));
  226. }
  227. return -RT_ETIMEOUT;
  228. }
  229. /**
  230. * send data to server or client by AT commands.
  231. *
  232. * @param socket current socket
  233. * @param buff send buffer
  234. * @param bfsz send buffer size
  235. * @param type connect socket type(tcp, udp)
  236. *
  237. * @return >=0: the size of send success
  238. * -1: send AT commands error or send data error
  239. * -2: waited socket event timeout
  240. * -5: no memory
  241. */
  242. static int m26_socket_send(int socket, const char *buff, size_t bfsz, enum at_socket_type type)
  243. {
  244. int result = 0, event_result = 0;
  245. at_response_t resp = RT_NULL;
  246. size_t cur_pkt_size = 0, sent_size = 0;
  247. RT_ASSERT(buff);
  248. resp = at_create_resp(128, 2, rt_tick_from_millisecond(5000));
  249. if (!resp)
  250. {
  251. LOG_E("No memory for response structure!");
  252. return -RT_ENOMEM;
  253. }
  254. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  255. /* set current socket for send URC event */
  256. cur_socket = socket;
  257. /* set AT client end sign to deal with '>' sign.*/
  258. at_set_end_sign('>');
  259. while (sent_size < bfsz)
  260. {
  261. if (bfsz - sent_size < M26_MODULE_SEND_MAX_SIZE)
  262. {
  263. cur_pkt_size = bfsz - sent_size;
  264. }
  265. else
  266. {
  267. cur_pkt_size = M26_MODULE_SEND_MAX_SIZE;
  268. }
  269. /* send the "AT+QISEND" commands to AT server than receive the '>' response on the first line. */
  270. if (at_exec_cmd(resp, "AT+QISEND=%d,%d", socket, cur_pkt_size) < 0)
  271. {
  272. result = -RT_ERROR;
  273. goto __exit;
  274. }
  275. /* send the real data to server or client */
  276. result = (int) at_client_send(buff + sent_size, cur_pkt_size);
  277. if (result == 0)
  278. {
  279. result = -RT_ERROR;
  280. goto __exit;
  281. }
  282. /* waiting result event from AT URC */
  283. if (at_socket_event_recv(SET_EVENT(socket, 0), rt_tick_from_millisecond(300*3), RT_EVENT_FLAG_OR) < 0)
  284. {
  285. LOG_E("socket (%d) send failed, wait connect result timeout.", socket);
  286. result = -RT_ETIMEOUT;
  287. goto __exit;
  288. }
  289. /* waiting OK or failed result */
  290. if ((event_result = at_socket_event_recv(M26_EVENT_SEND_OK | M26_EVENT_SEND_FAIL, rt_tick_from_millisecond(1 * 1000),
  291. RT_EVENT_FLAG_OR)) < 0)
  292. {
  293. LOG_E("socket (%d) send failed, wait connect OK|FAIL timeout.", socket);
  294. result = -RT_ETIMEOUT;
  295. goto __exit;
  296. }
  297. /* check result */
  298. if (event_result & M26_EVENT_SEND_FAIL)
  299. {
  300. LOG_E("socket (%d) send failed, return failed.", socket);
  301. result = -RT_ERROR;
  302. goto __exit;
  303. }
  304. if (type == AT_SOCKET_TCP)
  305. {
  306. at_wait_send_finish(socket, cur_pkt_size);
  307. }
  308. sent_size += cur_pkt_size;
  309. }
  310. __exit:
  311. /* reset the end sign for data conflict */
  312. at_set_end_sign(0);
  313. rt_mutex_release(at_event_lock);
  314. if (resp)
  315. {
  316. at_delete_resp(resp);
  317. }
  318. return result;
  319. }
  320. /**
  321. * domain resolve by AT commands.
  322. *
  323. * @param name domain name
  324. * @param ip parsed IP address, it's length must be 16
  325. *
  326. * @return 0: domain resolve success
  327. * -1: send AT commands error or response error
  328. * -2: wait socket event timeout
  329. * -5: no memory
  330. */
  331. static int m26_domain_resolve(const char *name, char ip[16])
  332. {
  333. #define RESOLVE_RETRY 5
  334. int i, result = RT_EOK;
  335. char recv_ip[16] = { 0 };
  336. at_response_t resp = RT_NULL;
  337. RT_ASSERT(name);
  338. RT_ASSERT(ip);
  339. /* The maximum response time is 14 seconds, affected by network status */
  340. resp = at_create_resp(128, 4, rt_tick_from_millisecond(14 * 1000));
  341. if (!resp)
  342. {
  343. LOG_E("No memory for response structure!");
  344. return -RT_ENOMEM;
  345. }
  346. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  347. for(i = 0; i < RESOLVE_RETRY; i++)
  348. {
  349. if (at_exec_cmd(resp, "AT+QIDNSGIP=\"%s\"", name) < 0)
  350. {
  351. result = -RT_ERROR;
  352. goto __exit;
  353. }
  354. /* parse the third line of response data, get the IP address */
  355. if(at_resp_parse_line_args_by_kw(resp, ".", "%s", recv_ip) < 0)
  356. {
  357. rt_thread_delay(rt_tick_from_millisecond(100));
  358. /* resolve failed, maybe receive an URC CRLF */
  359. continue;
  360. }
  361. if (strlen(recv_ip) < 8)
  362. {
  363. rt_thread_delay(rt_tick_from_millisecond(100));
  364. /* resolve failed, maybe receive an URC CRLF */
  365. continue;
  366. }
  367. else
  368. {
  369. strncpy(ip, recv_ip, 15);
  370. ip[15] = '\0';
  371. break;
  372. }
  373. }
  374. __exit:
  375. rt_mutex_release(at_event_lock);
  376. if (resp)
  377. {
  378. at_delete_resp(resp);
  379. }
  380. return result;
  381. }
  382. /**
  383. * set AT socket event notice callback
  384. *
  385. * @param event notice event
  386. * @param cb notice callback
  387. */
  388. static void m26_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb)
  389. {
  390. if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1]))
  391. {
  392. at_evt_cb_set[event] = cb;
  393. }
  394. }
  395. static void urc_connect_func(const char *data, rt_size_t size)
  396. {
  397. int socket = 0;
  398. RT_ASSERT(data && size);
  399. sscanf(data, "%d%*[^0-9]", &socket);
  400. if (strstr(data, "CONNECT OK"))
  401. {
  402. at_socket_event_send(SET_EVENT(socket, M26_EVENT_CONN_OK));
  403. }
  404. else
  405. {
  406. at_socket_event_send(SET_EVENT(socket, M26_EVENT_CONN_FAIL));
  407. }
  408. }
  409. static void urc_send_func(const char *data, rt_size_t size)
  410. {
  411. RT_ASSERT(data && size);
  412. if (strstr(data, "SEND OK"))
  413. {
  414. at_socket_event_send(SET_EVENT(cur_socket, M26_EVENT_SEND_OK));
  415. }
  416. else if (strstr(data, "SEND FAIL"))
  417. {
  418. at_socket_event_send(SET_EVENT(cur_socket, M26_EVENT_SEND_FAIL));
  419. }
  420. }
  421. static void urc_close_func(const char *data, rt_size_t size)
  422. {
  423. int socket = 0;
  424. RT_ASSERT(data && size);
  425. if (strstr(data, "CLOSE OK"))
  426. {
  427. at_socket_event_send(SET_EVENT(cur_socket, M26_EVNET_CLOSE_OK));
  428. }
  429. else if (strstr(data, "CLOSED"))
  430. {
  431. sscanf(data, "%d, CLOSED", &socket);
  432. /* notice the socket is disconnect by remote */
  433. if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
  434. {
  435. at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, NULL, 0);
  436. }
  437. }
  438. }
  439. static void urc_recv_func(const char *data, rt_size_t size)
  440. {
  441. int socket = 0;
  442. rt_size_t bfsz = 0, temp_size = 0;
  443. rt_int32_t timeout;
  444. char *recv_buf = RT_NULL, temp[8];
  445. RT_ASSERT(data && size);
  446. /* get the current socket and receive buffer size by receive data */
  447. sscanf(data, "+RECEIVE: %d, %d", &socket, (int *) &bfsz);
  448. /* get receive timeout by receive buffer length */
  449. timeout = bfsz;
  450. if (socket < 0 || bfsz == 0)
  451. return;
  452. recv_buf = rt_calloc(1, bfsz);
  453. if (!recv_buf)
  454. {
  455. LOG_E("no memory for URC receive buffer (%d)!", bfsz);
  456. /* read and clean the coming data */
  457. while (temp_size < bfsz)
  458. {
  459. if (bfsz - temp_size > sizeof(temp))
  460. {
  461. at_client_recv(temp, sizeof(temp), timeout);
  462. }
  463. else
  464. {
  465. at_client_recv(temp, bfsz - temp_size, timeout);
  466. }
  467. temp_size += sizeof(temp);
  468. }
  469. return;
  470. }
  471. /* sync receive data */
  472. if (at_client_recv(recv_buf, bfsz, timeout) != bfsz)
  473. {
  474. LOG_E("receive size(%d) data failed!", bfsz);
  475. rt_free(recv_buf);
  476. return;
  477. }
  478. /* notice the receive buffer and buffer size */
  479. if (at_evt_cb_set[AT_SOCKET_EVT_RECV])
  480. {
  481. at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz);
  482. }
  483. }
  484. static void urc_ping_func(const char *data, rt_size_t size)
  485. {
  486. static int icmp_seq = 0;
  487. int result, recv_len, time, ttl;
  488. char dst_ip[16] = { 0 };
  489. RT_ASSERT(data);
  490. sscanf(data, "+QPING: %d,%[^,],%d,%d,%d", &result, dst_ip, &recv_len, &time, &ttl);
  491. switch(result)
  492. {
  493. case 0:
  494. rt_kprintf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n", recv_len, dst_ip, icmp_seq++, ttl, time);
  495. break;
  496. case 1:
  497. rt_kprintf("ping request timeout!\n");
  498. break;
  499. case 2:
  500. icmp_seq = 0;
  501. break;
  502. case 3:
  503. rt_kprintf("ping: TCP/IP protocol stack is busy\n");
  504. break;
  505. case 4:
  506. rt_kprintf("ping: unknown remote server host\n");
  507. break;
  508. default:
  509. break;
  510. }
  511. }
  512. static void urc_func(const char *data, rt_size_t size)
  513. {
  514. RT_ASSERT(data);
  515. LOG_I("URC data : %.*s", size, data);
  516. }
  517. static const struct at_urc urc_table[] = {
  518. {"RING", "\r\n", urc_func},
  519. {"Call Ready", "\r\n", urc_func},
  520. {"RDY", "\r\n", urc_func},
  521. {"NO CARRIER", "\r\n", urc_func},
  522. {"", ", CONNECT OK\r\n", urc_connect_func},
  523. {"", ", CONNECT FAIL\r\n", urc_connect_func},
  524. {"SEND OK", "\r\n", urc_send_func},
  525. {"SEND FAIL", "\r\n", urc_send_func},
  526. {"", ", CLOSE OK\r\n", urc_close_func},
  527. {"", ", CLOSED\r\n", urc_close_func},
  528. {"+RECEIVE:", "\r\n", urc_recv_func},
  529. {"+QPING:", "\r\n", urc_ping_func},
  530. };
  531. #define AT_SEND_CMD(resp, resp_line, timeout, cmd) \
  532. do \
  533. { \
  534. if (at_exec_cmd(at_resp_set_info(resp, 128, resp_line, rt_tick_from_millisecond(timeout)), cmd) < 0) \
  535. { \
  536. result = -RT_ERROR; \
  537. goto __exit; \
  538. } \
  539. } while(0); \
  540. /* init for M26 or MC20 */
  541. static void m26_init_thread_entry(void *parameter)
  542. {
  543. #define CPIN_RETRY 10
  544. #define CSQ_RETRY 10
  545. #define CREG_RETRY 10
  546. #define CGREG_RETRY 20
  547. at_response_t resp = RT_NULL;
  548. int i, qimux, qimode;
  549. char parsed_data[10];
  550. rt_err_t result = RT_EOK;
  551. resp = at_create_resp(128, 0, rt_tick_from_millisecond(300));
  552. if (!resp)
  553. {
  554. LOG_E("No memory for response structure!");
  555. result = -RT_ENOMEM;
  556. goto __exit;
  557. }
  558. LOG_D("Start initializing the M26/MC20 module");
  559. /* wait M26 startup finish */
  560. if (at_client_wait_connect(M26_WAIT_CONNECT_TIME))
  561. {
  562. result = -RT_ETIMEOUT;
  563. goto __exit;
  564. }
  565. /* disable echo */
  566. AT_SEND_CMD(resp, 0, 300, "ATE0");
  567. /* get module version */
  568. AT_SEND_CMD(resp, 0, 300, "ATI");
  569. /* show module version */
  570. for (i = 0; i < (int) resp->line_counts - 1; i++)
  571. {
  572. LOG_D("%s", at_resp_get_line(resp, i + 1));
  573. }
  574. /* check SIM card */
  575. for (i = 0; i < CPIN_RETRY; i++)
  576. {
  577. at_exec_cmd(at_resp_set_info(resp, 128, 2, rt_tick_from_millisecond(5000)), "AT+CPIN?");
  578. if (at_resp_get_line_by_kw(resp, "READY"))
  579. {
  580. LOG_D("SIM card detection success");
  581. break;
  582. }
  583. rt_thread_delay(rt_tick_from_millisecond(1000));
  584. }
  585. if (i == CPIN_RETRY)
  586. {
  587. LOG_E("SIM card detection failed!");
  588. result = -RT_ERROR;
  589. goto __exit;
  590. }
  591. /* waiting for dirty data to be digested */
  592. rt_thread_delay(rt_tick_from_millisecond(10));
  593. /* check signal strength */
  594. for (i = 0; i < CSQ_RETRY; i++)
  595. {
  596. AT_SEND_CMD(resp, 0, 300, "AT+CSQ");
  597. at_resp_parse_line_args_by_kw(resp, "+CSQ:", "+CSQ: %s", &parsed_data);
  598. if (strncmp(parsed_data, "99,99", sizeof(parsed_data)))
  599. {
  600. LOG_D("Signal strength: %s", parsed_data);
  601. break;
  602. }
  603. rt_thread_delay(rt_tick_from_millisecond(1000));
  604. }
  605. if (i == CSQ_RETRY)
  606. {
  607. LOG_E("Signal strength check failed (%s)", parsed_data);
  608. result = -RT_ERROR;
  609. goto __exit;
  610. }
  611. /* check the GSM network is registered */
  612. for (i = 0; i < CREG_RETRY; i++)
  613. {
  614. AT_SEND_CMD(resp, 0, 300, "AT+CREG?");
  615. at_resp_parse_line_args_by_kw(resp, "+CREG:", "+CREG: %s", &parsed_data);
  616. if (!strncmp(parsed_data, "0,1", sizeof(parsed_data)) || !strncmp(parsed_data, "0,5", sizeof(parsed_data)))
  617. {
  618. LOG_D("GSM network is registered (%s)", parsed_data);
  619. break;
  620. }
  621. rt_thread_delay(rt_tick_from_millisecond(1000));
  622. }
  623. if (i == CREG_RETRY)
  624. {
  625. LOG_E("The GSM network is register failed (%s)", parsed_data);
  626. result = -RT_ERROR;
  627. goto __exit;
  628. }
  629. /* check the GPRS network is registered */
  630. for (i = 0; i < CGREG_RETRY; i++)
  631. {
  632. AT_SEND_CMD(resp, 0, 300, "AT+CGREG?");
  633. at_resp_parse_line_args_by_kw(resp, "+CGREG:", "+CGREG: %s", &parsed_data);
  634. if (!strncmp(parsed_data, "0,1", sizeof(parsed_data)) || !strncmp(parsed_data, "0,5", sizeof(parsed_data)))
  635. {
  636. LOG_D("GPRS network is registered (%s)", parsed_data);
  637. break;
  638. }
  639. rt_thread_delay(rt_tick_from_millisecond(1000));
  640. }
  641. if (i == CGREG_RETRY)
  642. {
  643. LOG_E("The GPRS network is register failed (%s)", parsed_data);
  644. result = -RT_ERROR;
  645. goto __exit;
  646. }
  647. AT_SEND_CMD(resp, 0, 300, "AT+QIFGCNT=0");
  648. AT_SEND_CMD(resp, 0, 300, "AT+QICSGP=1, \"CMNET\"");
  649. AT_SEND_CMD(resp, 0, 300, "AT+QIMODE?");
  650. at_resp_parse_line_args_by_kw(resp, "+QIMODE:", "+QIMODE: %d", &qimode);
  651. if (qimode == 1)
  652. {
  653. AT_SEND_CMD(resp, 0, 300, "AT+QIMODE=0");
  654. }
  655. /* the device default response timeout is 40 seconds, but it set to 15 seconds is convenient to use. */
  656. AT_SEND_CMD(resp, 2, 20 * 1000, "AT+QIDEACT");
  657. /* Set to multiple connections */
  658. AT_SEND_CMD(resp, 0, 300, "AT+QIMUX?");
  659. at_resp_parse_line_args_by_kw(resp, "+QIMUX:", "+QIMUX: %d", &qimux);
  660. if (qimux == 0)
  661. {
  662. AT_SEND_CMD(resp, 0, 300, "AT+QIMUX=1");
  663. }
  664. AT_SEND_CMD(resp, 0, 300, "AT+QIREGAPP");
  665. /* the device default response timeout is 150 seconds, but it set to 20 seconds is convenient to use. */
  666. AT_SEND_CMD(resp, 0, 20 * 1000, "AT+QIACT");
  667. AT_SEND_CMD(resp, 2, 300, "AT+QILOCIP");
  668. __exit:
  669. if (resp)
  670. {
  671. at_delete_resp(resp);
  672. }
  673. if (!result)
  674. {
  675. LOG_I("AT network initialize success!");
  676. }
  677. else
  678. {
  679. LOG_E("AT network initialize failed (%d)!", result);
  680. }
  681. }
  682. int m26_net_init(void)
  683. {
  684. #ifdef PKG_AT_INIT_BY_THREAD
  685. rt_thread_t tid;
  686. tid = rt_thread_create("m26_net_init", m26_init_thread_entry, RT_NULL, M26_THREAD_STACK_SIZE, M26_THREAD_PRIORITY, 20);
  687. if (tid)
  688. {
  689. rt_thread_startup(tid);
  690. }
  691. else
  692. {
  693. LOG_E("Create AT initialization thread fail!");
  694. }
  695. #else
  696. m26_init_thread_entry(RT_NULL);
  697. #endif
  698. return RT_EOK;
  699. }
  700. int m26_ping(int argc, char **argv)
  701. {
  702. at_response_t resp = RT_NULL;
  703. if (argc != 2)
  704. {
  705. rt_kprintf("Please input: at_ping <host address>\n");
  706. return -RT_ERROR;
  707. }
  708. resp = at_create_resp(64, 0, rt_tick_from_millisecond(5000));
  709. if (!resp)
  710. {
  711. rt_kprintf("No memory for response structure!\n");
  712. return -RT_ENOMEM;
  713. }
  714. if (at_exec_cmd(resp, "AT+QPING=\"%s\"", argv[1]) < 0)
  715. {
  716. rt_kprintf("AT send ping commands error!\n");
  717. return -RT_ERROR;
  718. }
  719. if (resp)
  720. {
  721. at_delete_resp(resp);
  722. }
  723. return RT_EOK;
  724. }
  725. int m26_ifconfig(void)
  726. {
  727. at_response_t resp = RT_NULL;
  728. char resp_arg[AT_CMD_MAX_LEN] = { 0 };
  729. const char * resp_expr = "%s";
  730. rt_err_t result = RT_EOK;
  731. resp = at_create_resp(64, 2, rt_tick_from_millisecond(300));
  732. if (!resp)
  733. {
  734. rt_kprintf("No memory for response structure!\n");
  735. return -RT_ENOMEM;
  736. }
  737. if (at_exec_cmd(resp, "AT+QILOCIP") < 0)
  738. {
  739. rt_kprintf("AT send ip commands error!\n");
  740. result = RT_ERROR;
  741. goto __exit;
  742. }
  743. if (at_resp_parse_line_args(resp, 2, resp_expr, resp_arg) == 1)
  744. {
  745. rt_kprintf("IP address : %s\n", resp_arg);
  746. }
  747. else
  748. {
  749. rt_kprintf("Parse error, current line buff : %s\n", at_resp_get_line(resp, 2));
  750. result = RT_ERROR;
  751. goto __exit;
  752. }
  753. __exit:
  754. if (resp)
  755. {
  756. at_delete_resp(resp);
  757. }
  758. return result;
  759. }
  760. #ifdef FINSH_USING_MSH
  761. #include <finsh.h>
  762. MSH_CMD_EXPORT_ALIAS(m26_net_init, at_net_init, initialize AT network);
  763. MSH_CMD_EXPORT_ALIAS(m26_ping, at_ping, AT ping network host);
  764. MSH_CMD_EXPORT_ALIAS(m26_ifconfig, at_ifconfig, list the information of network interfaces);
  765. #endif
  766. static const struct at_device_ops m26_socket_ops = {
  767. m26_socket_connect,
  768. m26_socket_close,
  769. m26_socket_send,
  770. m26_domain_resolve,
  771. m26_socket_set_event_cb,
  772. };
  773. static int at_socket_device_init(void)
  774. {
  775. /* create current AT socket event */
  776. at_socket_event = rt_event_create("at_se", RT_IPC_FLAG_FIFO);
  777. if (at_socket_event == RT_NULL)
  778. {
  779. LOG_E("AT client port initialize failed! at_sock_event create failed!");
  780. return -RT_ENOMEM;
  781. }
  782. /* create current AT socket event lock */
  783. at_event_lock = rt_mutex_create("at_se", RT_IPC_FLAG_FIFO);
  784. if (at_event_lock == RT_NULL)
  785. {
  786. LOG_E("AT client port initialize failed! at_sock_lock create failed!");
  787. rt_event_delete(at_socket_event);
  788. return -RT_ENOMEM;
  789. }
  790. /* initialize AT client */
  791. at_client_init(AT_DEVICE_NAME, AT_DEVICE_RECV_BUFF_LEN);
  792. /* register URC data execution function */
  793. at_set_urc_table(urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
  794. /* initialize m26 network */
  795. m26_net_init();
  796. /* set m26 AT Socket options */
  797. at_socket_device_register(&m26_socket_ops);
  798. return RT_EOK;
  799. }
  800. INIT_APP_EXPORT(at_socket_device_init);
  801. #endif /* AT_DEVICE_M26 */