1 /*
2  * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3  */
4 
5 #include <stddef.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <errno.h>
9 
10 #if AOS_COMP_CLI
11 #include "aos/cli.h"
12 #endif
13 #include "aos/list.h"
14 
15 #include <drivers/u_ld.h>
16 #include <drivers/spinlock.h>
17 #include <drivers/char/u_device.h>
18 #include <drivers/char/u_driver.h>
19 #include <drivers/char/u_bus.h>
20 
21 static int u_bus_dump(struct u_bus *bus);
22 static int u_device_unbind_driver(struct u_device *dev);
23 static int u_bus_detach_device(struct u_device *dev);
24 
25 /**
26  * all buses is connected via g_bus_list_head,
27  * used to enumerate bus/device/driver,
28  * either for info dump or for power management function
29  *
30  */
31 static dlist_t g_bus_list_head;
32 static spinlock_t g_bus_list_lock;
33 
34 /**
35  * dump all bus informations
36  *
37  * @return always returns 0
38  */
u_bus_dump_all(void)39 int u_bus_dump_all(void) {
40 	u_bus_t *bus = NULL;
41 	dlist_t *next = NULL;
42 	u_bus_private_t *p = NULL;
43 
44 	dlist_for_each_entry_safe(&g_bus_list_head, next, p, u_bus_private_t, bus_node) {
45 		ddkc_info("p:%p, bus_node:%p, next:%p, prev:%p\r\n", p, &p->bus_node, p->bus_node.next, p->bus_node.prev);
46 		bus = p->bus;
47 		u_bus_dump(bus);
48 	}
49 
50 	return 0;
51 }
52 
53 /**
54  * dump single bus's information, all devices, drivers connected to this bus is included
55  *
56  * @param bus - pointer to specified bus
57  * @return
58  */
u_bus_dump(struct u_bus * bus)59 static int u_bus_dump(struct u_bus *bus) {
60 	u_device_t *dev = NULL;
61 	u_driver_t *drv = NULL;
62 	struct u_bus_private *p = NULL;
63 	u_device_private_t *dev_p = NULL;
64 	u_driver_private_t *drv_p = NULL;
65 
66 	struct dlist_s *next = NULL;
67 
68 	if (!bus)
69 		return -EINVAL;
70 
71 	ddkc_info("bus:%p, name:%s, p:%p\r\n", bus, bus->name, bus->p);
72 
73 	p = bus->p;
74 
75 	/* dump information of all devices, who is connected into current bus */
76 	if (dlist_empty(&p->dev_list)) {
77 		ddkc_warn("bus[%s]'s device list is empty\r\n", bus->name);
78 	} else {
79 		dlist_for_each_entry_safe(&p->dev_list, next, dev_p, u_device_private_t, bus_node) {
80 			dev = dev_p->dev;
81 			u_device_dump(dev);
82 		}
83 	}
84 
85 	/* dump information of all drivers, who is connected into current bus */
86 	if (dlist_empty(&p->drv_list)) {
87 		ddkc_warn("bus[%s]'s driver list is empty\r\n", bus->name);
88 	} else {
89 		dlist_for_each_entry_safe(&p->drv_list, next, drv_p, u_driver_private_t, bus_node) {
90 			drv = drv_p->drv;
91 			u_driver_dump(drv);
92 		}
93 	}
94 
95 	return 0;
96 }
97 
98 /**
99  * connect dev into target bus(dev->bus)
100  * low level operations, driver is not aware of this operation
101  *
102  * @param dev - pointer to target device
103  * @return always returns 0
104  */
u_bus_add_device(struct u_device * dev)105 int u_bus_add_device(struct u_device *dev) {
106 	unsigned long flags;
107 	u_bus_t *bus = dev->bus;
108 
109 	/* add dev->p->bus_node into dev->bus's p->dev_list */
110 	spin_lock_irqsave(&bus->p->lock, flags);
111 	dlist_add_tail(&dev->p->bus_node, &bus->p->dev_list);
112 	spin_unlock_irqrestore(&bus->p->lock, flags);
113 
114 	return 0;
115 }
116 
117 /**
118  * disconnect device with its driver and delete it from target bus(dev->bus)
119  *
120  * @param dev - pointer to target device
121  * @return always return 0
122  */
u_bus_del_device(struct u_device * dev)123 int u_bus_del_device(struct u_device *dev) {
124 	u_bus_t *bus = NULL;
125 
126 	if (!dev) {
127 		ddkc_err("invalid dev:%p to delete\r\n", dev);
128 		return -EINVAL;
129 	}
130 
131 	bus = dev->bus;
132 
133 	/* if device is already attached with specified driver, detach it */
134 	if (dev && dev->drv) {
135         u_bus_detach_device(dev);
136         u_device_unbind_driver(dev);
137     }
138 
139     /* delete dev from it's bus */
140 	if (dev && dev->bus && !dlist_empty(&dev->bus->p->dev_list)) {
141 		//TODO: should notify driver about this device is to be deleted?
142 		unsigned long flags;
143 
144 		spin_lock_irqsave(&bus->p->lock, flags);
145 		dlist_del(&dev->p->bus_node);
146 		dlist_init(&dev->p->bus_node);
147 		spin_unlock_irqrestore(&bus->p->lock, flags);
148 	}
149 
150 	return 0;
151 }
152 
153 /**
154  * bind device with target driver
155  *
156  * @param drv - pointer to the driver to be binded
157  * @param dev - pointer to the device to be binded
158  * @return always return 0
159  */
u_driver_bind_device(struct u_driver * drv,struct u_device * dev)160 static int u_driver_bind_device(struct u_driver *drv, struct u_device *dev) {
161     unsigned long flags;
162 	u_driver_private_t *drv_p = drv->p;
163 	u_device_private_t *dev_p = dev->p;
164 
165 	spin_lock_irqsave(&drv_p->lock, flags);
166 	dlist_add_tail(&dev_p->drv_node, &drv_p->dev_list);
167 	spin_unlock_irqrestore(&drv_p->lock, flags);
168 
169 	return 0;
170 }
171 
172 /**
173  * unbind device with the binded driver
174  *
175  * @param dev - pointer to target device
176  * @return always returns 0
177  */
u_device_unbind_driver(struct u_device * dev)178 static int u_device_unbind_driver(struct u_device *dev) {
179     unsigned long flags;
180     u_device_private_t *dev_p = dev->p;
181 
182     spin_lock_irqsave(&dev_p->lock, flags);
183     dlist_del(&dev_p->drv_node);
184     spin_unlock_irqrestore(&dev_p->lock, flags);
185 
186     return 0;
187 }
188 
189 /**
190  * Try to init dev with drv's ops
191  *
192  * @param drv - target driver to be used for device initialization
193  * @param dev - target device to be initialized
194  * @return return 1 if init success; otherwise return 0
195  */
u_driver_init_device(struct u_driver * drv,struct u_device * dev)196 static int u_driver_init_device(struct u_driver *drv, struct u_device *dev)
197 {
198 	int r = -1;
199 
200 	/* attach to drv for the moment, will detach if init/probe fails */
201 	dev->drv = drv;
202 	ddkc_dbg("bus[%s] try to init dev[%s] with drv[%s]\r\n", dev->bus->name, dev->name, drv->name);
203 
204 	ddkc_dbg("dev->bus->init:%p, drv->init:%p\r\n", dev->bus->init, drv->init);
205 	ddkc_dbg("dev->bus->probe:%p, drv->probe:%p\r\n", dev->bus->probe, drv->probe);
206 	do {
207 		/* try legacy ops, bus init cb is prioritized */
208 		if (dev->bus->init) {
209 			r = dev->bus->init(dev);
210 			break;
211 		} else if (drv->init) {
212 			r = drv->init(dev);
213 			break;
214 		}
215 
216 		/* try probe ops - for linux-like drivers, bus probe cb is prioritized */
217 		if (dev->bus->probe) {
218 			r = dev->bus->probe(dev);
219 			break;
220 		} else if (drv->probe) {
221 			r = drv->probe(dev);
222 			break;
223 		}
224 	} while(0);
225 
226 	if (!r) {
227 		ddkc_dbg("bus[%s] drv[%s] init dev[%s] success\r\n", dev->bus->name, drv->name, dev->p->name);
228 		u_driver_bind_device(drv, dev);
229 	} else {
230 		ddkc_warn("bus[%s] drv[%s] init dev[%s] fails\r\n", dev->bus->name, drv->name, dev->name);
231 		dev->drv = NULL;
232 	}
233 
234 	return r;
235 }
236 
237 /**
238  * Try whether drv matches dev with bus match function
239  *
240  * @param drv - target driver to be matched with dev
241  * @param dev - target device to be matched with drv
242  * @return return 1 if match success; otherwise return 0
243  */
u_driver_match_device(struct u_driver * drv,struct u_device * dev)244 static int u_driver_match_device(struct u_driver *drv, struct u_device *dev)
245 {
246 	if (!drv || !dev) {
247 		ddkc_err("invalid drv:%p or dev:%p\r\n", drv, dev);
248 		return 0;
249 	}
250 
251 	ddkc_dbg("driver match device, drv:%p, drv->bus:%p, dev:%p\r\n", drv, drv->bus, dev);
252 	if (drv->bus) {
253 		ddkc_dbg("driver match device, drv->bus->match:%p\r\n", drv->bus->match);
254 		return drv->bus->match ? drv->bus->match(dev, drv) : 1;
255 	} else {
256 		ddkc_err("invalid drv->bus:%p\r\n", drv->bus);
257 		return 0;
258 	}
259 }
260 
261 /**
262  * enumerate driver list and try to init the device with the drivers
263  *
264  * @param dev - pointer to the deviice to be initialized
265  *
266  * @return 0 if device initialization success; negative if device initialization fails
267  */
u_bus_try_init_device(struct u_device * dev)268 int u_bus_try_init_device(struct u_device *dev) {
269 	int r = 0;
270 	u_bus_t *bus = dev->bus;
271 	u_driver_t *drv = NULL;
272 	u_driver_private_t *drv_p = NULL;
273 	struct dlist_s *next = NULL;
274 
275 	if (dev->drv) {
276 		ddkc_warn("dev[%s]'s is busy, is now driven by drv[%s]\r\n", dev->name, dev->drv->name);
277 		return 0;
278 	}
279 	// whenever device is created, try match and init it if match returns true
280 	if (dlist_empty(&bus->p->drv_list)) {
281 		ddkc_dbg("bus[%s]'s drv_list is empty\r\n", bus->name);
282 		return 0;
283 	}
284 
285 	dlist_for_each_entry_safe(&bus->p->drv_list, next, drv_p, u_driver_private_t, bus_node) {
286 		drv = drv_p->drv;
287 
288 		r = u_driver_match_device(drv, dev);
289 		if (!r) {
290 			ddkc_dbg("drv[%s] does not match dev[%s]\r\n", drv->name, dev->name);
291 			continue;
292 		}
293 
294 		r = u_driver_init_device(drv, dev);
295 		if (r) {
296 			ddkc_err("drv[%s] init dev[%s] fails\r\n", drv->name, dev->name);
297 		} else {
298 			ddkc_info("drv[%s] init dev[%s] success\r\n", drv->name, dev->name);
299 		}
300 	}
301 
302 	return 0;
303 }
304 
305 /**
306  * add a driver into bus's driver list
307  *
308  * @param drv - the driver to be added
309  * @return always return 0
310  */
u_bus_add_driver(struct u_driver * drv)311 int u_bus_add_driver(struct u_driver *drv) {
312 	u_bus_t *bus = drv->bus;
313 	unsigned long flags;
314 
315 	spin_lock_irqsave(&bus->p->lock, flags);
316 	dlist_add_tail(&drv->p->bus_node, &bus->p->drv_list);
317 	spin_unlock_irqrestore(&bus->p->lock, flags);
318 
319 	return 0;
320 }
321 
322 /**
323  * attach a driver into bus's driver list,
324  * try to init free devices(not drived by any driver) if device is matchd
325  *
326  * @drv: the driver to be added
327  * @return always return 0
328  */
u_bus_attach_driver(struct u_driver * drv)329 int u_bus_attach_driver(struct u_driver *drv) {
330 	int r = 0;
331 	u_bus_t *bus = drv->bus;
332 	u_device_t *dev = NULL;
333 	u_device_private_t *dev_p = NULL;
334 	dlist_t *next = NULL;
335 
336 	// whenever device is created, try init it if match returns success
337 	if (dlist_empty(&bus->p->dev_list)) {
338 		ddkc_dbg("bus[%s]'s dev_list is empty\r\n", bus->name);
339 		return 0;
340 	}
341 
342 	/* try to match the device in bus device list with driver */
343 
344 	dlist_for_each_entry_safe(&bus->p->dev_list, next, dev_p, u_device_private_t, bus_node) {
345 		dev = dev_p->dev;
346 		/* exclude the devices who is already attached by driver */
347 		if (dev->drv) {
348 			ddkc_dbg("bus[%s] dev[%s] is already probed by drv[%s]\r\n",
349 			         bus->name, dev->p->name, dev->drv->name);
350 			continue;
351 		}
352 
353 		r = u_driver_match_device(drv, dev);
354 		if (!r) {
355 			ddkc_dbg("drv[%s] does not match dev[%s]\r\n", drv->name, dev->name);
356 			continue;
357 		}
358 
359 		r = u_driver_init_device(drv, dev);
360 		ddkc_dbg("drv[%s] init dev[%s] %s, r:%d\r\n", drv->name, dev->name, r ? "fail" : "success", r);
361 	}
362 
363 	return 0;
364 }
365 
u_bus_get_by_name(char * name)366 u_bus_t * u_bus_get_by_name(char *name) {
367 	dlist_t *next = NULL;
368 	u_bus_private_t *p = NULL;
369 	u_bus_t *bus = NULL;
370 
371 	if (!name)
372 		return NULL;
373 
374 
375 	dlist_for_each_entry_safe(&g_bus_list_head, next, p, u_bus_private_t, bus_node) {
376 		u_bus_dump(p->bus);
377 		bus = p->bus;
378 		ddkc_dbg("bus->name:%s, name_len:%d\r\n", bus->name, strlen(bus->name));
379 		if (!strcmp(bus->name, name)) {
380 			ddkc_dbg("name:%s, bus:%p\r\n", name, bus);
381 			break;
382 		}
383 		bus = NULL;
384 	}
385 
386 	return bus;
387 }
388 
389 /**
390  * init global bus list, this is module entry API of u_bus
391  * @return always return 0
392  */
u_bus_list_init(void)393 int u_bus_list_init(void) {
394 	ddkc_dbg("bus list init\r\n");
395 	dlist_init(&g_bus_list_head);
396 	spin_lock_init(&g_bus_list_lock);
397 	return 0;
398 }
399 
400 /**
401  * add new bus into global bus list
402  *
403  * @param bus - pointer to target bus to be added
404  * @return always return 0
405  */
u_bus_add(struct u_bus * bus)406 int u_bus_add(struct u_bus *bus) {
407 	unsigned long flags;
408 
409 	ddkc_dbg("add bus[%s] into global bus list\r\n", bus->name);
410 	spin_lock_irqsave(&g_bus_list_lock, flags);
411 	dlist_add_tail(&bus->p->bus_node, &g_bus_list_head);
412 	spin_unlock_irqrestore(&g_bus_list_lock, flags);
413 	return 0;
414 }
415 
416 /**
417  * init bus node struct
418  *
419  * @param bus - target bus to be initialized
420  * @return 0 for success; negative for failure
421  */
u_bus_node_initialize(struct u_bus * bus)422 int u_bus_node_initialize(struct u_bus *bus) {
423 	u_bus_private_t *p = NULL;
424 
425 	p = (u_bus_private_t *)malloc(sizeof(u_bus_private_t));
426 	if (!p) {
427 		ddkc_err("malloc for u_bus_private_t fails\r\n");
428 		return -ENOMEM;
429 	}
430 
431 	spin_lock_init(&p->lock);
432 	dlist_init(&p->dev_list);
433 	dlist_init(&p->drv_list);
434 	dlist_init(&p->bus_node);
435 	p->bus = bus;
436 	bus->p = p;
437 
438 	return 0;
439 }
440 
441 /**
442  * register bus to system
443  *
444  * @param bus - pointer to the target bus to be registered
445  * @return 0 for success; negative for failure
446  */
u_bus_register(struct u_bus * bus)447 int u_bus_register(struct u_bus *bus) {
448 	int r = 0;
449 
450 	if(!bus) {
451 		ddkc_err("invalid bus:%p\r\n", bus);
452 		return -EINVAL;
453 	}
454 
455 	if (bus->p || !bus->name) {
456 		ddkc_err("invalid bus priv data:%p or bus name:%p, ignore\r\n", bus->p, bus->name);
457 		return -EINVAL;
458 	}
459 
460 	r = u_bus_node_initialize(bus);
461 	if (r) {
462 		ddkc_err("bus node init fails, error:%d\r\n", r);
463 		return -1;
464 	}
465 
466 	return u_bus_add(bus);
467 }
468 
469 /**
470  * unregister bus from system
471  *
472  * @param bus  - pointer to the target bus to be unregistered
473  * @return
474  */
u_bus_unregister(struct u_bus * bus)475 int u_bus_unregister(struct u_bus *bus) {
476 	unsigned long flags;
477 
478 	// TODO: all bus related driver/device list should be clean up before calling u_bus_unregister
479 	ddkc_info("add bus[%s] into global bus list\r\n", bus->name);
480 	spin_lock_irqsave(&g_bus_list_lock, flags);
481 	dlist_del(&bus->p->bus_node);
482 	spin_unlock_irqrestore(&g_bus_list_lock, flags);
483 	return 0;
484 }
485 
486 #if 0
487 struct u_device *u_bus_find_dev_by_id(struct u_bus *bus, dev_t devid) {
488 	u_device_t *dev = NULL;
489 	struct u_driver_t *drv = NULL;
490 	struct u_bus_private *p = NULL;
491 	u_device_private_t *dev_p = NULL;
492 
493 	struct dlist_s *next = NULL;
494 
495 	if (!bus)
496 		return -EINVAL;
497 	ddkc_info("bus:%p, name:%s, p:%p, devid:0x%x\r\n", bus, bus->name, bus->p, devid);
498 
499 	p = bus->p;
500 
501 	if (dlist_empty(&p->dev_list)) {
502 		ddkc_dbg("bus[%s]'s device list is empty\r\n", bus->name);
503 	}
504 	dlist_for_each_entry_safe(&p->dev_list, next, dev_p, u_device_private_t, bus_node) {
505 		dev = dev_p->dev;
506 		if (dev->dev_id == devid) {
507 			ddkc_loud("dev:%p found with devid:0x%x\r\n", dev, devid);
508 			break;
509 		}
510         ddkc_loud("dev->dev_id:%d\r\n", dev->dev_id);
511 		dev = NULL;
512 	}
513 
514 	return dev;
515 }
516 
517 struct u_device *u_device_find_by_devid(dev_t devid) {
518 	u_bus_t *bus = NULL;
519 	dlist_t *pos = NULL;
520 	dlist_t *next = NULL;
521 	u_bus_private_t *p = NULL;
522 	struct u_device *dev = NULL;
523 
524     ddkc_dbg ("%s\r\n", __func__);
525 	dlist_for_each_entry_safe(&g_bus_list_head, next, p, u_bus_private_t, bus_node) {
526 		bus = p->bus;
527 		dev = u_bus_find_dev_by_id(bus, devid);
528 		if (dev)
529 			break;
530 	}
531 
532 	ddkc_err("u_device[%p] found by devid[0x%x]\r\n", dev, devid);
533 	return dev;
534 }
535 
536 #endif
537 
538 
539 /**
540  * delete a driver from bus's driver list
541  *
542  * @param drv - pointer to the driver to be deleted
543  * @return always return 0
544  */
u_bus_del_driver(struct u_driver * drv)545 int u_bus_del_driver(struct u_driver *drv) {
546 	u_bus_t *bus = NULL;
547 	unsigned long flags;
548 
549 	if (!drv) {
550 		ddkc_err("invalid drv:%p to delete\r\n", drv);
551 		return -EINVAL;
552 	}
553 
554 	bus = drv->bus;
555 	spin_lock_irqsave(&bus->p->lock, flags);
556 	dlist_del(&drv->p->bus_node);
557 	spin_unlock_irqrestore(&bus->p->lock, flags);
558 
559 	return 0;
560 }
561 
562 /**
563  * Try to deinit a device
564  *
565  * @param drv - pointer to target device's driver
566  * @param dev - pointer to target device
567  * @return 0 if deinit success; otherwise return negative
568  */
u_driver_deinit_device(struct u_driver * drv,struct u_device * dev)569 static int u_driver_deinit_device(struct u_driver *drv, struct u_device *dev)
570 {
571     int r = -1;
572 
573     /* attach to drv for the moment, will detach if init fails */
574     ddkc_dbg("bus[%s] drv[%s] removing dev[%s]\r\n", dev->bus->name, drv->name, dev->name);
575 
576 	ddkc_dbg("dev->bus->deinit:%p, drv->deinit:%p\r\n", dev->bus->deinit, drv->deinit);
577     ddkc_dbg("dev->bus->remove:%p, drv->remove:%p\r\n", dev->bus->remove, drv->remove);
578 
579     /* try legacy ops */
580 	if (dev->bus->deinit) {
581 		r = dev->bus->deinit(dev);
582 		if (r)
583 			goto remove_fail;
584 	} else if (drv->deinit) {
585 		r = drv->deinit(dev);
586 		if (r)
587 			goto remove_fail;
588 	}
589 
590     if (dev->bus->remove) {
591         r = dev->bus->remove(dev);
592         if (r)
593             goto remove_fail;
594     } else if (drv->remove) {
595         r = drv->remove(dev);
596         if (r)
597             goto remove_fail;
598     }
599 
600     dev->drv = NULL;
601     ddkc_dbg("bus[%s] drv[%s] remove dev[%s] success\r\n", dev->bus->name, drv->name, dev->p->name);
602 
603     return 0;
604 
605 remove_fail:
606     dev->drv = NULL;
607     ddkc_dbg("bus[%s] drv[%s] remove dev[%s] fails\r\n", dev->bus->name, drv->name, dev->name);
608     return -1;
609 }
610 
611 /**
612  * deattch a driver into bus's driver list
613  *
614  * @param drv - pointer to target driver to be deatched
615  * @return always return 0
616  */
u_bus_detach_driver(struct u_driver * drv)617 int u_bus_detach_driver(struct u_driver *drv) {
618 	int r = 0;
619 	u_device_t *dev = NULL;
620 	u_device_private_t *dev_p = NULL;
621 	dlist_t *next = NULL;
622 
623     if (dlist_empty(&drv->p->dev_list)) {
624         ddkc_dbg("drv[%s]'s dev_list is empty\r\n", drv->name);
625         return 0;
626     }
627     ddkc_dbg("drv:%p, drv->p:%p, &drv->p->dev_list:%p\r\n", drv, drv->p, &drv->p->dev_list);
628 
629 	/* try to remove the devices which is already attached with the driver */
630 	dlist_for_each_entry_safe(&drv->p->dev_list, next, dev_p, u_device_private_t, drv_node) {
631 		ddkc_dbg("dev:%p, dev_p:%p\r\n", dev, dev_p);
632 		dev = dev_p->dev;
633         ddkc_dbg("dev:%p, dev_p:%p\r\n", dev, dev_p);
634         r = u_driver_deinit_device(drv, dev);
635 		ddkc_dbg("drv[%s] remove dev[%s] %s, r:%d\r\n", drv->name, dev->name, r ? "fail" : "success", r);
636 	}
637 
638 	return 0;
639 }
640 
641 /**
642  * detach a device into bus's driver list
643  *
644  * @param dev - target device to be detached
645  * @return always return 0
646  */
u_bus_detach_device(struct u_device * dev)647 int u_bus_detach_device(struct u_device *dev) {
648     int r = 0;
649     u_driver_t *drv = dev->drv;
650 
651     if (!drv) {
652         ddkc_dbg("dev[%s] is not attached to driver\r\n", dev->name);
653         return 0;
654     }
655 
656     r = u_driver_deinit_device(drv, dev);
657     if (r) {
658         ddkc_err("dev[%s] deatch with driver[%s] failed\r\n", dev->name, drv->name);
659         return 0;
660     }
661     ddkc_dbg("dev[%s] deatch with driver[%s] succeed\r\n", dev->name, drv->name);
662 
663     return 0;
664 }
665 
666 #if AOS_COMP_CLI
667 /**
668  * command service handler - dump information of all bus/device/driver
669  *
670  */
u_bus_dump_cmd(char * wbuf,int len,int argc,char ** argv)671 static void u_bus_dump_cmd(char *wbuf, int len, int argc, char **argv) {
672 
673 	ddkc_info("dumping bus/device/driver information\r\n");
674 	u_bus_dump_all();
675 	ddkc_info("dump bus/device/driver information done\r\n");
676 
677 	return;
678 }
679 
680 struct cli_command u_bus_test_cmds[] = {
681 	{"ubusdump",         "dump system's bus/device/driver information", u_bus_dump_cmd},
682 };
683 
u_bus_test_cmd_init(void)684 static int u_bus_test_cmd_init(void) {
685 	ddkc_dbg("registering udevice commands\r\n");
686 	return aos_cli_register_commands(&u_bus_test_cmds[0],
687 	                                 sizeof(u_bus_test_cmds)/sizeof(u_bus_test_cmds[0]));
688 }
689 #endif /* AOS_COMP_CLI */
690 
691 /**
692  * u_bus module init entry
693  * declared with CORE_DRIVER_ENTRY, which is 1st level driver init entry
694  * @return 0
695  */
u_bus_init(void)696 int u_bus_init(void) {
697 	#if AOS_COMP_CLI
698 	u_bus_test_cmd_init();
699 	#endif
700 	return u_bus_list_init();
701 }
702 
703 CORE_DRIVER_ENTRY(u_bus_init)
704