at_device.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-05-08 chenyong first version
  9. */
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <at_device.h>
  13. #define DBG_TAG "at.dev"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. /* The global list of at device */
  17. static rt_slist_t at_device_list = RT_SLIST_OBJECT_INIT(at_device_list);
  18. /* The global list of at device class */
  19. static rt_slist_t at_device_class_list = RT_SLIST_OBJECT_INIT(at_device_class_list);
  20. /**
  21. * This function will get the first initialized AT device.
  22. *
  23. * @return the AT device structure pointer
  24. */
  25. struct at_device *at_device_get_first_initialized(void)
  26. {
  27. rt_base_t level;
  28. rt_slist_t *node = RT_NULL;
  29. struct at_device *device = RT_NULL;
  30. level = rt_hw_interrupt_disable();
  31. rt_slist_for_each(node, &at_device_list)
  32. {
  33. device = rt_slist_entry(node, struct at_device, list);
  34. if (device && device->is_init == RT_TRUE)
  35. {
  36. rt_hw_interrupt_enable(level);
  37. return device;
  38. }
  39. }
  40. rt_hw_interrupt_enable(level);
  41. return RT_NULL;
  42. }
  43. /**
  44. * This function will get AT device by device name.
  45. *
  46. * @param type the name type
  47. * @param name the device name or the client name
  48. *
  49. * @return the AT device structure pointer
  50. */
  51. struct at_device *at_device_get_by_name(int type, const char *name)
  52. {
  53. rt_base_t level;
  54. rt_slist_t *node = RT_NULL;
  55. struct at_device *device = RT_NULL;
  56. RT_ASSERT(name);
  57. level = rt_hw_interrupt_disable();
  58. rt_slist_for_each(node, &at_device_list)
  59. {
  60. device = rt_slist_entry(node, struct at_device, list);
  61. if (device)
  62. {
  63. if (((type == AT_DEVICE_NAMETYPE_DEVICE) || (type == AT_DEVICE_NAMETYPE_NETDEV)) &&
  64. (rt_strncmp(device->name, name, rt_strlen(name)) == 0))
  65. {
  66. rt_hw_interrupt_enable(level);
  67. return device;
  68. }
  69. else if ((type == AT_DEVICE_NAMETYPE_CLIENT) &&
  70. (rt_strncmp(device->client->device->parent.name, name, rt_strlen(name)) == 0))
  71. {
  72. rt_hw_interrupt_enable(level);
  73. return device;
  74. }
  75. }
  76. }
  77. rt_hw_interrupt_enable(level);
  78. return RT_NULL;
  79. }
  80. #ifdef AT_USING_SOCKET
  81. /**
  82. * This function will get AT device by ip address.
  83. *
  84. * @param ip_addr input ip address
  85. * network
  86. * @return != NULL: network interface device object
  87. * NULL: get failed
  88. */
  89. struct at_device *at_device_get_by_ipaddr(ip_addr_t *ip_addr)
  90. {
  91. rt_base_t level;
  92. rt_slist_t *node = RT_NULL;
  93. struct at_device *device = RT_NULL;
  94. level = rt_hw_interrupt_disable();
  95. rt_slist_for_each(node, &at_device_list)
  96. {
  97. device = rt_slist_entry(node, struct at_device, list);
  98. if (device && ip_addr_cmp(ip_addr, &(device->netdev->ip_addr)))
  99. {
  100. rt_hw_interrupt_enable(level);
  101. return device;
  102. }
  103. }
  104. rt_hw_interrupt_enable(level);
  105. return RT_NULL;
  106. }
  107. #endif /* AT_USING_SOCKET */
  108. /**
  109. * This function will perform a variety of control functions on AT devices.
  110. *
  111. * @param device the pointer of AT device structure
  112. * @param cmd the command sent to AT device
  113. * @param arg the argument of command
  114. *
  115. * @return = 0: perform successfully
  116. * < 0: perform failed
  117. */
  118. int at_device_control(struct at_device *device, int cmd, void *arg)
  119. {
  120. if (device->class->device_ops->control)
  121. {
  122. return device->class->device_ops->control(device, cmd, arg);
  123. }
  124. else
  125. {
  126. LOG_W("AT device(%s) not support control operations.", device->name);
  127. return RT_EOK;
  128. }
  129. }
  130. /**
  131. * This function registers an AT device class with specified device class ID.
  132. *
  133. * @param class the pointer of AT device class structure
  134. * @param class_id AT device class ID
  135. *
  136. * @return 0: register successfully
  137. */
  138. int at_device_class_register(struct at_device_class *class, uint16_t class_id)
  139. {
  140. rt_base_t level;
  141. RT_ASSERT(class);
  142. /* Fill AT device class */
  143. class->class_id = class_id;
  144. /* Initialize current AT device class single list */
  145. rt_slist_init(&(class->list));
  146. level = rt_hw_interrupt_disable();
  147. /* Add current AT device class to list */
  148. rt_slist_append(&at_device_class_list, &(class->list));
  149. rt_hw_interrupt_enable(level);
  150. return RT_EOK;
  151. }
  152. /* Get AT device class by client ID */
  153. static struct at_device_class *at_device_class_get(uint16_t class_id)
  154. {
  155. rt_base_t level;
  156. rt_slist_t *node = RT_NULL;
  157. struct at_device_class *class = RT_NULL;
  158. level = rt_hw_interrupt_disable();
  159. /* Get AT device class by class ID */
  160. rt_slist_for_each(node, &at_device_class_list)
  161. {
  162. class = rt_slist_entry(node, struct at_device_class, list);
  163. if (class && class->class_id == class_id)
  164. {
  165. rt_hw_interrupt_enable(level);
  166. return class;
  167. }
  168. }
  169. rt_hw_interrupt_enable(level);
  170. return RT_NULL;
  171. }
  172. /**
  173. * This function registers an AT device with specified device name and AT client name.
  174. *
  175. * @param device the pointer of AT device structure
  176. * @param device_name AT device name
  177. * @param at_client_name AT device client name
  178. * @param class_id AT device class ID
  179. * @param user_data user-specific data
  180. *
  181. * @return = 0: register successfully
  182. * < 0: register failed
  183. */
  184. int at_device_register(struct at_device *device, const char *device_name,
  185. const char *at_client_name, uint16_t class_id, void *user_data)
  186. {
  187. rt_base_t level;
  188. int result = 0;
  189. static int device_counts = 0;
  190. char name[RT_NAME_MAX] = {0};
  191. struct at_device_class *class = RT_NULL;
  192. RT_ASSERT(device);
  193. RT_ASSERT(device_name);
  194. RT_ASSERT(at_client_name);
  195. class = at_device_class_get(class_id);
  196. if (class == RT_NULL)
  197. {
  198. LOG_E("get AT device class(%d) failed.", class_id);
  199. result = -RT_ERROR;
  200. goto __exit;
  201. }
  202. /* Fill AT device object*/
  203. #ifdef AT_USING_SOCKET
  204. device->sockets = (struct at_socket *) rt_calloc(class->socket_num, sizeof(struct at_socket));
  205. if (device->sockets == RT_NULL)
  206. {
  207. LOG_E("no memory for AT Socket number(%d) create.", class->socket_num);
  208. result = -RT_ENOMEM;
  209. goto __exit;
  210. }
  211. /* create AT device socket event */
  212. rt_snprintf(name, RT_NAME_MAX, "at_se%d", device_counts++);
  213. device->socket_event = rt_event_create(name, RT_IPC_FLAG_FIFO);
  214. if (device->socket_event == RT_NULL)
  215. {
  216. LOG_E("no memory for AT device(%s) socket event create.", device_name);
  217. result = -RT_ENOMEM;
  218. goto __exit;
  219. }
  220. #endif /* AT_USING_SOCKET */
  221. rt_memcpy(device->name, device_name, rt_strlen(device_name));
  222. device->class = class;
  223. device->user_data = user_data;
  224. /* Initialize current AT device single list */
  225. rt_slist_init(&(device->list));
  226. level = rt_hw_interrupt_disable();
  227. /* Add current AT device to device list */
  228. rt_slist_append(&at_device_list, &(device->list));
  229. rt_hw_interrupt_enable(level);
  230. /* Initialize AT device */
  231. result = class->device_ops->init(device);
  232. if (result < 0)
  233. {
  234. goto __exit;
  235. }
  236. __exit:
  237. if (result < 0)
  238. {
  239. device->is_init = RT_FALSE;
  240. }
  241. else
  242. {
  243. device->is_init = RT_TRUE;
  244. }
  245. return result;
  246. }