at_socket_sim76xx.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. /*
  2. * File : at_socket_sim76xx.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-12-22 thomasonegd first version
  23. * 2019-03-06 thomasonegd fix udp connection.
  24. * 2019-03-08 thomasonegd add power_on & power_off api
  25. * 2019-05-14 chenyong multi AT socket client support
  26. */
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <at_device_sim76xx.h>
  30. #define LOG_TAG "at.skt"
  31. #include <at_log.h>
  32. #ifdef AT_DEVICE_USING_SIM76XX
  33. #define SIM76XX_MODULE_SEND_MAX_SIZE 1500
  34. #define SIM76XX_MAX_CONNECTIONS 10
  35. /* set real event by current socket and current state */
  36. #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event))
  37. /* AT socket event type */
  38. #define SIM76XX_EVENT_CONN_OK (1L << 0)
  39. #define SIM76XX_EVENT_SEND_OK (1L << 1)
  40. #define SIM76XX_EVENT_RECV_OK (1L << 2)
  41. #define SIM76XX_EVNET_CLOSE_OK (1L << 3)
  42. #define SIM76XX_EVENT_CONN_FAIL (1L << 4)
  43. #define SIM76XX_EVENT_SEND_FAIL (1L << 5)
  44. static at_evt_cb_t at_evt_cb_set[] =
  45. {
  46. [AT_SOCKET_EVT_RECV] = NULL,
  47. [AT_SOCKET_EVT_CLOSED] = NULL,
  48. };
  49. static char udp_ipstr[SIM76XX_MAX_CONNECTIONS][16];
  50. static int udp_port[SIM76XX_MAX_CONNECTIONS];
  51. /* unsolicited TCP/IP command<err> codes */
  52. static void at_tcp_ip_errcode_parse(int result)
  53. {
  54. switch(result)
  55. {
  56. case 0 : LOG_D("%d : operation succeeded ", result); break;
  57. case 1 : LOG_E("%d : UNetwork failure", result); break;
  58. case 2 : LOG_E("%d : Network not opened", result); break;
  59. case 3 : LOG_E("%d : Wrong parameter", result); break;
  60. case 4 : LOG_E("%d : Operation not supported", result); break;
  61. case 5 : LOG_E("%d : Failed to create socket", result); break;
  62. case 6 : LOG_E("%d : Failed to bind socket", result); break;
  63. case 7 : LOG_E("%d : TCP server is already listening", result); break;
  64. case 8 : LOG_E("%d : Busy", result); break;
  65. case 9 : LOG_E("%d : Sockets opened", result); break;
  66. case 10 : LOG_E("%d : Timeout ", result); break;
  67. case 11 : LOG_E("%d : DNS parse failed for AT+CIPOPEN", result); break;
  68. case 255 : LOG_E("%d : Unknown error", result); break;
  69. }
  70. }
  71. static int sim76xx_socket_event_send(struct at_device *device, uint32_t event)
  72. {
  73. return (int)rt_event_send(device->socket_event, event);
  74. }
  75. static int sim76xx_socket_event_recv(struct at_device *device, uint32_t event, uint32_t timeout, rt_uint8_t option)
  76. {
  77. int result = RT_EOK;
  78. rt_uint32_t recved;
  79. result = rt_event_recv(device->socket_event, event, option | RT_EVENT_FLAG_CLEAR, timeout, &recved);
  80. if (result != RT_EOK)
  81. {
  82. return -RT_ETIMEOUT;
  83. }
  84. return recved;
  85. }
  86. /**
  87. * close socket by AT commands.
  88. *
  89. * @param current socket
  90. *
  91. * @return 0: close socket success
  92. * -1: send AT commands error
  93. * -2: wait socket event timeout
  94. * -5: no memory
  95. */
  96. static int sim76xx_socket_close(struct at_socket *socket)
  97. {
  98. int result = RT_EOK;
  99. int activated = 0;
  100. uint8_t lnk_stat[10] = {0};
  101. at_response_t resp = RT_NULL;
  102. int device_socket = (int) socket->user_data;
  103. struct at_device *device = (struct at_device *) socket->device;
  104. resp = at_create_resp(64, 0, RT_TICK_PER_SECOND);
  105. if (resp == RT_NULL)
  106. {
  107. LOG_E("no memory for sim76xx device(%s) response structure.", device->name);
  108. return -RT_ENOMEM;
  109. }
  110. rt_thread_mdelay(100);
  111. /* check socket link_state */
  112. if (at_obj_exec_cmd(device->client, resp, "AT+CIPCLOSE?") < 0)
  113. {
  114. result = -RT_ERROR;
  115. goto __exit;
  116. }
  117. if (at_resp_parse_line_args_by_kw(resp, "+CIPCLOSE:", "+CIPCLOSE: %d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
  118. &lnk_stat[0], &lnk_stat[1], &lnk_stat[1], &lnk_stat[2], &lnk_stat[3], &lnk_stat[4],
  119. &lnk_stat[5], &lnk_stat[6], &lnk_stat[7], &lnk_stat[8], &lnk_stat[9]) < 0)
  120. {
  121. result = -RT_ERROR;
  122. goto __exit;
  123. }
  124. if (lnk_stat[device_socket])
  125. {
  126. /* close tcp or udp socket if connected */
  127. if (at_obj_exec_cmd(device->client, resp, "AT+CIPCLOSE=%d", device_socket) < 0)
  128. {
  129. result = -RT_ERROR;
  130. goto __exit;
  131. }
  132. }
  133. /* check the network open or not */
  134. if (at_obj_exec_cmd(device->client, resp, "AT+NETOPEN?") < 0)
  135. {
  136. result = -RT_ERROR;
  137. goto __exit;
  138. }
  139. if (at_resp_parse_line_args_by_kw(resp, "+NETOPEN:", "+NETOPEN: %d", &activated) < 0)
  140. {
  141. result = -RT_ERROR;
  142. goto __exit;
  143. }
  144. if (activated)
  145. {
  146. /* if already open,then close it */
  147. if (at_obj_exec_cmd(device->client, resp, "AT+NETCLOSE") < 0)
  148. {
  149. result = -RT_ERROR;
  150. goto __exit;
  151. }
  152. }
  153. __exit:
  154. if (resp)
  155. {
  156. at_delete_resp(resp);
  157. }
  158. return result;
  159. }
  160. /**
  161. * open packet network
  162. */
  163. static int sim76xx_network_socket_open(struct at_socket *socket)
  164. {
  165. int result = RT_EOK, activated = 0;
  166. at_response_t resp = RT_NULL;
  167. struct at_device *device = (struct at_device *) socket->device;
  168. resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND);
  169. if (resp == RT_NULL)
  170. {
  171. LOG_E("no memory for sim76xx device(%s) response structure.", device->name);
  172. return -RT_ENOMEM;
  173. }
  174. /* check the network open or not */
  175. if (at_obj_exec_cmd(device->client, resp, "AT+NETOPEN?") < 0)
  176. {
  177. result = -RT_ERROR;
  178. goto __exit;
  179. }
  180. if (at_resp_parse_line_args_by_kw(resp, "+NETOPEN:", "+NETOPEN: %d", &activated) < 0)
  181. {
  182. result = -RT_ERROR;
  183. goto __exit;
  184. }
  185. if (activated)
  186. {
  187. /* network socket is already opened */
  188. goto __exit;
  189. }
  190. else
  191. {
  192. /* if not opened the open it */
  193. if (at_obj_exec_cmd(device->client, resp, "AT+NETOPEN") < 0)
  194. {
  195. result = -RT_ERROR;
  196. goto __exit;
  197. }
  198. }
  199. __exit:
  200. if (resp)
  201. {
  202. at_delete_resp(resp);
  203. }
  204. return result;
  205. }
  206. /**
  207. * create TCP/UDP client or server connect by AT commands.
  208. *
  209. * @param socket current socket
  210. * @param ip server or client IP address
  211. * @param port server or client port
  212. * @param type connect socket type(tcp, udp)
  213. * @param is_client connection is client
  214. *
  215. * @return 0: connect success
  216. * -1: connect failed, send commands error or type error
  217. * -2: wait socket event timeout
  218. * -5: no memory
  219. */
  220. static int sim76xx_socket_connect(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client)
  221. {
  222. int result = RT_EOK, event_result = 0;
  223. rt_bool_t retryed = RT_FALSE;
  224. at_response_t resp = RT_NULL;
  225. int device_socket = (int) socket->user_data;
  226. struct at_device *device = (struct at_device *) socket->device;
  227. rt_mutex_t lock = device->client->lock;
  228. RT_ASSERT(ip);
  229. RT_ASSERT(port >= 0);
  230. resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND);
  231. if (resp == RT_NULL)
  232. {
  233. LOG_E("no memory for sim76xx device(%s) response structure.", device->name);
  234. return -RT_ENOMEM;
  235. }
  236. rt_mutex_take(lock, RT_WAITING_FOREVER);
  237. __retry:
  238. if (is_client)
  239. {
  240. /* open network socket first(AT+NETOPEN) */
  241. sim76xx_network_socket_open(socket);
  242. switch (type)
  243. {
  244. case AT_SOCKET_TCP:
  245. /* send AT commands to connect TCP server */
  246. if (at_obj_exec_cmd(device->client, resp, "AT+CIPOPEN=%d,\"TCP\",\"%s\",%d", device_socket, ip, port) < 0)
  247. {
  248. result = -RT_ERROR;
  249. }
  250. break;
  251. case AT_SOCKET_UDP:
  252. if (at_obj_exec_cmd(device->client, resp, "AT+CIPOPEN=%d,\"UDP\",,,%d", device_socket, port) < 0)
  253. {
  254. result = -RT_ERROR;
  255. }
  256. strcpy(udp_ipstr[device_socket], ip);
  257. udp_port[device_socket] = port;
  258. break;
  259. default:
  260. LOG_E("Not supported connect type : %d.", type);
  261. result = -RT_ERROR;
  262. goto __exit;
  263. }
  264. }
  265. /* waiting result event from AT URC, the device default connection timeout is 75 seconds, but it set to 10 seconds is convenient to use.*/
  266. if (sim76xx_socket_event_recv(device, SET_EVENT(device_socket, 0), 10 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
  267. {
  268. LOG_E("sim76xx device(%s) socket(%d) connect failed, wait connect result timeout.", device->name, device_socket);
  269. result = -RT_ETIMEOUT;
  270. goto __exit;
  271. }
  272. /* waiting OK or failed result */
  273. event_result = sim76xx_socket_event_recv(device, SIM76XX_EVENT_CONN_OK | SIM76XX_EVENT_CONN_FAIL,
  274. 1 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
  275. if (event_result < 0)
  276. {
  277. LOG_E("sim76xx device(%s) socket(%d) connect failed, wait connect OK|FAIL timeout.", device->name, socket);
  278. result = -RT_ETIMEOUT;
  279. goto __exit;
  280. }
  281. /* check result */
  282. if (event_result & SIM76XX_EVENT_CONN_FAIL)
  283. {
  284. if (!retryed)
  285. {
  286. LOG_E("socket (%d) connect failed, maybe the socket was not be closed at the last time and now will retry.", socket);
  287. if (sim76xx_socket_close(socket) < 0)
  288. {
  289. result = -RT_ERROR;
  290. goto __exit;
  291. }
  292. retryed = RT_TRUE;
  293. goto __retry;
  294. }
  295. LOG_E("socket (%d) connect failed, failed to establish a connection.", socket);
  296. result = -RT_ERROR;
  297. goto __exit;
  298. }
  299. if (result != RT_EOK && !retryed)
  300. {
  301. LOG_D("socket (%d) connect failed, maybe the socket was not be closed at the last time and now will retry.", socket);
  302. if (sim76xx_socket_close(socket) < 0)
  303. {
  304. goto __exit;
  305. }
  306. retryed = RT_TRUE;
  307. result = RT_EOK;
  308. goto __retry;
  309. }
  310. __exit:
  311. rt_mutex_release(lock);
  312. if (resp)
  313. {
  314. at_delete_resp(resp);
  315. }
  316. return result;
  317. }
  318. /**
  319. * send data to server or client by AT commands.
  320. *
  321. * @param socket current socket
  322. * @param buff send buffer
  323. * @param bfsz send buffer size
  324. * @param type connect socket type(tcp, udp)
  325. *
  326. * @return >=0: the size of send success
  327. * -1: send AT commands error or send data error
  328. * -2: waited socket event timeout
  329. * -5: no memory
  330. */
  331. static int sim76xx_socket_send(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type)
  332. {
  333. int result = RT_EOK;
  334. int event_result = 0;
  335. size_t cur_pkt_size = 0, sent_size = 0;
  336. at_response_t resp = RT_NULL;
  337. int device_socket = (int) socket->user_data;
  338. struct at_device *device = (struct at_device *) socket->device;
  339. struct at_device_sim76xx *sim76xx = (struct at_device_sim76xx *) device->user_data;
  340. rt_mutex_t lock = device->client->lock;
  341. RT_ASSERT(buff);
  342. RT_ASSERT(bfsz > 0);
  343. resp = at_create_resp(128, 2, 5 * RT_TICK_PER_SECOND);
  344. if (resp == RT_NULL)
  345. {
  346. LOG_E("no memory for sim76xx device(%s) response structure.", device->name);
  347. return -RT_ENOMEM;
  348. }
  349. rt_mutex_take(lock, RT_WAITING_FOREVER);
  350. /* set current socket for send URC event */
  351. sim76xx->user_data = (void *) device_socket;
  352. /* set AT client end sign to deal with '>' sign.*/
  353. at_obj_set_end_sign(device->client, '>');
  354. while (sent_size < bfsz)
  355. {
  356. if (bfsz - sent_size < SIM76XX_MODULE_SEND_MAX_SIZE)
  357. {
  358. cur_pkt_size = bfsz - sent_size;
  359. }
  360. else
  361. {
  362. cur_pkt_size = SIM76XX_MODULE_SEND_MAX_SIZE;
  363. }
  364. switch (socket->type)
  365. {
  366. case AT_SOCKET_TCP:
  367. /* send the "AT+CIPSEND" commands to AT server than receive the '>' response on the first line. */
  368. if (at_obj_exec_cmd(device->client, resp, "AT+CIPSEND=%d,%d", device_socket, cur_pkt_size) < 0)
  369. {
  370. result = -RT_ERROR;
  371. goto __exit;
  372. }
  373. break;
  374. case AT_SOCKET_UDP:
  375. /* send the "AT+CIPSEND" commands to AT server than receive the '>' response on the first line. */
  376. if (at_obj_exec_cmd(device->client, resp, "AT+CIPSEND=%d,%d,\"%s\",%d",
  377. device_socket, cur_pkt_size, udp_ipstr[device_socket], udp_port[device_socket]) < 0)
  378. {
  379. result = -RT_ERROR;
  380. goto __exit;
  381. }
  382. break;
  383. }
  384. /* send the real data to server or client */
  385. result = (int) at_client_send(buff + sent_size, cur_pkt_size);
  386. if (result == 0)
  387. {
  388. result = -RT_ERROR;
  389. goto __exit;
  390. }
  391. /* waiting result event from AT URC */
  392. if (sim76xx_socket_event_recv(device, SET_EVENT(device_socket, 0), 5 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
  393. {
  394. LOG_E("sim76xx device(%s) socket (%d) send failed, wait connect result timeout.", device->name, device_socket);
  395. result = -RT_ETIMEOUT;
  396. goto __exit;
  397. }
  398. /* waiting OK or failed result */
  399. event_result = sim76xx_socket_event_recv(device, SIM76XX_EVENT_SEND_OK | SIM76XX_EVENT_SEND_FAIL,
  400. 5 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
  401. if (event_result < 0)
  402. {
  403. LOG_E("sim76xx device(%s) socket(%d) send failed, wait connect OK|FAIL timeout.", device->name, device_socket);
  404. result = -RT_ETIMEOUT;
  405. goto __exit;
  406. }
  407. /* check result */
  408. if (event_result & SIM76XX_EVENT_SEND_FAIL)
  409. {
  410. LOG_E("sim76xx device(%s) socket(%d) send failed.", device->name, device_socket);
  411. result = -RT_ERROR;
  412. goto __exit;
  413. }
  414. if (type == AT_SOCKET_TCP)
  415. {
  416. //cur_pkt_size = cur_send_bfsz;
  417. }
  418. sent_size += cur_pkt_size;
  419. }
  420. __exit:
  421. /* reset the end sign for data */
  422. at_obj_set_end_sign(device->client, 0);
  423. rt_mutex_release(lock);
  424. if (resp)
  425. {
  426. at_delete_resp(resp);
  427. }
  428. return result;
  429. }
  430. /**
  431. * domain resolve by AT commands.
  432. *
  433. * @param name domain name
  434. * @param ip parsed IP address, it's length must be 16
  435. *
  436. * @return 0: domain resolve success
  437. * -2: wait socket event timeout
  438. * -5: no memory
  439. */
  440. static int sim76xx_domain_resolve(const char *name, char ip[16])
  441. {
  442. #define RESOLVE_RETRY 5
  443. int i, result = RT_EOK;
  444. char domain[32] = {0};
  445. char domain_ip[16] = {0};
  446. at_response_t resp = RT_NULL;
  447. struct at_device *device = RT_NULL;
  448. RT_ASSERT(name);
  449. RT_ASSERT(ip);
  450. device = at_device_get_first_initialized();
  451. if (device == RT_NULL)
  452. {
  453. LOG_E("get first initialized sim76xx device failed.");
  454. return -RT_ERROR;
  455. }
  456. resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND);
  457. if (resp == RT_NULL)
  458. {
  459. LOG_E("no memory for sim76xx device(%s) response structure.", device->name);
  460. return -RT_ENOMEM;
  461. }
  462. for (i = 0; i < RESOLVE_RETRY; i++)
  463. {
  464. if (at_obj_exec_cmd(device->client, resp, "AT+CDNSGIP=\"%s\"", name) < 0)
  465. {
  466. rt_thread_mdelay(200);
  467. /* resolve failed, maybe receive an URC CRLF */
  468. continue;
  469. }
  470. /* parse the third line of response data, get the IP address */
  471. /* +CDNSGIP: 1,"www.baidu.com","14.215.177.39" */
  472. if (at_resp_parse_line_args_by_kw(resp, "+CDNSGIP:", "+CDNSGIP: 1,%[^,],\"%[^\"]", domain, domain_ip) < 0)
  473. {
  474. rt_thread_mdelay(200);
  475. /* resolve failed, maybe receive an URC CRLF */
  476. continue;
  477. }
  478. if (rt_strlen(domain_ip) < 8)
  479. {
  480. rt_thread_mdelay(200);
  481. /* resolve failed, maybe receive an URC CRLF */
  482. continue;
  483. }
  484. else
  485. {
  486. rt_strncpy(ip, domain_ip, 15);
  487. ip[15] = '\0';
  488. break;
  489. }
  490. }
  491. if (i == RESOLVE_RETRY)
  492. {
  493. result = -RT_ERROR;
  494. }
  495. if (resp)
  496. {
  497. at_delete_resp(resp);
  498. }
  499. return result;
  500. }
  501. /**
  502. * set AT socket event notice callback
  503. *
  504. * @param event notice event
  505. * @param cb notice callback
  506. */
  507. static void sim76xx_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb)
  508. {
  509. if (event < (sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1])))
  510. {
  511. at_evt_cb_set[event] = cb;
  512. }
  513. }
  514. static void urc_send_func(struct at_client *client, const char *data, rt_size_t size)
  515. {
  516. int device_socket = 0, rqst_size, cnf_size;
  517. struct at_device *device = RT_NULL;
  518. char *client_name = client->device->parent.name;
  519. RT_ASSERT(data && size);
  520. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  521. if (device == RT_NULL)
  522. {
  523. LOG_E("get sim76xx device by client name(%s) failed.", client_name);
  524. return;
  525. }
  526. sscanf(data, "+CIPSEND: %d,%d,%d", &device_socket, &rqst_size, &cnf_size);
  527. //cur_send_bfsz = cnf_size;
  528. sim76xx_socket_event_send(device, SET_EVENT(device_socket, SIM76XX_EVENT_SEND_OK));
  529. }
  530. static void urc_ping_func(struct at_client *client, const char *data, rt_size_t size)
  531. {
  532. static int icmp_seq = 0;
  533. int i, j = 0;
  534. int result, recv_len, time, ttl;
  535. int sent, rcvd, lost, min, max, avg;
  536. char dst_ip[16] = {0};
  537. RT_ASSERT(data);
  538. for (i = 0; i < size; i++)
  539. {
  540. if (*(data + i) == '.')
  541. j++;
  542. }
  543. if (j != 0)
  544. {
  545. sscanf(data, "+CPING: %d,%[^,],%d,%d,%d", &result, dst_ip, &recv_len, &time, &ttl);
  546. if (result == 1)
  547. LOG_I("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms", recv_len, dst_ip, icmp_seq++, ttl, time);
  548. }
  549. else
  550. {
  551. sscanf(data, "+CPING: %d,%d,%d,%d,%d,%d,%d", &result, &sent, &rcvd, &lost, &min, &max, &avg);
  552. if (result == 3)
  553. LOG_I("%d sent %d received %d lost, min=%dms max=%dms average=%dms", sent, rcvd, lost, min, max, avg);
  554. if (result == 2)
  555. LOG_I("ping requst timeout");
  556. }
  557. }
  558. static void urc_connect_func(struct at_client *client, const char *data, rt_size_t size)
  559. {
  560. int device_socket = 0, result = 0;
  561. struct at_device *device = RT_NULL;
  562. char *client_name = client->device->parent.name;
  563. RT_ASSERT(data && size);
  564. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  565. if (device == RT_NULL)
  566. {
  567. LOG_E("get sim76xx device by client name(%s) failed.", client_name);
  568. return;
  569. }
  570. sscanf(data, "+CIPOPEN: %d,%d", &device_socket, &result);
  571. if (result == 0)
  572. {
  573. sim76xx_socket_event_send(device, SET_EVENT(device_socket, SIM76XX_EVENT_CONN_OK));
  574. }
  575. else
  576. {
  577. at_tcp_ip_errcode_parse(result);
  578. sim76xx_socket_event_send(device, SET_EVENT(device_socket, SIM76XX_EVENT_CONN_FAIL));
  579. }
  580. }
  581. static void urc_close_func(struct at_client *client, const char *data, rt_size_t size)
  582. {
  583. int device_socket = 0, reason = 0;
  584. struct at_socket *socket = RT_NULL;
  585. struct at_device *device = RT_NULL;
  586. char *client_name = client->device->parent.name;
  587. RT_ASSERT(data && size);
  588. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  589. if (device == RT_NULL)
  590. {
  591. LOG_E("get sim76xx device by client name(%s) failed.", device->name);
  592. return;
  593. }
  594. sscanf(data, "+IPCLOSE %d,%d", &device_socket, &reason);
  595. switch (reason)
  596. {
  597. case 0:
  598. LOG_E("socket is closed by local,active");
  599. break;
  600. case 1:
  601. LOG_E("socket is closed by remote,passive");
  602. break;
  603. case 2:
  604. LOG_E("socket is closed for sending timeout");
  605. break;
  606. }
  607. /* get AT socket object by device socket descriptor */
  608. socket = &(device->sockets[device_socket]);
  609. /* notice the socket is disconnect by remote */
  610. if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
  611. {
  612. at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, RT_NULL, 0);
  613. }
  614. }
  615. static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size)
  616. {
  617. rt_size_t bfsz = 0, temp_size = 0;
  618. rt_int32_t timeout;
  619. char *recv_buf = RT_NULL, temp[8] = {0};
  620. int device_socket = 0;
  621. struct at_socket *socket = RT_NULL;
  622. struct at_device *device = RT_NULL;
  623. struct at_device_sim76xx *sim76xx = RT_NULL;
  624. char *client_name = client->device->parent.name;
  625. RT_ASSERT(data && size);
  626. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  627. if (device == RT_NULL)
  628. {
  629. LOG_E("get sim76xx device by client name(%s) failed.", client_name);
  630. return;
  631. }
  632. sim76xx = (struct at_device_sim76xx *) device->user_data;
  633. device_socket = (int) sim76xx->user_data;
  634. /* get the current socket and receive buffer size by receive data */
  635. sscanf(data, "+IPD%d:", (int *)&bfsz);
  636. /* get receive timeout by receive buffer length */
  637. timeout = bfsz * 10;
  638. if (bfsz == 0)
  639. return;
  640. recv_buf = (char *) rt_calloc(1, bfsz);
  641. if (recv_buf == RT_NULL)
  642. {
  643. LOG_E("no memory for sim76xx device(%s) URC receive buffer(%d).", device->name, bfsz);
  644. /* read and clean the coming data */
  645. while (temp_size < bfsz)
  646. {
  647. if (bfsz - temp_size > sizeof(temp))
  648. {
  649. at_client_obj_recv(client, temp, sizeof(temp), timeout);
  650. }
  651. else
  652. {
  653. at_client_obj_recv(client, temp, bfsz - temp_size, timeout);
  654. }
  655. temp_size += sizeof(temp);
  656. }
  657. return;
  658. }
  659. /* sync receive data */
  660. if (at_client_obj_recv(client, recv_buf, bfsz, timeout) != bfsz)
  661. {
  662. LOG_E("sim76xx device(%s) receive size(%d) data failed.", device->name, bfsz);
  663. rt_free(recv_buf);
  664. return;
  665. }
  666. /* get AT socket object by device socket descriptor */
  667. socket = &(device->sockets[device_socket]);
  668. /* notice the receive buffer and buffer size */
  669. if (at_evt_cb_set[AT_SOCKET_EVT_RECV])
  670. {
  671. at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz);
  672. }
  673. }
  674. static struct at_urc urc_table[] =
  675. {
  676. {"+CIPSEND:", "\r\n", urc_send_func},
  677. {"+CIPOPEN:", "\r\n", urc_connect_func},
  678. {"+CPING:", "\r\n", urc_ping_func},
  679. {"+IPCLOSE", "\r\n", urc_close_func},
  680. {"+IPD", "\r\n", urc_recv_func},
  681. };
  682. int sim76xx_connect(int argc, char **argv)
  683. {
  684. int32_t port;
  685. if (argc != 3)
  686. {
  687. rt_kprintf("Please input: at_connect <host address>\n");
  688. return -RT_ERROR;
  689. }
  690. sscanf(argv[2], "%d", &port);
  691. sim76xx_socket_connect(at_get_socket(0), argv[1], port, AT_SOCKET_TCP, 1);
  692. return RT_EOK;
  693. }
  694. int sim76xx_close(int argc, char **argv)
  695. {
  696. if (sim76xx_socket_close(at_get_socket(0)) < 0)
  697. {
  698. rt_kprintf("sim76xx_socket_close fail\n");
  699. }
  700. else
  701. {
  702. rt_kprintf("sim76xx_socket_closeed\n");
  703. }
  704. return RT_EOK;
  705. }
  706. int sim76xx_send(int argc, char **argv)
  707. {
  708. const char *buff = "1234567890\n";
  709. if (sim76xx_socket_send(at_get_socket(0), buff, 11, AT_SOCKET_TCP) < 0)
  710. {
  711. rt_kprintf("sim76xx_socket_send fail\n");
  712. }
  713. return RT_EOK;
  714. }
  715. int sim76xx_domain(int argc, char **argv)
  716. {
  717. char ip[16];
  718. if (sim76xx_domain_resolve("www.baidu.com", ip) < 0)
  719. {
  720. rt_kprintf("sim76xx_socket_send fail\n");
  721. }
  722. else
  723. {
  724. rt_kprintf("baidu.com : %s\n", ip);
  725. }
  726. return RT_EOK;
  727. }
  728. #ifdef FINSH_USING_MSH
  729. #include <finsh.h>
  730. MSH_CMD_EXPORT_ALIAS(sim76xx_connect, at_connect, AT connect network host);
  731. MSH_CMD_EXPORT_ALIAS(sim76xx_close, at_close, AT close a socket);
  732. MSH_CMD_EXPORT_ALIAS(sim76xx_send, at_send, AT send a pack);
  733. MSH_CMD_EXPORT_ALIAS(sim76xx_domain, at_domain, AT domain resolve);
  734. #endif
  735. static const struct at_socket_ops sim76xx_socket_ops =
  736. {
  737. sim76xx_socket_connect,
  738. sim76xx_socket_close,
  739. sim76xx_socket_send,
  740. sim76xx_domain_resolve,
  741. sim76xx_socket_set_event_cb,
  742. };
  743. int sim76xx_socket_init(struct at_device *device)
  744. {
  745. RT_ASSERT(device);
  746. /* register URC data execution function */
  747. at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
  748. return RT_EOK;
  749. }
  750. int sim76xx_socket_class_register(struct at_device_class *class)
  751. {
  752. RT_ASSERT(class);
  753. class->socket_num = AT_DEVICE_SIM76XX_SOCKETS_NUM;
  754. class->socket_ops = &sim76xx_socket_ops;
  755. return RT_EOK;
  756. }
  757. #endif /* AT_DEVICE_SIM76XX */