at_socket_sim800c.c 19 KB

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