at_socket_m6315.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. /*
  2. * File : at_socket_m6315.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 malongwei first version
  23. * 2019-05-13 chenyong multi AT socket client support
  24. */
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <at_device_m6315.h>
  28. #define LOG_TAG "at.skt.m6315"
  29. #include <at_log.h>
  30. #if defined(AT_DEVICE_USING_M6315) && defined(AT_USING_SOCKET)
  31. #define M6315_MODULE_SEND_MAX_SIZE 1000
  32. /* set real event by current socket and current state */
  33. #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event))
  34. /* AT socket event type */
  35. #define M6315_EVENT_CONN_OK (1L << 0)
  36. #define M6315_EVENT_SEND_OK (1L << 1)
  37. #define M6315_EVENT_RECV_OK (1L << 2)
  38. #define M6315_EVNET_CLOSE_OK (1L << 3)
  39. #define M6315_EVENT_CONN_FAIL (1L << 4)
  40. #define M6315_EVENT_SEND_FAIL (1L << 5)
  41. #define M6315_EVENT_CONN_ALREADY (1L << 6)
  42. static at_evt_cb_t at_evt_cb_set[] = {
  43. [AT_SOCKET_EVT_RECV] = NULL,
  44. [AT_SOCKET_EVT_CLOSED] = NULL,
  45. };
  46. static int m6315_socket_event_send(struct at_device *device, uint32_t event)
  47. {
  48. return (int) rt_event_send(device->socket_event, event);
  49. }
  50. static int m6315_socket_event_recv(struct at_device *device, uint32_t event, uint32_t timeout, rt_uint8_t option)
  51. {
  52. int result = RT_EOK;
  53. rt_uint32_t recved;
  54. result = rt_event_recv(device->socket_event, event, option | RT_EVENT_FLAG_CLEAR, timeout, &recved);
  55. if (result != RT_EOK)
  56. {
  57. return -RT_ETIMEOUT;
  58. }
  59. return recved;
  60. }
  61. /**
  62. * close socket by AT commands.
  63. *
  64. * @param current socket
  65. *
  66. * @return 0: close socket success
  67. * -1: send AT commands error
  68. * -2: wait socket event timeout
  69. * -5: no memory
  70. */
  71. static int m6315_socket_close(struct at_socket *socket)
  72. {
  73. uint32_t event = 0;
  74. int result = RT_EOK;
  75. int device_socket = (int) socket->user_data;
  76. struct at_device *device = (struct at_device *) socket->device;
  77. /* clear socket close event */
  78. event = SET_EVENT(device_socket, M6315_EVNET_CLOSE_OK);
  79. m6315_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
  80. if (at_obj_exec_cmd(device->client, NULL, "AT+QICLOSE=%d", device_socket) < 0)
  81. {
  82. result = -RT_ERROR;
  83. goto __exit;
  84. }
  85. if (m6315_socket_event_recv(device, event, rt_tick_from_millisecond(300*3), RT_EVENT_FLAG_AND) < 0)
  86. {
  87. LOG_E("%s device socket(%d) wait close OK timeout.", device->name, device_socket);
  88. result = -RT_ETIMEOUT;
  89. goto __exit;
  90. }
  91. __exit:
  92. return result;
  93. }
  94. /**
  95. * create TCP/UDP client or server connect by AT commands.
  96. *
  97. * @param socket current socket
  98. * @param ip server or client IP address
  99. * @param port server or client port
  100. * @param type connect socket type(tcp, udp)
  101. * @param is_client connection is client
  102. *
  103. * @return 0: connect success
  104. * -1: connect failed, send commands error or type error
  105. * -2: wait socket event timeout
  106. * -5: no memory
  107. */
  108. static int m6315_socket_connect(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client)
  109. {
  110. uint32_t event = 0;
  111. rt_bool_t retryed = RT_FALSE;
  112. at_response_t resp = RT_NULL;
  113. int result = RT_EOK, event_result = 0;
  114. int device_socket = (int) socket->user_data;
  115. struct at_device *device = (struct at_device *) socket->device;
  116. RT_ASSERT(ip);
  117. RT_ASSERT(port >= 0);
  118. resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND);
  119. if (resp == RT_NULL)
  120. {
  121. LOG_E("no memory for resp create.");
  122. return -RT_ENOMEM;
  123. }
  124. __retry:
  125. /* clear socket connect event */
  126. event = SET_EVENT(device_socket, M6315_EVENT_CONN_OK | M6315_EVENT_CONN_FAIL | M6315_EVENT_CONN_ALREADY);
  127. m6315_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
  128. if (is_client)
  129. {
  130. switch (type)
  131. {
  132. case AT_SOCKET_TCP:
  133. /* send AT commands(eg: AT+QIOPEN=0,"TCP","x.x.x.x", 1234) to connect TCP server */
  134. if (at_obj_exec_cmd(device->client, RT_NULL,
  135. "AT+QIOPEN=%d,\"TCP\",\"%s\",%d", device_socket, ip, port) < 0)
  136. {
  137. result = -RT_ERROR;
  138. goto __exit;
  139. }
  140. break;
  141. case AT_SOCKET_UDP:
  142. if (at_obj_exec_cmd(device->client, RT_NULL,
  143. "AT+QIOPEN=%d,\"UDP\",\"%s\",%d", device_socket, ip, port) < 0)
  144. {
  145. result = -RT_ERROR;
  146. goto __exit;
  147. }
  148. break;
  149. default:
  150. LOG_E("%s device not supported connect type : %d.", device->name, type);
  151. result = -RT_ERROR;
  152. goto __exit;
  153. }
  154. }
  155. /* waiting result event from AT URC, the device default connection timeout is 75 seconds, but it set to 10 seconds is convenient to use */
  156. if (m6315_socket_event_recv(device, SET_EVENT(device_socket, 0), 10 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
  157. {
  158. LOG_E("%s device socket(%d) wait connect result timeout.", device->name, device_socket);
  159. result = -RT_ETIMEOUT;
  160. goto __exit;
  161. }
  162. /* waiting OK or failed result */
  163. event_result = m6315_socket_event_recv(device,
  164. M6315_EVENT_CONN_OK | M6315_EVENT_CONN_FAIL | M6315_EVENT_CONN_ALREADY, 1 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
  165. if (event_result < 0)
  166. {
  167. LOG_E("%s device socket(%d) wait connect OK|FAIL|ALREADY timeout.", device->name, device_socket);
  168. result = -RT_ETIMEOUT;
  169. goto __exit;
  170. }
  171. /* check result */
  172. if (event_result & M6315_EVENT_CONN_FAIL)
  173. {
  174. if (retryed == RT_FALSE)
  175. {
  176. LOG_D("%s device socket(%d) connect failed, the socket was not be closedand now will connect retry.",
  177. device->name, device_socket);
  178. if (m6315_socket_close(socket) < 0)
  179. {
  180. result = -RT_ERROR;
  181. goto __exit;
  182. }
  183. retryed = RT_TRUE;
  184. goto __retry;
  185. }
  186. LOG_E("%s device socket(%d) connect failed.", device->name, device_socket);
  187. result = -RT_ERROR;
  188. goto __exit;
  189. }
  190. __exit:
  191. if (resp)
  192. {
  193. at_delete_resp(resp);
  194. }
  195. return result;
  196. }
  197. /**
  198. * send data to server or client by AT commands.
  199. *
  200. * @param socket current socket
  201. * @param buff send buffer
  202. * @param bfsz send buffer size
  203. * @param type connect socket type(tcp, udp)
  204. *
  205. * @return >=0: the size of send success
  206. * -1: send AT commands error or send data error
  207. * -2: waited socket event timeout
  208. * -5: no memory
  209. */
  210. static int m6315_socket_send(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type)
  211. {
  212. uint32_t event = 0;
  213. int result = RT_EOK, event_result = 0;
  214. size_t cur_pkt_size = 0, sent_size = 0;
  215. at_response_t resp = RT_NULL;
  216. int device_socket = (int) socket->user_data;
  217. struct at_device *device = (struct at_device *) socket->device;
  218. rt_mutex_t lock = device->client->lock;
  219. RT_ASSERT(buff);
  220. resp = at_create_resp(128, 2, 20 * RT_TICK_PER_SECOND);
  221. if (resp == RT_NULL)
  222. {
  223. LOG_E("no memory for resp create.");
  224. return -RT_ENOMEM;
  225. }
  226. rt_mutex_take(lock, RT_WAITING_FOREVER);
  227. /* clear socket connect event */
  228. event = SET_EVENT(device_socket, M6315_EVENT_SEND_OK | M6315_EVENT_SEND_FAIL);
  229. m6315_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
  230. /* set AT client end sign to deal with '>' sign.*/
  231. at_obj_set_end_sign(device->client, '>');
  232. while (sent_size < bfsz)
  233. {
  234. if (bfsz - sent_size < M6315_MODULE_SEND_MAX_SIZE)
  235. {
  236. cur_pkt_size = bfsz - sent_size;
  237. }
  238. else
  239. {
  240. cur_pkt_size = M6315_MODULE_SEND_MAX_SIZE;
  241. }
  242. /* send the "AT+QISEND" commands to AT server than receive the '>' response on the first line. */
  243. if (at_obj_exec_cmd(device->client, resp, "AT+QISEND=%d,%d", device_socket, cur_pkt_size) < 0)
  244. {
  245. result = -RT_ERROR;
  246. goto __exit;
  247. }
  248. /* send the real data to server or client */
  249. result = (int) at_client_obj_send(device->client, buff + sent_size, cur_pkt_size);
  250. if (result == 0)
  251. {
  252. result = -RT_ERROR;
  253. goto __exit;
  254. }
  255. /* waiting result event from AT URC */
  256. if (m6315_socket_event_recv(device, SET_EVENT(device_socket, 0), 20 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
  257. {
  258. LOG_E("%s device socket(%d) wait send result timeout.", device->name, device_socket);
  259. result = -RT_ETIMEOUT;
  260. goto __exit;
  261. }
  262. /* waiting OK or failed result */
  263. event_result = m6315_socket_event_recv(device,
  264. M6315_EVENT_SEND_OK | M6315_EVENT_SEND_FAIL, 15 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
  265. if (event_result < 0)
  266. {
  267. LOG_E("%s device socket(%d) wait send connect OK|FAIL timeout.", device->name, device_socket);
  268. result = -RT_ETIMEOUT;
  269. goto __exit;
  270. }
  271. /* check result */
  272. if (event_result & M6315_EVENT_SEND_FAIL)
  273. {
  274. LOG_E("%s device socket(%d) send failed.", device->name, device_socket);
  275. result = -RT_ERROR;
  276. goto __exit;
  277. }
  278. sent_size += cur_pkt_size;
  279. }
  280. __exit:
  281. /* reset the end sign for data conflict */
  282. at_obj_set_end_sign(device->client, 0);
  283. rt_mutex_release(lock);
  284. if (resp)
  285. {
  286. at_delete_resp(resp);
  287. }
  288. return result > 0 ? sent_size : result;
  289. }
  290. /**
  291. * domain resolve by AT commands.
  292. *
  293. * @param name domain name
  294. * @param ip parsed IP address, it's length must be 16
  295. *
  296. * @return 0: domain resolve success
  297. * -1: send AT commands error or response error
  298. * -2: wait socket event timeout
  299. * -5: no memory
  300. */
  301. static int m6315_domain_resolve(const char *name, char ip[16])
  302. {
  303. #define RESOLVE_RETRY 5
  304. int i, result = RT_EOK;
  305. char recv_ip[16] = { 0 };
  306. at_response_t resp = RT_NULL;
  307. struct at_device *device = RT_NULL;
  308. RT_ASSERT(name);
  309. RT_ASSERT(ip);
  310. device = at_device_get_first_initialized();
  311. if (device == RT_NULL)
  312. {
  313. LOG_E("get first init device failed.");
  314. return -RT_ERROR;
  315. }
  316. /* The maximum response time is 20 seconds, affected by network status */
  317. resp = at_create_resp(128, 4, 20 * RT_TICK_PER_SECOND);
  318. if (resp == RT_NULL)
  319. {
  320. LOG_E("no memory for resp create.");
  321. return -RT_ENOMEM;
  322. }
  323. for (i = 0; i < RESOLVE_RETRY; i++)
  324. {
  325. if (at_obj_exec_cmd(device->client, resp, "AT+QIDNSGIP=\"%s\"", name) < 0) //MODIFY name
  326. {
  327. result = -RT_ERROR;
  328. goto __exit;
  329. }
  330. if (at_resp_parse_line_args(resp, 4, "%s", recv_ip) < 0)
  331. {
  332. rt_thread_mdelay(100);
  333. /* resolve failed, maybe receive an URC CRLF */
  334. continue;
  335. }
  336. if (rt_strlen(recv_ip) < 8)
  337. {
  338. rt_thread_mdelay(100);
  339. /* resolve failed, maybe receive an URC CRLF */
  340. continue;
  341. }
  342. else
  343. {
  344. rt_thread_mdelay(10);
  345. rt_strncpy(ip, recv_ip, 15);
  346. ip[15] = '\0';
  347. break;
  348. }
  349. }
  350. __exit:
  351. if (resp)
  352. {
  353. at_delete_resp(resp);
  354. }
  355. return result;
  356. }
  357. /**
  358. * set AT socket event notice callback
  359. *
  360. * @param event notice event
  361. * @param cb notice callback
  362. */
  363. static void m6315_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb)
  364. {
  365. if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1]))
  366. {
  367. at_evt_cb_set[event] = cb;
  368. }
  369. }
  370. static void urc_connect_func(struct at_client *client, const char *data, rt_size_t size)
  371. {
  372. int device_socket = 0;
  373. struct at_device *device = RT_NULL;
  374. char *client_name = client->device->parent.name;
  375. RT_ASSERT(data && size);
  376. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  377. if (device == RT_NULL)
  378. {
  379. LOG_E("get device(%s) failed.", client_name);
  380. return;
  381. }
  382. if (strstr(data, "ALREADY CONNECT"))
  383. {
  384. m6315_socket_event_send(device, SET_EVENT(device_socket, M6315_EVENT_CONN_ALREADY));
  385. return;
  386. }
  387. /* get the current socket by receive data */
  388. sscanf(data, "%d,%*s", &device_socket);
  389. if (strstr(data, "CONNECT OK"))
  390. {
  391. m6315_socket_event_send(device, SET_EVENT(device_socket, M6315_EVENT_CONN_OK));
  392. }
  393. else if (strstr(data, "CONNECT FAIL"))
  394. {
  395. m6315_socket_event_send(device, SET_EVENT(device_socket, M6315_EVENT_CONN_FAIL));
  396. }
  397. }
  398. static void urc_send_func(struct at_client *client, const char *data, rt_size_t size)
  399. {
  400. int device_socket = 0;
  401. struct at_device *device = RT_NULL;
  402. char *client_name = client->device->parent.name;
  403. RT_ASSERT(data && size);
  404. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  405. if (device == RT_NULL)
  406. {
  407. LOG_E("get device(%s) failed.", client_name);
  408. return;
  409. }
  410. /* get the current socket by receive data */
  411. // sscanf(data, "%d,%*s", &device_socket);
  412. if (rt_strstr(data, "SEND OK"))
  413. {
  414. m6315_socket_event_send(device, SET_EVENT(device_socket, M6315_EVENT_SEND_OK));
  415. }
  416. else if (rt_strstr(data, "SEND FAIL"))
  417. {
  418. m6315_socket_event_send(device, SET_EVENT(device_socket, M6315_EVENT_SEND_FAIL));
  419. }
  420. }
  421. static void urc_close_func(struct at_client *client, const char *data, rt_size_t size)
  422. {
  423. int device_socket = 0;
  424. struct at_device *device = RT_NULL;
  425. char *client_name = client->device->parent.name;
  426. RT_ASSERT(data && size);
  427. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  428. if (device == RT_NULL)
  429. {
  430. LOG_E("get device(%s) failed.", client_name);
  431. return;
  432. }
  433. /* get the current socket by receive data */
  434. sscanf(data, "%d,%*s", &device_socket);
  435. if (rt_strstr(data, "CLOSE OK"))
  436. {
  437. m6315_socket_event_send(device, SET_EVENT(device_socket, M6315_EVNET_CLOSE_OK));
  438. }
  439. else if (rt_strstr(data, "CLOSED"))
  440. {
  441. struct at_socket *socket = RT_NULL;
  442. /* get AT socket object by device socket descriptor */
  443. socket = &(device->sockets[device_socket]);
  444. /* notice the socket is disconnect by remote */
  445. if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
  446. {
  447. at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, RT_NULL, 0);
  448. }
  449. }
  450. }
  451. static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size)
  452. {
  453. int device_socket = 0;
  454. rt_int32_t timeout;
  455. rt_size_t bfsz = 0, temp_size = 0;
  456. char *recv_buf = RT_NULL, temp[8] = {0};
  457. struct at_socket *socket = RT_NULL;
  458. struct at_device *device = RT_NULL;
  459. char *client_name = client->device->parent.name;
  460. RT_ASSERT(data && size);
  461. /* get the current socket and receive buffer size by receive data */
  462. sscanf(data, "+RECEIVE:%d,%d:", &device_socket, (int *) &bfsz);
  463. /* set receive timeout by receive buffer length, not less than 10 ms */
  464. timeout = bfsz > 10 ? bfsz : 10;
  465. if (device_socket < 0 || bfsz == 0)
  466. {
  467. return;
  468. }
  469. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  470. if (device == RT_NULL)
  471. {
  472. LOG_E("get device(%s) failed.", client_name);
  473. return;
  474. }
  475. recv_buf = (char *) rt_calloc(1, bfsz);
  476. if (recv_buf == RT_NULL)
  477. {
  478. LOG_E("no memory for receive buffer(%d).", bfsz);
  479. /* read and clean the coming data */
  480. while (temp_size < bfsz)
  481. {
  482. if (bfsz - temp_size > sizeof(temp))
  483. {
  484. at_client_obj_recv(client, temp, sizeof(temp), timeout);
  485. }
  486. else
  487. {
  488. at_client_obj_recv(client, temp, bfsz - temp_size, timeout);
  489. }
  490. temp_size += sizeof(temp);
  491. }
  492. return;
  493. }
  494. /* sync receive data */
  495. if (at_client_obj_recv(client, recv_buf, bfsz, timeout) != bfsz)
  496. {
  497. LOG_E("%s device receive size(%d) data failed.", device->name, bfsz);
  498. rt_free(recv_buf);
  499. return;
  500. }
  501. /* get AT socket object by device socket descriptor */
  502. socket = &(device->sockets[device_socket]);
  503. /* notice the receive buffer and buffer size */
  504. if (at_evt_cb_set[AT_SOCKET_EVT_RECV])
  505. {
  506. at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz);
  507. }
  508. }
  509. /* m6315 device URC table for the socket data */
  510. static const struct at_urc urc_table[] =
  511. {
  512. {"", ", CONNECT OK\r\n", urc_connect_func},
  513. {"", ", CONNECT FAIL\r\n", urc_connect_func},
  514. {"", "ALREADY CONNECT\r\n", urc_connect_func},
  515. {"", "SEND OK\r\n", urc_send_func},
  516. {"", "SEND FAIL\r\n", urc_send_func},
  517. {"", ", CLOSE OK\r\n", urc_close_func},
  518. {"", ", CLOSED\r\n", urc_close_func},
  519. {"+RECEIVE:", "\r\n", urc_recv_func},
  520. };
  521. static const struct at_socket_ops m6315_socket_ops =
  522. {
  523. m6315_socket_connect,
  524. m6315_socket_close,
  525. m6315_socket_send,
  526. m6315_domain_resolve,
  527. m6315_socket_set_event_cb,
  528. };
  529. int m6315_socket_init(struct at_device *device)
  530. {
  531. RT_ASSERT(device);
  532. /* register URC data execution function */
  533. at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
  534. return RT_EOK;
  535. }
  536. int m6315_socket_class_register(struct at_device_class *class)
  537. {
  538. RT_ASSERT(class);
  539. class->socket_num = AT_DEVICE_M6315_SOCKETS_NUM;
  540. class->socket_ops = &m6315_socket_ops;
  541. return RT_EOK;
  542. }
  543. #endif /* AT_DEVICE_USING_M6315 && AT_USING_SOCKET */