diff options
Diffstat (limited to 'firmware/usbstack/core/core.c')
-rw-r--r-- | firmware/usbstack/core/core.c | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/firmware/usbstack/core/core.c b/firmware/usbstack/core/core.c new file mode 100644 index 0000000000..61b7f83636 --- /dev/null +++ b/firmware/usbstack/core/core.c | |||
@@ -0,0 +1,392 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: $ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Christian Gmeiner | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <errno.h> | ||
21 | #include <string.h> | ||
22 | #include <ctype.h> | ||
23 | #include "usbstack.h" | ||
24 | |||
25 | #include "config.h" | ||
26 | |||
27 | #include "usbstack/core.h" | ||
28 | #include "usbstack/config.h" | ||
29 | #include "usbstack/controller.h" | ||
30 | #include "usbstack/drivers/device/usb_serial.h" | ||
31 | #include "usbstack/drivers/device/usb_storage.h" | ||
32 | |||
33 | struct usb_core usbcore; | ||
34 | |||
35 | /* private used functions */ | ||
36 | static void update_driver_names(unsigned char* result); | ||
37 | static void bind_device_driver(struct usb_device_driver* driver); | ||
38 | |||
39 | /** | ||
40 | * Initialize usb stack. | ||
41 | */ | ||
42 | void usb_stack_init(void) { | ||
43 | |||
44 | int i; | ||
45 | logf("usb_stack_init"); | ||
46 | |||
47 | /* init datastructures */ | ||
48 | usbcore.controller[0] = NULL; | ||
49 | usbcore.controller[1] = NULL; | ||
50 | usbcore.active_controller = NULL; | ||
51 | usbcore.device_driver = NULL; | ||
52 | usbcore.running = false; | ||
53 | |||
54 | memset(&device_driver_names, 0, USB_STACK_MAX_SETTINGS_NAME); | ||
55 | |||
56 | /* init arrays */ | ||
57 | for (i = 0; i < NUM_DRIVERS; i++) { | ||
58 | usbcore.device_drivers[i] = NULL; | ||
59 | usbcore.host_drivers[i] = NULL; | ||
60 | } | ||
61 | |||
62 | /* init controllers */ | ||
63 | #if (USBSTACK_CAPS & CONTROLLER_DEVICE) | ||
64 | usb_dcd_init(); | ||
65 | #endif | ||
66 | |||
67 | #if (USBSTACK_CAPS & CONTROLLER_HOST) | ||
68 | usb_hcd_init(); | ||
69 | #endif | ||
70 | |||
71 | /* init drivers */ | ||
72 | usb_serial_driver_init(); | ||
73 | usb_storage_driver_init(); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * Start processing of usb stack. This function init | ||
78 | * active usb controller. | ||
79 | */ | ||
80 | void usb_stack_start(void) { | ||
81 | |||
82 | /* are we allready running? */ | ||
83 | if (usbcore.running) { | ||
84 | logf("allready running!"); | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | if (usbcore.active_controller == NULL) { | ||
89 | logf("no active controller!"); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | /* forward to controller */ | ||
94 | logf("starting controller"); | ||
95 | usbcore.active_controller->start(); | ||
96 | usbcore.running = true; | ||
97 | |||
98 | /* look if started controller is a device controller | ||
99 | * and if it has a device driver bind to it */ | ||
100 | logf("check for auto bind"); | ||
101 | if (usbcore.active_controller->type == DEVICE) { | ||
102 | if (usbcore.active_controller->device_driver == NULL && usbcore.device_driver != NULL) { | ||
103 | /* bind driver */ | ||
104 | logf("binding..."); | ||
105 | bind_device_driver(usbcore.device_driver); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Stop processing of usb stack. This function shutsdown | ||
112 | * active usb controller. | ||
113 | */ | ||
114 | void usb_stack_stop(void) { | ||
115 | |||
116 | /* are we allready stopped? */ | ||
117 | if (usbcore.running == false) { | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | /* forward to controller */ | ||
122 | usbcore.active_controller->stop(); | ||
123 | usbcore.running = false; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Gets called by upper layers to indicate that there is | ||
128 | * an interrupt waiting for the controller. | ||
129 | */ | ||
130 | void usb_stack_irq(void) { | ||
131 | |||
132 | /* simply notify usb controller */ | ||
133 | if (usbcore.active_controller != NULL && usbcore.active_controller->irq != NULL) { | ||
134 | usbcore.active_controller->irq(); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * If a host device controller is loaded, we need to have a function | ||
140 | * to call for maintanence. We need to check if a new device has connected, | ||
141 | * find suitable drivers for new devices. | ||
142 | */ | ||
143 | void usb_stack_work(void) { | ||
144 | /* TODO will be used with host device controllers | ||
145 | * and needs to be called in a loop (thread) */ | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * Register an usb controller in the stack. The stack can | ||
150 | * only have two controllers registered at one time. | ||
151 | * One device host controller and one host device controller. | ||
152 | * | ||
153 | * @param ctrl pointer to controller to register. | ||
154 | * @return 0 on success else a defined error code. | ||
155 | */ | ||
156 | int usb_controller_register(struct usb_controller* ctrl) { | ||
157 | |||
158 | if (ctrl == NULL) { | ||
159 | return EINVAL; | ||
160 | } | ||
161 | |||
162 | logf("usb_stack: register usb ctrl"); | ||
163 | logf(" -> name: %s", ctrl->name); | ||
164 | logf(" -> type: %d", ctrl->type); | ||
165 | |||
166 | switch (ctrl->type) { | ||
167 | case DEVICE: | ||
168 | if (usbcore.controller[0] == NULL) { | ||
169 | usbcore.controller[0] = ctrl; | ||
170 | return 0; | ||
171 | } | ||
172 | break; | ||
173 | case HOST: | ||
174 | if (usbcore.controller[1] == NULL) { | ||
175 | usbcore.controller[1] = ctrl; | ||
176 | return 0; | ||
177 | } | ||
178 | break; | ||
179 | default: | ||
180 | return EINVAL; | ||
181 | } | ||
182 | |||
183 | return ENOFREESLOT; | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * Unregister an usb controller from the stack. | ||
188 | * | ||
189 | * @param ctrl pointer to controller to unregister. | ||
190 | * @return 0 on success else a defined error code. | ||
191 | */ | ||
192 | int usb_controller_unregister(struct usb_controller* ctrl) { | ||
193 | |||
194 | if (ctrl == NULL) { | ||
195 | return EINVAL; | ||
196 | } | ||
197 | |||
198 | switch (ctrl->type) { | ||
199 | case DEVICE: | ||
200 | if (usbcore.controller[0] == ctrl) { | ||
201 | usbcore.controller[0] = NULL; | ||
202 | return 0; | ||
203 | } | ||
204 | break; | ||
205 | case HOST: | ||
206 | if (usbcore.controller[1] == ctrl) { | ||
207 | usbcore.controller[1] = NULL; | ||
208 | return 0; | ||
209 | } | ||
210 | break; | ||
211 | default: | ||
212 | return EINVAL; | ||
213 | } | ||
214 | |||
215 | return 0; /* never reached */ | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * Select an usb controller and active it. | ||
220 | * | ||
221 | * @param type of controller to activate. | ||
222 | */ | ||
223 | void usb_controller_select(int type) { | ||
224 | |||
225 | struct usb_controller* new = NULL; | ||
226 | |||
227 | /* check if a controller of the wanted type is already loaded */ | ||
228 | if (usbcore.active_controller != NULL && (int)usbcore.active_controller->type == type) { | ||
229 | logf("controller already set"); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | logf("usb_controller_select"); | ||
234 | logf(" -> type: %d", type); | ||
235 | |||
236 | usbcore.mode = type; | ||
237 | |||
238 | switch (type) { | ||
239 | case DEVICE: | ||
240 | new = usbcore.controller[0]; | ||
241 | break; | ||
242 | case HOST: | ||
243 | new = usbcore.controller[1]; | ||
244 | break; | ||
245 | } | ||
246 | |||
247 | /* if there is only one controller, stop here */ | ||
248 | if (new == NULL) { | ||
249 | logf("no suitable cntrl found"); | ||
250 | return; | ||
251 | } | ||
252 | |||
253 | /* shutdown current used controller */ | ||
254 | if (usbcore.active_controller != NULL) { | ||
255 | logf("shuting down old one"); | ||
256 | usbcore.active_controller->shutdown(); | ||
257 | } | ||
258 | |||
259 | /* set and init new controller */ | ||
260 | usbcore.active_controller = new; | ||
261 | logf("init controller"); | ||
262 | usbcore.active_controller->init(); | ||
263 | } | ||
264 | |||
265 | int usb_stack_get_mode(void) { | ||
266 | return usbcore.mode; | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * Register an usb device driver. | ||
271 | * | ||
272 | * @param driver pointer to an usb_device_driver struct. | ||
273 | * @return 0 on success, else a defined error code. | ||
274 | */ | ||
275 | int usb_device_driver_register(struct usb_device_driver* driver) { | ||
276 | |||
277 | int i; | ||
278 | |||
279 | if (driver == NULL) { | ||
280 | return EINVAL; | ||
281 | } | ||
282 | |||
283 | /* add to linked list */ | ||
284 | logf("usb_stack: register usb driver"); | ||
285 | for (i = 0; i < NUM_DRIVERS; i++) { | ||
286 | if (usbcore.device_drivers[i] == NULL) { | ||
287 | usbcore.device_drivers[i] = driver; | ||
288 | update_driver_names(device_driver_names); | ||
289 | return 0; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | update_driver_names(device_driver_names); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | int usb_device_driver_bind(const char* name) { | ||
299 | |||
300 | int i; | ||
301 | struct usb_device_driver *tmp = NULL; | ||
302 | struct usb_device_driver *driver = NULL; | ||
303 | |||
304 | if (name == NULL) { | ||
305 | return EINVAL; | ||
306 | } | ||
307 | |||
308 | /* look for driver */ | ||
309 | logf("looking for driver %s", name); | ||
310 | for (i = 0; i < NUM_DRIVERS; i++) { | ||
311 | tmp = usbcore.device_drivers[i]; | ||
312 | if (tmp != NULL && strcmp(name, tmp->name) == 0) { | ||
313 | driver = tmp; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | if (driver == NULL) { | ||
318 | logf("no driver found"); | ||
319 | return ENODRIVERFOUND; | ||
320 | } | ||
321 | |||
322 | /* look if there is an usb controller loaded */ | ||
323 | if (usbcore.active_controller == NULL) { | ||
324 | /* safe choosen driver and set it when controller starts */ | ||
325 | usbcore.device_driver = driver; | ||
326 | |||
327 | } else { | ||
328 | |||
329 | /* we need to have an active dcd controller */ | ||
330 | if (usbcore.active_controller->type != DEVICE) { | ||
331 | logf("wrong type"); | ||
332 | return EWRONGCONTROLLERTYPE; | ||
333 | } | ||
334 | |||
335 | /* bind driver to controller */ | ||
336 | bind_device_driver(driver); | ||
337 | } | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | void usb_device_driver_unbind(void) { | ||
343 | |||
344 | logf("usb_device_driver_unbind"); | ||
345 | if (usbcore.active_controller->device_driver != NULL) { | ||
346 | usbcore.active_controller->device_driver->unbind(); | ||
347 | usbcore.active_controller->device_driver = NULL; | ||
348 | } | ||
349 | |||
350 | usbcore.device_driver = NULL; | ||
351 | } | ||
352 | |||
353 | static void update_driver_names(unsigned char* result) { | ||
354 | |||
355 | int i; | ||
356 | int pos = 0; | ||
357 | unsigned char terminator = ','; | ||
358 | struct usb_device_driver* dd = NULL; | ||
359 | |||
360 | /* reset buffer, iterate through drivers and add to char array */ | ||
361 | memset(result, 0, USB_STACK_MAX_SETTINGS_NAME); | ||
362 | for (i = 0; i < NUM_DRIVERS; i++) { | ||
363 | int len; | ||
364 | dd = usbcore.device_drivers[i]; | ||
365 | |||
366 | if (dd != NULL) { | ||
367 | len = strlen(dd->name); | ||
368 | if (pos > 0) { | ||
369 | memcpy(result + pos, &terminator, 1); | ||
370 | pos++; | ||
371 | } | ||
372 | memcpy(result + pos, dd->name, len); | ||
373 | pos += len; | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | |||
378 | static void bind_device_driver(struct usb_device_driver* driver) { | ||
379 | |||
380 | /* look if there is an old driver */ | ||
381 | if (usbcore.active_controller->device_driver != NULL) { | ||
382 | usbcore.active_controller->device_driver->unbind(); | ||
383 | } | ||
384 | |||
385 | /* bind driver to controller */ | ||
386 | usbcore.active_controller->device_driver = driver; | ||
387 | |||
388 | /* init dirver */ | ||
389 | driver->bind(usbcore.active_controller->controller_ops); | ||
390 | } | ||
391 | |||
392 | |||