summaryrefslogtreecommitdiff
path: root/firmware/usbstack/core
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack/core')
-rw-r--r--firmware/usbstack/core/config.c80
-rw-r--r--firmware/usbstack/core/core.c392
-rw-r--r--firmware/usbstack/core/epsetup.c186
-rw-r--r--firmware/usbstack/core/utils.c125
4 files changed, 783 insertions, 0 deletions
diff --git a/firmware/usbstack/core/config.c b/firmware/usbstack/core/config.c
new file mode 100644
index 0000000000..a05a508bf9
--- /dev/null
+++ b/firmware/usbstack/core/config.c
@@ -0,0 +1,80 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2007 by Christian Gmeiner
11 *
12 * Based on linux/drivers/usb/gadget/config.c
13 * Copyright (C) 2003 David Brownell
14 *
15 * All files in this archive are subject to the GNU General Public License.
16 * See the file COPYING in the source tree root for full license agreement.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include <string.h>
24#include "usbstack/core.h"
25
26static int usb_descriptor_fillbuf(void* buf, unsigned buflen, struct usb_descriptor_header** src) {
27
28 uint8_t* dest = buf;
29
30 if (!src) {
31 return -EINVAL;
32 }
33
34 /* fill buffer from src[] until null descriptor ptr */
35 for (; 0 != *src; src++) {
36 unsigned len = (*src)->bLength;
37
38 logf("len: %d", len);
39
40 if (len > buflen)
41 return -EINVAL;
42 memcpy(dest, *src, len);
43 buflen -= len;
44 dest += len;
45 }
46 return dest - (uint8_t *)buf;
47}
48
49int usb_stack_configdesc(const struct usb_config_descriptor* config, void* buf, unsigned length, struct usb_descriptor_header** desc) {
50
51 struct usb_config_descriptor* cp = buf;
52 int len;
53
54 if (length < USB_DT_CONFIG_SIZE || !desc) {
55 return -EINVAL;
56 }
57
58 /* config descriptor first */
59 *cp = *config;
60
61 /* then interface/endpoint/class/vendor/... */
62 len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (uint8_t*)buf, length - USB_DT_CONFIG_SIZE, desc);
63
64 if (len < 0) {
65 return len;
66 }
67
68 len += USB_DT_CONFIG_SIZE;
69 if (len > 0xffff) {
70 return -EINVAL;
71 }
72
73 /* patch up the config descriptor */
74 cp->bLength = USB_DT_CONFIG_SIZE;
75 cp->bDescriptorType = USB_DT_CONFIG;
76 cp->wTotalLength = len;
77 cp->bmAttributes |= USB_CONFIG_ATT_ONE;
78
79 return len;
80}
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
33struct usb_core usbcore;
34
35/* private used functions */
36static void update_driver_names(unsigned char* result);
37static void bind_device_driver(struct usb_device_driver* driver);
38
39/**
40 * Initialize usb stack.
41 */
42void 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 */
80void 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 */
114void 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 */
130void 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 */
143void 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 */
156int 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 */
192int 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 */
223void 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
265int 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 */
275int 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
298int 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
342void 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
353static 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
378static 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
diff --git a/firmware/usbstack/core/epsetup.c b/firmware/usbstack/core/epsetup.c
new file mode 100644
index 0000000000..6ae54fb9ac
--- /dev/null
+++ b/firmware/usbstack/core/epsetup.c
@@ -0,0 +1,186 @@
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 <string.h>
21#include <ctype.h>
22#include "usbstack/core.h"
23
24/**
25 *
26 * Naming Convention for Endpoint Names
27 *
28 * - ep1, ep2, ... address is fixed, not direction or type
29 * - ep1in, ep2out, ... address and direction are fixed, not type
30 * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
31 * - ep1in-bulk, ep2out-iso, ... all three are fixed
32 * - ep-* ... no functionality restrictions
33 *
34 * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
35 *
36 */
37static int ep_matches(struct usb_ep* ep, struct usb_endpoint_descriptor* desc);
38
39void usb_ep_autoconfig_reset(void) {
40
41 struct usb_ep* ep = NULL;
42 if (usbcore.active_controller == NULL) {
43 return;
44 }
45
46 logf("resetting endpoints");
47 list_for_each_entry(ep, &usbcore.active_controller->endpoints.list, list) {
48 logf("reset %s", ep->name);
49 ep->claimed = false;
50 }
51}
52
53/**
54 * Find a suitable endpoint for the requested endpoint descriptor.
55 * @param desc usb descritpro to use for seraching.
56 * @return NULL or a valid endpoint.
57 */
58struct usb_ep* usb_ep_autoconfig(struct usb_endpoint_descriptor* desc) {
59
60 struct usb_ep* ep = NULL;
61 if (usbcore.active_controller == NULL) {
62 logf("active controller NULL");
63 return NULL;
64 }
65
66 list_for_each_entry(ep, &usbcore.active_controller->endpoints.list, list) {
67 if (ep_matches (ep, desc)) {
68 return ep;
69 }
70 }
71
72 return NULL;
73}
74
75static int ep_matches(struct usb_ep* ep, struct usb_endpoint_descriptor* desc) {
76
77 uint8_t type;
78 const char* tmp;
79 uint16_t max;
80
81 /* endpoint already claimed? */
82 if (ep->claimed) {
83 logf("!! claimed !!");
84 return 0;
85 }
86
87 /* only support ep0 for portable CONTROL traffic */
88 type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
89 if (type == USB_ENDPOINT_XFER_CONTROL) {
90 logf("type == control");
91 return 0;
92 }
93
94 /* some other naming convention */
95 if (ep->name[0] != 'e') {
96 logf("wrong name");
97 return 0;
98 }
99
100 /* type-restriction: "-iso", "-bulk", or "-int".
101 * direction-restriction: "in", "out".
102 */
103 if (ep->name[2] != '-' ) {
104 tmp = strrchr (ep->name, '-');
105 if (tmp) {
106 switch (type) {
107 case USB_ENDPOINT_XFER_INT:
108 /* bulk endpoints handle interrupt transfers,
109 * except the toggle-quirky iso-synch kind
110 */
111 if (tmp[2] == 's') { // == "-iso"
112 return 0;
113 }
114 break;
115 case USB_ENDPOINT_XFER_BULK:
116 if (tmp[1] != 'b') { // != "-bulk"
117 return 0;
118 }
119 break;
120 case USB_ENDPOINT_XFER_ISOC:
121 if (tmp[2] != 's') { // != "-iso"
122 return 0;
123 }
124 }
125 } else {
126 tmp = ep->name + strlen (ep->name);
127 }
128
129 /* direction-restriction: "..in-..", "out-.." */
130 tmp--;
131 if (!isdigit(*tmp)) {
132 if (desc->bEndpointAddress & USB_DIR_IN) {
133 if ('n' != *tmp) {
134 return 0;
135 }
136 } else {
137 if ('t' != *tmp) {
138 return 0;
139 }
140 }
141 }
142 }
143
144
145 /* endpoint maxpacket size is an input parameter, except for bulk
146 * where it's an output parameter representing the full speed limit.
147 * the usb spec fixes high speed bulk maxpacket at 512 bytes.
148 */
149 max = 0x7ff & desc->wMaxPacketSize;
150
151 switch (type) {
152 case USB_ENDPOINT_XFER_INT:
153 /* INT: limit 64 bytes full speed, 1024 high speed */
154 if ((usbcore.active_controller->speed != USB_SPEED_HIGH) && (max > 64)) {
155 return 0;
156 }
157 /* FALLTHROUGH */
158
159 case USB_ENDPOINT_XFER_ISOC:
160 if ((usbcore.active_controller->speed != USB_SPEED_HIGH) && (max > 1023)) {
161 return 0;
162 }
163 break;
164 }
165
166 /* MATCH!! */
167
168 /* report address */
169 desc->bEndpointAddress |= ep->ep_num;
170
171 /* report (variable) full speed bulk maxpacket */
172 if (type == USB_ENDPOINT_XFER_BULK) {
173 int size = max;
174
175 /* min() doesn't work on bitfields with gcc-3.5 */
176 if (size > 64) {
177 size = 64;
178 }
179 desc->wMaxPacketSize = size;
180 }
181
182 /* save desc in endpoint */
183 ep->desc = desc;
184
185 return 1;
186}
diff --git a/firmware/usbstack/core/utils.c b/firmware/usbstack/core/utils.c
new file mode 100644
index 0000000000..2fb2695732
--- /dev/null
+++ b/firmware/usbstack/core/utils.c
@@ -0,0 +1,125 @@
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 <string.h>
21#include "usbstack/core.h"
22
23void into_usb_ctrlrequest(struct usb_ctrlrequest* request) {
24
25 char* type = "";
26 char* req = "";
27 char* extra = 0;
28
29 logf("-usb request-");
30 /* check if packet is okay */
31 if (request->bRequestType == 0 &&
32 request->bRequest == 0 &&
33 request->wValue == 0 &&
34 request->wIndex == 0 &&
35 request->wLength == 0) {
36 logf(" -> INVALID <-");
37 return;
38 }
39
40 switch (request->bRequestType & USB_TYPE_MASK) {
41 case USB_TYPE_STANDARD:
42 type = "standard";
43
44 switch (request->bRequest) {
45 case USB_REQ_GET_STATUS:
46 req = "get status";
47 break;
48 case USB_REQ_CLEAR_FEATURE:
49 req = "clear feature";
50 break;
51 case USB_REQ_SET_FEATURE:
52 req = "set feature";
53 break;
54 case USB_REQ_SET_ADDRESS:
55 req = "set address";
56 break;
57 case USB_REQ_GET_DESCRIPTOR:
58 req = "get descriptor";
59
60 switch (request->wValue >> 8) {
61 case USB_DT_DEVICE:
62 extra = "get device descriptor";
63 break;
64 case USB_DT_DEVICE_QUALIFIER:
65 extra = "get device qualifier";
66 break;
67 case USB_DT_OTHER_SPEED_CONFIG:
68 extra = "get other-speed config descriptor";
69 case USB_DT_CONFIG:
70 extra = "get configuration descriptor";
71 break;
72 case USB_DT_STRING:
73 extra = "get string descriptor";
74 break;
75 case USB_DT_DEBUG:
76 extra = "debug";
77 break;
78 }
79 break;
80
81 break;
82 case USB_REQ_SET_DESCRIPTOR:
83 req = "set descriptor";
84 break;
85 case USB_REQ_GET_CONFIGURATION:
86 req = "get configuration";
87 break;
88 case USB_REQ_SET_CONFIGURATION:
89 req = "set configuration";
90 break;
91 case USB_REQ_GET_INTERFACE:
92 req = "get interface";
93 break;
94 case USB_REQ_SET_INTERFACE:
95 req = "set interface";
96 break;
97 case USB_REQ_SYNCH_FRAME:
98 req = "sync frame";
99 break;
100 default:
101 req = "unkown";
102 break;
103 }
104
105 break;
106 case USB_TYPE_CLASS:
107 type = "class";
108 break;
109
110 case USB_TYPE_VENDOR:
111 type = "vendor";
112 break;
113 }
114
115 logf(" -b 0x%x", request->bRequestType);
116 logf(" -b 0x%x", request->bRequest);
117 logf(" -b 0x%x", request->wValue);
118 logf(" -b 0x%x", request->wIndex);
119 logf(" -b 0x%x", request->wLength);
120 logf(" -> t: %s", type);
121 logf(" -> r: %s", req);
122 if (extra != 0) {
123 logf(" -> e: %s", extra);
124 }
125}