at_socket_n58.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-05-22 shuobatian first version
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <at_device_n58.h>
  13. #if !defined(AT_SW_VERSION_NUM) || AT_SW_VERSION_NUM < 0x10300
  14. #error "This AT Client version is older, please check and update latest AT Client!"
  15. #endif
  16. #define LOG_TAG "at.skt"
  17. #include <at_log.h>
  18. #if defined(AT_DEVICE_USING_N58) && defined(AT_USING_SOCKET)
  19. #define N58_MODULE_SEND_MAX_SIZE 1000
  20. /* set real event by current socket and current state */
  21. #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event))
  22. /* AT socket event type */
  23. #define N58_EVENT_CONN_OK (1L << 0)
  24. #define N58_EVENT_SEND_OK (1L << 1)
  25. #define N58_EVENT_RECV_OK (1L << 2)
  26. #define N58_EVNET_CLOSE_OK (1L << 3)
  27. #define N58_EVENT_CONN_FAIL (1L << 4)
  28. #define N58_EVENT_SEND_FAIL (1L << 5)
  29. static at_evt_cb_t at_evt_cb_set[] = {
  30. [AT_SOCKET_EVT_RECV] = NULL,
  31. [AT_SOCKET_EVT_CLOSED] = NULL,
  32. };
  33. static int n58_socket_event_send(struct at_device *device, uint32_t event)
  34. {
  35. return (int)rt_event_send(device->socket_event, event);
  36. }
  37. static int n58_socket_event_recv(struct at_device *device, uint32_t event, uint32_t timeout, rt_uint8_t option)
  38. {
  39. int result = RT_EOK;
  40. rt_uint32_t recved;
  41. result = rt_event_recv(device->socket_event, event, option | RT_EVENT_FLAG_CLEAR, timeout, &recved);
  42. if (result != RT_EOK)
  43. {
  44. return -RT_ETIMEOUT;
  45. }
  46. return recved;
  47. }
  48. /**
  49. * close socket by AT commands.
  50. *
  51. * @param current socket
  52. *
  53. * @return 0: close socket success
  54. * -1: send AT commands error
  55. * -2: wait socket event timeout
  56. * -5: no memory
  57. */
  58. static int n58_socket_close(struct at_socket *socket)
  59. {
  60. uint32_t event = 0;
  61. int result = RT_EOK;
  62. int device_socket = (int)socket->user_data;
  63. enum at_socket_type type_socket = socket->type;
  64. struct at_device *device = (struct at_device *)socket->device;
  65. /* clear socket close event */
  66. event = SET_EVENT(device_socket, N58_EVNET_CLOSE_OK);
  67. n58_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
  68. if (type_socket == AT_SOCKET_TCP)
  69. {
  70. if (at_obj_exec_cmd(device->client, NULL, "AT+TCPCLOSE=%d", device_socket) < 0)
  71. {
  72. result = -RT_ERROR;
  73. goto __exit;
  74. }
  75. }
  76. else if (type_socket == AT_SOCKET_UDP)
  77. {
  78. if (at_obj_exec_cmd(device->client, NULL, "AT+UDPCLOSE=%d", device_socket) < 0)
  79. {
  80. result = -RT_ERROR;
  81. goto __exit;
  82. }
  83. }
  84. if (n58_socket_event_recv(device, event, rt_tick_from_millisecond(300 * 3), RT_EVENT_FLAG_AND) < 0)
  85. {
  86. LOG_E("n58 device(%s) socket(%d) close failed, wait close OK timeout.", device->name, device_socket);
  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 n58_socket_connect(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client)
  108. {
  109. uint32_t event = 0;
  110. rt_bool_t retryed = RT_FALSE;
  111. at_response_t resp = RT_NULL;
  112. int result = RT_EOK, event_result = 0;
  113. int device_socket = (int)socket->user_data;
  114. struct at_device *device = (struct at_device *)socket->device;
  115. RT_ASSERT(ip);
  116. RT_ASSERT(port >= 0);
  117. resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND);
  118. if (resp == RT_NULL)
  119. {
  120. LOG_E("no memory for n58 device(%s) response structure.", device->name);
  121. return -RT_ENOMEM;
  122. }
  123. __retry:
  124. /* clear socket connect event */
  125. event = SET_EVENT(device_socket, N58_EVENT_CONN_OK | N58_EVENT_CONN_FAIL);
  126. n58_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
  127. if (is_client)
  128. {
  129. switch (type)
  130. {
  131. case AT_SOCKET_TCP:
  132. /* send AT commands(eg: AT+TCPSETUP=<n>,<ip>,<port>) to connect TCP server */
  133. if (at_obj_exec_cmd(device->client, RT_NULL,
  134. "AT+TCPSETUP=%d,%s,%d", device_socket, ip, port) < 0)
  135. {
  136. result = -RT_ERROR;
  137. goto __exit;
  138. }
  139. break;
  140. /* send AT commands(eg: AT+UDPSETUP=<n>,<ip>,<port>) to connect TCP server */
  141. case AT_SOCKET_UDP:
  142. if (at_obj_exec_cmd(device->client, RT_NULL,
  143. "AT+UDPSETUP=%d,%s,%d", device_socket, ip, port) < 0)
  144. {
  145. result = -RT_ERROR;
  146. goto __exit;
  147. }
  148. break;
  149. default:
  150. LOG_E("n58 device(%s) 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 (n58_socket_event_recv(device, SET_EVENT(device_socket, 0), 10 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
  157. {
  158. LOG_E("n58 device(%s) socket(%d) connect failed, 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 = n58_socket_event_recv(device,
  164. N58_EVENT_CONN_OK | N58_EVENT_CONN_FAIL, 1 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
  165. if (event_result < 0)
  166. {
  167. LOG_E("n58 device(%s) socket(%d) connect failed, wait connect OK|FAIL timeout.", device->name, device_socket);
  168. result = -RT_ETIMEOUT;
  169. goto __exit;
  170. }
  171. /* check result */
  172. if (event_result & N58_EVENT_CONN_FAIL)
  173. {
  174. if (retryed == RT_FALSE)
  175. {
  176. LOG_D("n58 device(%s) socket(%d) connect failed, maybe the socket was not be closed at the last time and now will retry.",
  177. device->name, device_socket);
  178. if (n58_socket_close(socket) < 0)
  179. {
  180. result = -RT_ERROR;
  181. goto __exit;
  182. }
  183. retryed = RT_TRUE;
  184. goto __retry;
  185. }
  186. LOG_E("n58 device(%s) 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 n58_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, 5 * RT_TICK_PER_SECOND);
  221. if (resp == RT_NULL)
  222. {
  223. LOG_E("no memory for n58 device(%s) response structure.", device->name);
  224. return -RT_ENOMEM;
  225. }
  226. rt_mutex_take(lock, RT_WAITING_FOREVER);
  227. /* clear socket connect event */
  228. event = SET_EVENT(device_socket, N58_EVENT_SEND_OK | N58_EVENT_SEND_FAIL);
  229. n58_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 < N58_MODULE_SEND_MAX_SIZE)
  235. {
  236. cur_pkt_size = bfsz - sent_size;
  237. }
  238. else
  239. {
  240. cur_pkt_size = N58_MODULE_SEND_MAX_SIZE;
  241. }
  242. /* send the "AT+QISEND" commands to AT server than receive the '>' response on the first line. */
  243. if (type == AT_SOCKET_TCP)
  244. {
  245. if (at_obj_exec_cmd(device->client, resp, "AT+TCPSEND=%d,%d", device_socket, cur_pkt_size) < 0)
  246. {
  247. result = -RT_ERROR;
  248. goto __exit;
  249. }
  250. }
  251. else if (type == AT_SOCKET_UDP)
  252. {
  253. if (at_obj_exec_cmd(device->client, resp, "AT+UDPSEND=%d,%d", device_socket, cur_pkt_size) < 0)
  254. {
  255. result = -RT_ERROR;
  256. goto __exit;
  257. }
  258. }
  259. /* send the real data to server or client */
  260. result = (int)at_client_obj_send(device->client, buff + sent_size, cur_pkt_size);
  261. if (result == 0)
  262. {
  263. result = -RT_ERROR;
  264. goto __exit;
  265. }
  266. /* waiting result event from AT URC */
  267. if (n58_socket_event_recv(device, SET_EVENT(device_socket, 0), 15 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
  268. {
  269. LOG_E("n58 device(%s) socket(%d) send failed, wait connect result timeout.", device->name, device_socket);
  270. result = -RT_ETIMEOUT;
  271. goto __exit;
  272. }
  273. /* waiting OK or failed result */
  274. event_result = n58_socket_event_recv(device,
  275. N58_EVENT_SEND_OK | N58_EVENT_SEND_FAIL, 5 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
  276. if (event_result < 0)
  277. {
  278. LOG_E("n58 device(%s) socket(%d) send failed, wait connect OK|FAIL timeout.", device->name, device_socket);
  279. result = -RT_ETIMEOUT;
  280. goto __exit;
  281. }
  282. /* check result */
  283. if (event_result & N58_EVENT_SEND_FAIL)
  284. {
  285. LOG_E("n58 device(%s) socket(%d) send failed.", device->name, device_socket);
  286. result = -RT_ERROR;
  287. goto __exit;
  288. }
  289. sent_size += cur_pkt_size;
  290. }
  291. __exit:
  292. /* reset the end sign for data conflict */
  293. at_obj_set_end_sign(device->client, 0);
  294. rt_mutex_release(lock);
  295. if (resp)
  296. {
  297. at_delete_resp(resp);
  298. }
  299. return result;
  300. }
  301. /**
  302. * domain resolve by AT commands.
  303. *
  304. * @param name domain name
  305. * @param ip parsed IP address, it's length must be 16
  306. *
  307. * @return 0: domain resolve success
  308. * -1: send AT commands error or response error
  309. * -2: wait socket event timeout
  310. * -5: no memory
  311. */
  312. static int n58_domain_resolve(const char *name, char ip[16])
  313. {
  314. #define RESOLVE_RETRY 5
  315. int i, result = RT_EOK;
  316. char recv_ip[16] = {0};
  317. at_response_t resp = RT_NULL;
  318. struct at_device *device = RT_NULL;
  319. RT_ASSERT(name);
  320. RT_ASSERT(ip);
  321. device = at_device_get_first_initialized();
  322. if (device == RT_NULL)
  323. {
  324. LOG_E("get first initialization n58 device failed.");
  325. return -RT_ERROR;
  326. }
  327. /* The maximum response time is 14 seconds, affected by network status */
  328. resp = at_create_resp(128, 4, 14 * RT_TICK_PER_SECOND);
  329. if (resp == RT_NULL)
  330. {
  331. LOG_E("no memory for n58 device(%s) response structure.", device->name);
  332. return -RT_ENOMEM;
  333. }
  334. for (i = 0; i < RESOLVE_RETRY; i++)
  335. {
  336. int err_code = 0;
  337. if (at_obj_exec_cmd(device->client, resp, "AT+CDNSGIP=\"%s\"", name) < 0)
  338. {
  339. result = -RT_ERROR;
  340. goto __exit;
  341. }
  342. /* domain name prase error options */
  343. if (at_resp_parse_line_args_by_kw(resp, "+CDNSGIP: 0", "+CDNSGIP: 0,%d", &err_code) > 0)
  344. {
  345. /* 3 - network error, 8 - dns common error */
  346. if (err_code == 3 || err_code == 8)
  347. {
  348. result = -RT_ERROR;
  349. goto __exit;
  350. }
  351. }
  352. /* parse the third line of response data, get the IP address */
  353. if (at_resp_parse_line_args_by_kw(resp, "+CDNSGIP:", "%*[^,],%*[^,],\"%[^\"]", recv_ip) < 0)
  354. {
  355. rt_thread_mdelay(100);
  356. /* resolve failed, maybe receive an URC CRLF */
  357. continue;
  358. }
  359. if (rt_strlen(recv_ip) < 8)
  360. {
  361. rt_thread_mdelay(100);
  362. /* resolve failed, maybe receive an URC CRLF */
  363. continue;
  364. }
  365. else
  366. {
  367. rt_thread_mdelay(10);
  368. rt_strncpy(ip, recv_ip, 15);
  369. ip[15] = '\0';
  370. break;
  371. }
  372. }
  373. __exit:
  374. if (resp)
  375. {
  376. at_delete_resp(resp);
  377. }
  378. return result;
  379. }
  380. /**
  381. * set AT socket event notice callback
  382. *
  383. * @param event notice event
  384. * @param cb notice callback
  385. */
  386. static void n58_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb)
  387. {
  388. if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1]))
  389. {
  390. at_evt_cb_set[event] = cb;
  391. }
  392. }
  393. static void urc_connect_func(struct at_client *client, const char *data, rt_size_t size)
  394. {
  395. int device_socket = 0;
  396. struct at_device *device = RT_NULL;
  397. char *client_name = client->device->parent.name;
  398. char constat[16] = {0};
  399. RT_ASSERT(data && size);
  400. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  401. if (device == RT_NULL)
  402. {
  403. LOG_E("get n58 device by client name(%s) failed.", client_name);
  404. return;
  405. }
  406. /* get the current socket by receive data */
  407. sscanf(data, "%*[^ ]%d,%s", &device_socket, constat);
  408. LOG_D("data:%s", data);
  409. LOG_D("socket:%d,constat:%s", device_socket, constat);
  410. if (strstr(constat, "OK"))
  411. {
  412. LOG_D("socket %d:connect ok!", device_socket);
  413. n58_socket_event_send(device, SET_EVENT(device_socket, N58_EVENT_CONN_OK));
  414. }
  415. else if (strstr(constat, "FAIL"))
  416. {
  417. LOG_D("socket %d:connect fail!", device_socket);
  418. n58_socket_event_send(device, SET_EVENT(device_socket, N58_EVENT_CONN_FAIL));
  419. }
  420. }
  421. static void urc_send_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 n58 device by client name(%s) failed.", client_name);
  431. return;
  432. }
  433. /* get the current socket by receive data */
  434. sscanf(data, "%*[^ ] %d,%*d\r\n", &device_socket);
  435. if (rt_strstr(data, "OPERATION"))
  436. {
  437. LOG_E("input data timeout!");
  438. n58_socket_event_send(device, SET_EVENT(device_socket, N58_EVENT_SEND_FAIL));
  439. }
  440. else if (rt_strstr(data, "ERROR")) //链路号错误
  441. {
  442. n58_socket_event_send(device, SET_EVENT(device_socket, N58_EVENT_SEND_FAIL));
  443. }
  444. else //没有错误就是成功
  445. {
  446. n58_socket_event_send(device, SET_EVENT(device_socket, N58_EVENT_SEND_OK));
  447. }
  448. }
  449. static void urc_close_func(struct at_client *client, const char *data, rt_size_t size)
  450. {
  451. int device_socket = 0;
  452. struct at_device *device = RT_NULL;
  453. char *client_name = client->device->parent.name;
  454. RT_ASSERT(data && size);
  455. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  456. if (device == RT_NULL)
  457. {
  458. LOG_E("get n58 device by client name(%s) failed.", client_name);
  459. return;
  460. }
  461. /* get the current socket by receive data */
  462. /* +TCPCLOSE: 1,OK */
  463. sscanf(data, "%*[^ ]%d,%*s", &device_socket);
  464. if (rt_strstr(data, "OK"))
  465. {
  466. n58_socket_event_send(device, SET_EVENT(device_socket, N58_EVNET_CLOSE_OK));
  467. }
  468. else if (rt_strstr(data, "Link Closed"))
  469. {
  470. struct at_socket *socket = RT_NULL;
  471. /* get AT socket object by device socket descriptor */
  472. socket = &(device->sockets[device_socket]);
  473. /* notice the socket is disconnect by remote */
  474. if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
  475. {
  476. at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, RT_NULL, 0);
  477. }
  478. }
  479. }
  480. static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size)
  481. {
  482. int device_socket = 0;
  483. rt_size_t bfsz = 0;
  484. int data_index = size - 1;
  485. char *recv_buf = RT_NULL;
  486. struct at_socket *socket = RT_NULL;
  487. struct at_device *device = RT_NULL;
  488. char *client_name = client->device->parent.name;
  489. RT_ASSERT(data && size);
  490. /* get the current socket and receive buffer size by receive data */
  491. sscanf(data, "%*[^ ] %d,%d,", &device_socket, (int *)&bfsz);
  492. recv_buf = (char *)rt_calloc(1, bfsz + 1);
  493. if (recv_buf == RT_NULL)
  494. {
  495. LOG_E("no memory for n58 device(%s) URC receive buffer (%d).", device->name, bfsz);
  496. return;
  497. }
  498. data_index -= 2; //"\r\n"移除
  499. recv_buf[bfsz] = '\0';
  500. for (int i = bfsz - 1; i >= 0; i--)
  501. {
  502. recv_buf[i] = data[data_index];
  503. data_index--;
  504. }
  505. /* get receive timeout by receive buffer length */
  506. LOG_D("recv socket:%d", device_socket);
  507. if (device_socket < 0 || bfsz == 0)
  508. {
  509. return;
  510. }
  511. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  512. if (device == RT_NULL)
  513. {
  514. LOG_E("get n58 device by client name(%s) failed.", client_name);
  515. return;
  516. }
  517. /* get AT socket object by device socket descriptor */
  518. socket = &(device->sockets[device_socket]);
  519. /* notice the receive buffer and buffer size */
  520. if (at_evt_cb_set[AT_SOCKET_EVT_RECV])
  521. {
  522. at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz);
  523. }
  524. }
  525. /* n58 device URC table for the socket data */
  526. static const struct at_urc urc_table[] =
  527. {
  528. {"+TCPSETUP:", "\r\n", urc_connect_func},
  529. {"+UDPSETUP:", "\r\n", urc_connect_func},
  530. {"+TCPSEND:", "\r\n", urc_send_func},
  531. {"+UDPSEND:", "\r\n", urc_send_func},
  532. {"+TCPCLOSE:", "\r\n", urc_close_func},
  533. {"+UDPCLOSE:", "\r\n", urc_close_func},
  534. {"+TCPRECV:", "\r\n", urc_recv_func},
  535. {"+UDPRECV:", "\r\n", urc_recv_func},
  536. };
  537. static const struct at_socket_ops n58_socket_ops =
  538. {
  539. n58_socket_connect,
  540. n58_socket_close,
  541. n58_socket_send,
  542. n58_domain_resolve,
  543. n58_socket_set_event_cb,
  544. #if defined(AT_SW_VERSION_NUM) && AT_SW_VERSION_NUM > 0x10300
  545. RT_NULL,
  546. #endif
  547. };
  548. int n58_socket_init(struct at_device *device)
  549. {
  550. RT_ASSERT(device);
  551. /* register URC data execution function */
  552. at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
  553. return RT_EOK;
  554. }
  555. int n58_socket_class_register(struct at_device_class *class)
  556. {
  557. RT_ASSERT(class);
  558. class->socket_num = AT_DEVICE_N58_SOCKETS_NUM;
  559. class->socket_ops = &n58_socket_ops;
  560. return RT_EOK;
  561. }
  562. #endif /* AT_DEVICE_USING_n58 && AT_USING_SOCKET */