at_socket_m26.c 20 KB

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