1 /*
2  * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3  */
4 
5 #include <stddef.h>
6 #include <errno.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "aos/list.h"
12 
13 #include <drivers/spinlock.h>
14 #include <drivers/char/u_device.h>
15 #include <drivers/char/u_driver.h>
16 #include <drivers/char/u_bus.h>
17 
18 /**
19  * dump driver information
20  *
21  * @param drv - pointer to target driver to be dumped
22  * @return 0 for success; -1 for failure
23  *
24  */
u_driver_dump(struct u_driver * drv)25 int u_driver_dump(struct u_driver *drv) {
26 
27 	if (!drv) {
28 		ddkc_err("drv is NULL\r\n");
29 		return -1;
30 	}
31 
32 	ddkc_info("drv->name:%s, drv:%p, bus:%p, p:%p\r\n",
33 	          drv->name ? drv->name : "NULL",
34 	          drv, drv->bus, drv->p);
35 	ddkc_info("drv->init:%p, drv->deinit:%p, drv->pm:%p, drv->on_ping:%p\r\n",
36 	          drv->init, drv->deinit, drv->pm, drv->on_ping);
37 	ddkc_info("drv->probe:%p, drv->remove:%p, drv->shutdown:%p, drv->suspend:%p, drv->resume:%p\r\n",
38 	          drv->probe, drv->remove, drv->shutdown, drv->suspend, drv->resume);
39 
40 	return 0;
41 }
42 
43 /**
44  * check whether driver with the same name is already loaded or not
45  * check whether driver with same name is already registered or not
46  *
47  * @param drv - pointer to target driver to be found
48  * @return 0 for success; -1 for failure
49  */
_bus_find_driver(struct u_driver * drv)50 int _bus_find_driver(struct u_driver *drv) {
51 	u_bus_t *bus = drv->bus;
52 	u_driver_private_t *drv_p = NULL;
53 	struct dlist_s *next = NULL;
54 	u_driver_t *drv_b = NULL;
55 
56 	dlist_for_each_entry_safe(&bus->p->drv_list, next, drv_p, u_driver_private_t, bus_node) {
57 		drv_b = drv_p->drv;
58 
59 		if (!strcmp(drv->name, drv_b->name))
60 			return 1;
61 	}
62 
63 	return 0;
64 }
65 
66 /**
67  * driver private struct initialization
68  * @param drv - pointer to target driver
69  * @return 0 for success; negative for failure
70  */
u_driver_initialize(struct u_driver * drv)71 int u_driver_initialize(struct u_driver *drv) {
72 	u_driver_private_t *p = NULL;
73 
74 	p = (u_driver_private_t *)malloc(sizeof(u_driver_private_t));
75 	if (!p) {
76 		ddkc_err("malloc for u_driver_private_t fails\r\n");
77 		return -ENOMEM;
78 	}
79 
80 	ddkc_dbg("malloc for u_driver_private_t done\r\n");
81 
82 	spin_lock_init(&p->lock);
83 	dlist_init(&p->dev_list);
84 	dlist_init(&p->bus_node);
85 	p->drv = drv;
86 	drv->p = p;
87 
88 	return 0;
89 }
90 
91 /**
92  * free driver's private struct
93  *
94  * @param drv - pointer to target driver
95  * @return always return 0
96  */
u_driver_deinitialize(struct u_driver * drv)97 int u_driver_deinitialize(struct u_driver *drv) {
98 
99 	free(drv->p);
100     drv->p = NULL;
101 
102 	return 0;
103 }
104 
105 /**
106  * add drvier into system
107  *
108  * @param drv - pointer to target driver
109  * @return 0 for success; negative for failure
110  */
u_driver_add(struct u_driver * drv)111 int u_driver_add(struct u_driver *drv) {
112 	int r = 0;
113 	// TODO: need to assign drv->bus to platform_bus if it is not assigned
114 
115 	if (!drv->p || !drv->bus || !drv->name) {
116 		ddkc_err("invalid drv->p:%p, drv->bus:%p or drv->name:%p\r\n", drv->p, drv->bus, drv->name);
117 		return -EINVAL;
118 	}
119 
120 	r = _bus_find_driver(drv);
121 	if (r) {
122 		ddkc_err("drv[%s] is already added\r\n", drv->name);
123 		return -EBUSY;
124 	}
125 
126 	r = u_bus_add_driver(drv);
127 	if (r)
128 		goto drv_add_error;
129 
130 	u_bus_attach_driver(drv);
131 
132 	return 0;
133 
134 drv_add_error:
135 	free(drv->p);
136 	drv->p = NULL;
137 
138 	return -1;
139 }
140 
141 /**
142  * delete driver from system
143  * detach it from bus and ehen delete the driver from bus
144  *
145  * @param drv  - pointer to target driver
146  * @return 0 for success; negative for failure
147  */
u_driver_del(struct u_driver * drv)148 int u_driver_del(struct u_driver *drv) {
149 	int r = 0;
150 
151 	/* deinit devices attached to this driver before delete it from bus */
152 	r = u_bus_detach_driver(drv);
153 	if (r)
154 		ddkc_err("detach drv[%s] failed, r:%d\r\n", drv->name, r);
155 
156 	r = u_bus_del_driver(drv);
157 	if (r)
158 		ddkc_err("delete drv[%s] failed, r:%d\r\n", drv->name, r);
159 
160 	return r;
161 }
162 
163 /**
164  * register a driver into system, init it's private struct before add it into system
165  *
166  * @param drv - pointer to target driver to be registered
167  * @return 0 for success; negative for failure
168  */
u_driver_register(struct u_driver * drv)169 int u_driver_register(struct u_driver *drv) {
170 	if(!drv)
171 		return -EINVAL;
172 
173 	u_driver_initialize(drv);
174 	return u_driver_add(drv);
175 }
176 
177 /**
178  * unregister a driver from system
179  * delete it and then free its private struct
180  *
181  * @param drv - pointer to target driver to be registered
182  * @return 0 for success; negative for failure
183  */
u_driver_unregister(struct u_driver * drv)184 int u_driver_unregister(struct u_driver *drv) {
185 	if(!drv)
186 		return -EINVAL;
187 
188 	u_driver_del(drv);
189 	return u_driver_deinitialize(drv);
190 }
191