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