bus.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  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. * 2022-10-13 flybreak the first version
  9. * 2023-04-12 ErikChan support rt_bus
  10. */
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #define DBG_TAG "dev_bus"
  16. #define DBG_LVL DBG_INFO
  17. #include <rtdbg.h>
  18. #ifdef RT_USING_DM
  19. #include <drivers/core/bus.h>
  20. static struct rt_bus bus_root =
  21. {
  22. .name = "root",
  23. .children = RT_LIST_OBJECT_INIT(bus_root.children),
  24. };
  25. #endif
  26. #ifdef RT_USING_DEV_BUS
  27. #if defined(RT_USING_POSIX_DEVIO)
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30. #include <poll.h>
  31. #include <sys/ioctl.h>
  32. #include <dfs_file.h>
  33. static int bus_fops_open(struct dfs_file *fd)
  34. {
  35. LOG_D("bus fops open");
  36. return 0;
  37. }
  38. static int bus_fops_close(struct dfs_file *fd)
  39. {
  40. LOG_D("bus fops close");
  41. return 0;
  42. }
  43. static const struct dfs_file_ops bus_fops =
  44. {
  45. bus_fops_open,
  46. bus_fops_close,
  47. RT_NULL,
  48. RT_NULL,
  49. RT_NULL,
  50. RT_NULL,
  51. RT_NULL,
  52. RT_NULL,
  53. RT_NULL,
  54. };
  55. #endif
  56. rt_device_t rt_device_bus_create(char *name, int attach_size)
  57. {
  58. rt_err_t result = RT_EOK;
  59. rt_device_t dev = rt_device_create(RT_Device_Class_Bus, 0);
  60. result = rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
  61. if (result < 0)
  62. {
  63. rt_kprintf("dev bus [%s] register failed!, ret=%d\n", name, result);
  64. return RT_NULL;
  65. }
  66. #if defined(RT_USING_POSIX_DEVIO)
  67. dev->fops = &bus_fops;
  68. #endif
  69. LOG_D("bus create");
  70. return dev;
  71. }
  72. rt_err_t rt_device_bus_destroy(rt_device_t dev)
  73. {
  74. rt_device_unregister(dev);
  75. dev->parent.type = RT_Object_Class_Device;
  76. rt_device_destroy(dev);
  77. LOG_D("bus destroy");
  78. return RT_EOK;
  79. }
  80. #endif
  81. #ifdef RT_USING_DM
  82. /**
  83. * @brief This function get the root bus
  84. */
  85. rt_bus_t rt_bus_root(void)
  86. {
  87. return &bus_root;
  88. }
  89. /**
  90. * @brief This function loop the dev_list of the bus, and call fn in each loop
  91. *
  92. * @param bus the target bus
  93. *
  94. * @param drv the target drv to be matched
  95. *
  96. * @param fn the function callback in each loop
  97. *
  98. * @return the error code, RT_EOK on added successfully.
  99. */
  100. rt_err_t rt_bus_for_each_dev(rt_bus_t bus, rt_driver_t drv, int (*fn)(rt_driver_t drv, rt_device_t dev))
  101. {
  102. rt_base_t level;
  103. rt_device_t dev;
  104. RT_ASSERT(bus != RT_NULL);
  105. RT_ASSERT(drv != RT_NULL);
  106. level = rt_spin_lock_irqsave(&bus->spinlock);
  107. rt_list_for_each_entry(dev, &bus->dev_list, node)
  108. {
  109. fn(drv, dev);
  110. }
  111. rt_spin_unlock_irqrestore(&bus->spinlock, level);
  112. return RT_EOK;
  113. }
  114. /**
  115. * @brief This function loop the drv_list of the bus, and call fn in each loop
  116. *
  117. * @param bus the target bus
  118. *
  119. * @param dev the target dev to be matched
  120. *
  121. * @param fn the function callback in each loop
  122. *
  123. * @return the error code, RT_EOK on added successfully.
  124. */
  125. rt_err_t rt_bus_for_each_drv(rt_bus_t bus, rt_device_t dev, int (*fn)(rt_driver_t drv, rt_device_t dev))
  126. {
  127. rt_err_t err;
  128. rt_base_t level;
  129. rt_driver_t drv;
  130. RT_ASSERT(bus != RT_NULL);
  131. RT_ASSERT(dev != RT_NULL);
  132. if (rt_list_isempty(&bus->drv_list))
  133. {
  134. return RT_EOK;
  135. }
  136. err = -RT_ERROR;
  137. level = rt_spin_lock_irqsave(&bus->spinlock);
  138. rt_list_for_each_entry(drv, &bus->drv_list, node)
  139. {
  140. if (fn(drv, dev))
  141. {
  142. err = -RT_EOK;
  143. break;
  144. }
  145. }
  146. rt_spin_unlock_irqrestore(&bus->spinlock, level);
  147. return err;
  148. }
  149. /**
  150. * @brief This function add a bus to the root
  151. *
  152. * @param bus_node the bus to be added
  153. *
  154. * @return the error code, RT_EOK on added successfully.
  155. */
  156. rt_err_t rt_bus_add(rt_bus_t bus_node)
  157. {
  158. rt_base_t level;
  159. RT_ASSERT(bus_node != RT_NULL);
  160. bus_node->bus = &bus_root;
  161. rt_list_init(&bus_node->list);
  162. level = rt_spin_lock_irqsave(&bus_node->spinlock);
  163. rt_list_insert_before(&bus_root.children, &bus_node->list);
  164. rt_spin_unlock_irqrestore(&bus_node->spinlock, level);
  165. return RT_EOK;
  166. }
  167. /**
  168. * @brief This function match the device and driver, probe them if match successed
  169. *
  170. * @param drv the drv to match/probe
  171. *
  172. * @param dev the dev to match/probe
  173. *
  174. * @return the result of probe, 1 on added successfully.
  175. */
  176. static int rt_bus_probe(rt_driver_t drv, rt_device_t dev)
  177. {
  178. int ret = 0;
  179. rt_bus_t bus = drv->bus;
  180. if (!bus)
  181. {
  182. bus = dev->bus;
  183. }
  184. RT_ASSERT(bus != RT_NULL);
  185. if (!dev->drv && bus->match(drv, dev))
  186. {
  187. dev->drv = drv;
  188. ret = bus->probe(dev);
  189. if (ret)
  190. {
  191. dev->drv = RT_NULL;
  192. }
  193. }
  194. return ret;
  195. }
  196. /**
  197. * @brief This function add a driver to the drv_list of a specific bus
  198. *
  199. * @param bus the bus to add
  200. *
  201. * @param drv the driver to be added
  202. *
  203. * @return the error code, RT_EOK on added successfully.
  204. */
  205. rt_err_t rt_bus_add_driver(rt_bus_t bus, rt_driver_t drv)
  206. {
  207. rt_base_t level;
  208. RT_ASSERT(bus != RT_NULL);
  209. RT_ASSERT(drv != RT_NULL);
  210. drv->bus = bus;
  211. level = rt_spin_lock_irqsave(&bus->spinlock);
  212. rt_list_insert_before(&bus->drv_list, &drv->node);
  213. rt_spin_unlock_irqrestore(&bus->spinlock, level);
  214. rt_bus_for_each_dev(drv->bus, drv, rt_bus_probe);
  215. return RT_EOK;
  216. }
  217. /**
  218. * @brief This function add a device to the dev_list of a specific bus
  219. *
  220. * @param bus the bus to add
  221. *
  222. * @param dev the device to be added
  223. *
  224. * @return the error code, RT_EOK on added successfully.
  225. */
  226. rt_err_t rt_bus_add_device(rt_bus_t bus, rt_device_t dev)
  227. {
  228. rt_base_t level;
  229. RT_ASSERT(bus != RT_NULL);
  230. RT_ASSERT(dev != RT_NULL);
  231. dev->bus = bus;
  232. level = rt_spin_lock_irqsave(&bus->spinlock);
  233. rt_list_insert_before(&bus->dev_list, &dev->node);
  234. rt_spin_unlock_irqrestore(&bus->spinlock, level);
  235. rt_bus_for_each_drv(dev->bus, dev, rt_bus_probe);
  236. return RT_EOK;
  237. }
  238. /**
  239. * @brief This function remove a driver from bus
  240. *
  241. * @param drv the driver to be removed
  242. *
  243. * @return the error code, RT_EOK on added successfully.
  244. */
  245. rt_err_t rt_bus_remove_driver(rt_driver_t drv)
  246. {
  247. RT_ASSERT(drv->bus != RT_NULL);
  248. LOG_D("Bus(%s) remove driver %s", drv->bus->name, drv->name);
  249. rt_list_remove(&drv->node);
  250. return RT_EOK;
  251. }
  252. /**
  253. * @brief This function remove a device from bus
  254. *
  255. * @param dev the device to be removed
  256. *
  257. * @return the error code, RT_EOK on added successfully.
  258. */
  259. rt_err_t rt_bus_remove_device(rt_device_t dev)
  260. {
  261. RT_ASSERT(dev->bus != RT_NULL);
  262. LOG_D("Bus(%s) remove device %s", dev->bus->name, dev->name);
  263. rt_list_remove(&dev->node);
  264. return RT_EOK;
  265. }
  266. /**
  267. * @brief This function find a bus by name
  268. * @param bus the name to be finded
  269. *
  270. * @return the bus finded by name.
  271. */
  272. rt_bus_t rt_bus_find_by_name(char *name)
  273. {
  274. rt_bus_t bus = RT_NULL;
  275. struct rt_list_node *node = RT_NULL;
  276. if (!rt_list_isempty(&bus_root.children))
  277. {
  278. rt_list_for_each(node, &bus_root.children)
  279. {
  280. bus = rt_list_entry(node, struct rt_bus, list);
  281. if (!rt_strncmp(bus->name, name, RT_NAME_MAX))
  282. {
  283. return bus;
  284. }
  285. }
  286. }
  287. return bus;
  288. }
  289. /**
  290. * @brief This function transfer dev_list and drv_list to the other bus
  291. *
  292. * @param new_bus the bus to transfer
  293. *
  294. * @param dev the target device
  295. *
  296. * @return the error code, RT_EOK on added successfully.
  297. */
  298. rt_err_t rt_bus_reload_driver_device(rt_bus_t new_bus, rt_device_t dev)
  299. {
  300. rt_base_t level;
  301. RT_ASSERT(new_bus != RT_NULL);
  302. RT_ASSERT(dev != RT_NULL);
  303. level = rt_spin_lock_irqsave(&new_bus->spinlock);
  304. rt_list_remove(&dev->node);
  305. rt_list_insert_before(&new_bus->dev_list, &dev->node);
  306. rt_list_remove(&dev->drv->node);
  307. rt_list_insert_before(&new_bus->drv_list, &dev->drv->node);
  308. rt_spin_unlock_irqrestore(&new_bus->spinlock, level);
  309. return RT_EOK;
  310. }
  311. /**
  312. * @brief This function register a bus
  313. * @param bus the bus to be registered
  314. *
  315. * @return the error code, RT_EOK on registeration successfully.
  316. */
  317. rt_err_t rt_bus_register(rt_bus_t bus)
  318. {
  319. rt_list_init(&bus->children);
  320. rt_list_init(&bus->dev_list);
  321. rt_list_init(&bus->drv_list);
  322. rt_spin_lock_init(&bus->spinlock);
  323. rt_bus_add(bus);
  324. return RT_EOK;
  325. }
  326. #endif