summaryrefslogtreecommitdiff
path: root/firmware/usbstack
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usbstack')
-rw-r--r--firmware/usbstack/config.h31
-rw-r--r--firmware/usbstack/controller.h68
-rw-r--r--firmware/usbstack/core.h84
-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
-rw-r--r--firmware/usbstack/device.h48
-rw-r--r--firmware/usbstack/drivers/device/usb_serial.c300
-rw-r--r--firmware/usbstack/drivers/device/usb_serial.h32
-rw-r--r--firmware/usbstack/drivers/device/usb_storage.c269
-rw-r--r--firmware/usbstack/drivers/device/usb_storage.h31
-rw-r--r--firmware/usbstack/host.h31
13 files changed, 1677 insertions, 0 deletions
diff --git a/firmware/usbstack/config.h b/firmware/usbstack/config.h
new file mode 100644
index 0000000000..95b00da1b3
--- /dev/null
+++ b/firmware/usbstack/config.h
@@ -0,0 +1,31 @@
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#ifndef _USBSTACK_CONFIG_H_
21#define _USBSTACK_CONFIG_H_
22
23/* default: use no controller */
24#ifndef USBSTACK_CAPS
25#define USBSTACK_CAPS 0
26#endif
27
28#define CONTROLLER_DEVICE (1 << 0)
29#define CONTROLLER_HOST (1 << 1)
30
31#endif /*_USBSTACK_CONFIG_H_*/
diff --git a/firmware/usbstack/controller.h b/firmware/usbstack/controller.h
new file mode 100644
index 0000000000..8e99cf6641
--- /dev/null
+++ b/firmware/usbstack/controller.h
@@ -0,0 +1,68 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: arcotg_udc.c 12340 2007-02-16 22:13:21Z barrywardell $
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#ifndef _USBSTACK_CONTROLLER_H_
21#define _USBSTACK_CONTROLLER_H_
22
23struct usb_controller {
24 const char* name;
25 enum usb_controller_type type;
26 enum usb_device_speed speed;
27 void (*init)(void);
28 void (*shutdown)(void);
29 void (*irq)(void);
30 void (*start)(void);
31 void (*stop)(void);
32 void* controller_ops;
33 struct usb_device_driver* device_driver;
34 struct usb_host_driver* host_driver;
35 struct usb_ep* ep0;
36 struct usb_ep endpoints;
37};
38
39struct usb_dcd_controller_ops {
40 /* endpoint management */
41 int (*enable)(struct usb_ep* ep);
42 int (*disable)(struct usb_ep* ep);
43 int (*set_halt)(struct usb_ep* ep, bool hald);
44
45 /* transmitting */
46 int (*send)(struct usb_ep* ep, struct usb_response* req);
47 int (*receive)(struct usb_ep* ep, struct usb_response* res);
48
49 /* ep0 */
50 struct usb_ep* ep0;
51};
52
53int usb_controller_register(struct usb_controller* ctrl);
54int usb_controller_unregister(struct usb_controller* ctrl);
55
56/*
57 * dcd - device controller driver
58 */
59void usb_dcd_init(void);
60void usb_dcd_shutdown(void);
61
62/*
63 * hcd - host controller driver
64 */
65void usb_hcd_init(void);
66void usb_hcd_shutdown(void);
67
68#endif /*_USBSTACK_CONTROLLER_H_*/
diff --git a/firmware/usbstack/core.h b/firmware/usbstack/core.h
new file mode 100644
index 0000000000..7bda2934e7
--- /dev/null
+++ b/firmware/usbstack/core.h
@@ -0,0 +1,84 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: arcotg_udc.c 12340 2007-02-16 22:13:21Z barrywardell $
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#ifndef _USBSTACK_CORE_H_
21#define _USBSTACK_CORE_H_
22
23#include "linkedlist.h"
24#include "usb_ch9.h"
25#include "logf.h"
26#include "system.h"
27
28#include "usbstack.h"
29
30/*
31 * stack datatypes
32 */
33struct usb_response {
34 void* buf;
35 uint32_t length;
36};
37
38struct usb_ep {
39 const char name[15];
40 uint8_t type;
41 uint32_t ep_num; /* which endpoint? */
42 uint32_t pipe_num; /* which pipe? */
43 uint32_t maxpacket;
44 bool claimed;
45
46 struct usb_endpoint_descriptor *desc;
47 struct list_head list;
48};
49
50#include "usbstack/controller.h"
51#include "usbstack/device.h"
52#include "usbstack/host.h"
53
54#define NUM_DRIVERS 3
55
56/*
57 * usb core
58 */
59struct usb_core {
60 /* we can have maximum two controllers (one device, one host) */
61 struct usb_controller* controller[2];
62 struct usb_controller* active_controller;
63 /* device driver used by stack */
64 struct usb_device_driver* device_driver;
65 /* for each type of driver use own array */
66 struct usb_host_driver* host_drivers[NUM_DRIVERS];
67 struct usb_device_driver* device_drivers[NUM_DRIVERS];
68 enum usb_controller_type mode;
69 bool running;
70};
71
72void usb_stack_irq(void);
73void usb_stack_work(void);
74
75/* endpoint configuration */
76void usb_ep_autoconfig_reset(void);
77struct usb_ep* usb_ep_autoconfig(struct usb_endpoint_descriptor* desc);
78
79/* only used for debug */
80void into_usb_ctrlrequest(struct usb_ctrlrequest* request);
81
82extern struct usb_core usbcore;
83
84#endif /*_USBSTACK_CORE_H_*/
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}
diff --git a/firmware/usbstack/device.h b/firmware/usbstack/device.h
new file mode 100644
index 0000000000..5b385d8129
--- /dev/null
+++ b/firmware/usbstack/device.h
@@ -0,0 +1,48 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: arcotg_udc.c 12340 2007-02-16 22:13:21Z barrywardell $
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#ifndef _USBSTACK_DEVICE_H_
21#define _USBSTACK_DEVICE_H_
22
23/*
24 * usb device driver
25 */
26struct usb_device_driver {
27 const char* name;
28 void (*bind)(void* controller_ops);
29 void (*unbind)(void);
30 int (*request)(struct usb_ctrlrequest* req);
31 void (*suspend)(void);
32 void (*resume)(void);
33 void (*speed)(enum usb_device_speed speed);
34 struct usb_descriptors* descriptors;
35 void* data; /* used to store controller specific ops struct */
36};
37
38int usb_device_driver_register(struct usb_device_driver* driver);
39
40/* forward declaration */
41struct usb_config_descriptor;
42struct usb_descriptor_header;
43
44int usb_stack_configdesc(const struct usb_config_descriptor* config,
45 void* buf, unsigned length,
46 struct usb_descriptor_header** desc);
47
48#endif /*_USBSTACK_DEVICE_H_*/
diff --git a/firmware/usbstack/drivers/device/usb_serial.c b/firmware/usbstack/drivers/device/usb_serial.c
new file mode 100644
index 0000000000..fe1e52f25a
--- /dev/null
+++ b/firmware/usbstack/drivers/device/usb_serial.c
@@ -0,0 +1,300 @@
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 "usb_serial.h"
21#include <string.h>
22
23static struct usb_dcd_controller_ops* ops;
24
25struct usb_device_driver usb_serial_driver = {
26 .name = "serial",
27 .bind = usb_serial_driver_bind,
28 .unbind = NULL,
29 .request = usb_serial_driver_request,
30 .suspend = NULL,
31 .resume = NULL,
32 .speed = usb_serial_driver_speed,
33};
34
35/*-------------------------------------------------------------------------*/
36/* usb descriptors */
37
38/* TODO: implement strings */
39#define GS_MANUFACTURER_STR_ID 0
40#define GS_PRODUCT_STR_ID 0
41#define GS_SERIAL_STR_ID 0
42#define GS_BULK_CONFIG_STR_ID 0
43#define GS_DATA_STR_ID 0
44
45#define GS_BULK_CONFIG_ID 1
46
47static struct usb_device_descriptor serial_device_desc = {
48 .bLength = USB_DT_DEVICE_SIZE,
49 .bDescriptorType = USB_DT_DEVICE,
50 .bcdUSB = 0x0200,
51 .bDeviceClass = USB_CLASS_COMM,
52 .bDeviceSubClass = 0,
53 .bDeviceProtocol = 0,
54 .idVendor = 0x0525,
55 .idProduct = 0xa4a6,
56 .iManufacturer = GS_MANUFACTURER_STR_ID,
57 .iProduct = GS_PRODUCT_STR_ID,
58 .iSerialNumber = GS_SERIAL_STR_ID,
59 .bNumConfigurations = 1,
60};
61
62static struct usb_config_descriptor serial_bulk_config_desc = {
63 .bLength = USB_DT_CONFIG_SIZE,
64 .bDescriptorType = USB_DT_CONFIG,
65
66 .bNumInterfaces = 1,
67 .bConfigurationValue = GS_BULK_CONFIG_ID,
68 .iConfiguration = GS_BULK_CONFIG_STR_ID,
69 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
70 .bMaxPower = 1,
71};
72
73static struct usb_interface_descriptor serial_bulk_interface_desc = {
74 .bLength = USB_DT_INTERFACE_SIZE,
75 .bDescriptorType = USB_DT_INTERFACE,
76 .bInterfaceNumber = 0,
77 .bNumEndpoints = 2,
78 .bInterfaceClass = USB_CLASS_CDC_DATA,
79 .bInterfaceSubClass = 0,
80 .bInterfaceProtocol = 0,
81 .iInterface = GS_DATA_STR_ID,
82};
83
84static struct usb_endpoint_descriptor serial_fullspeed_in_desc = {
85 .bLength = USB_DT_ENDPOINT_SIZE,
86 .bDescriptorType = USB_DT_ENDPOINT,
87 .bEndpointAddress = USB_DIR_IN,
88 .bmAttributes = USB_ENDPOINT_XFER_BULK,
89 .wMaxPacketSize = 8,
90};
91
92static struct usb_endpoint_descriptor serial_fullspeed_out_desc = {
93 .bLength = USB_DT_ENDPOINT_SIZE,
94 .bDescriptorType = USB_DT_ENDPOINT,
95 .bEndpointAddress = USB_DIR_OUT,
96 .bmAttributes = USB_ENDPOINT_XFER_BULK,
97 .wMaxPacketSize = 8,
98};
99
100static struct usb_debug_descriptor serial_debug_desc = {
101 .bLength = sizeof(struct usb_debug_descriptor),
102 .bDescriptorType = USB_DT_DEBUG,
103};
104
105static struct usb_qualifier_descriptor serial_qualifier_desc = {
106 .bLength = sizeof(struct usb_qualifier_descriptor),
107 .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
108 .bcdUSB = 0x0200,
109 .bDeviceClass = USB_CLASS_COMM,
110 .bNumConfigurations = 1,
111};
112
113struct usb_descriptor_header *serial_bulk_fullspeed_function[] = {
114 (struct usb_descriptor_header *) &serial_bulk_interface_desc,
115 (struct usb_descriptor_header *) &serial_fullspeed_in_desc,
116 (struct usb_descriptor_header *) &serial_fullspeed_out_desc,
117 NULL,
118};
119
120#define BUFFER_SIZE 100
121uint8_t buf[BUFFER_SIZE];
122
123struct usb_response res;
124
125/* helper functions */
126static int config_buf(uint8_t *buf, uint8_t type, unsigned index);
127static int set_config(int config);
128
129
130struct device {
131 struct usb_ep* in;
132 struct usb_ep* out;
133 uint32_t used_config;
134};
135
136static struct device dev;
137
138/*-------------------------------------------------------------------------*/
139
140void usb_serial_driver_init(void) {
141
142 logf("usb serial: register");
143 usb_device_driver_register(&usb_serial_driver);
144}
145
146/*-------------------------------------------------------------------------*/
147
148void usb_serial_driver_bind(void* controler_ops) {
149
150 logf("usb serial: bind");
151 ops = controler_ops;
152
153 /* serach and asign endpoints */
154 usb_ep_autoconfig_reset();
155
156 dev.in = usb_ep_autoconfig(&serial_fullspeed_in_desc);
157 if (!dev.in) {
158 goto autoconf_fail;
159 }
160 dev.in->claimed = true;
161 logf("usb serial: in: %s", dev.in->name);
162
163 dev.out = usb_ep_autoconfig(&serial_fullspeed_out_desc);
164 if (!dev.out) {
165 goto autoconf_fail;
166 }
167 dev.out->claimed = true;
168 logf("usb serial: out: %s", dev.out->name);
169
170 /* update device decsriptor */
171 serial_device_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
172
173 /* update qualifie descriptor */
174 serial_qualifier_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
175
176 /* update debug descriptor */
177 serial_debug_desc.bDebugInEndpoint = dev.in->ep_num;
178 serial_debug_desc.bDebugOutEndpoint = dev.out->ep_num;
179
180 return;
181
182autoconf_fail:
183 logf("failed to find endpoiunts");
184}
185
186int usb_serial_driver_request(struct usb_ctrlrequest* request) {
187
188 int ret = -EOPNOTSUPP;
189 logf("usb serial: request");
190
191 res.length = 0;
192 res.buf = NULL;
193
194 switch (request->bRequestType & USB_TYPE_MASK) {
195 case USB_TYPE_STANDARD:
196
197 switch (request->bRequest) {
198 case USB_REQ_GET_DESCRIPTOR:
199
200 switch (request->wValue >> 8) {
201 case USB_DT_DEVICE:
202 logf("usb serial: sending device desc");
203 ret = MIN(sizeof(struct usb_device_descriptor), request->wLength);
204 res.buf = &serial_device_desc;
205 break;
206
207 case USB_DT_DEVICE_QUALIFIER:
208 logf("usb serial: sending qualifier dec");
209 ret = MIN(sizeof(struct usb_qualifier_descriptor), request->wLength);
210 res.buf = &serial_qualifier_desc;
211
212 case USB_DT_CONFIG:
213 logf("usb serial: sending config desc");
214
215 ret = config_buf(buf, request->wValue >> 8, request->wValue & 0xff);
216 if (ret >= 0) {
217 logf("%d, vs %d", request->wLength, ret);
218 ret = MIN(request->wLength, (uint16_t)ret);
219 }
220 res.buf = buf;
221 break;
222
223 case USB_DT_DEBUG:
224 logf("usb serial: sending debug desc");
225 ret = MIN(sizeof(struct usb_debug_descriptor), request->wLength);
226 res.buf = &serial_debug_desc;
227 break;
228 }
229 break;
230
231 case USB_REQ_SET_CONFIGURATION:
232 logf("usb serial: set configuration %d", request->wValue);
233 ret = set_config(request->wValue);
234 break;
235
236 case USB_REQ_GET_CONFIGURATION:
237 logf("usb serial: get configuration");
238 ret = 1;
239 res.buf = &dev.used_config;
240 break;
241 }
242 }
243
244 if (ret >= 0) {
245 res.length = ret;
246 ret = ops->send(NULL, &res);
247 }
248
249 return ret;
250}
251
252void usb_serial_driver_speed(enum usb_device_speed speed) {
253
254 switch (speed) {
255 case USB_SPEED_LOW:
256 case USB_SPEED_FULL:
257 logf("usb serial: using fullspeed");
258 break;
259 case USB_SPEED_HIGH:
260 logf("usb serial: using highspeed");
261 break;
262 default:
263 logf("speed: hmm");
264 break;
265 }
266}
267
268/*-------------------------------------------------------------------------*/
269/* helper functions */
270
271static int config_buf(uint8_t *buf, uint8_t type, unsigned index) {
272
273 int len;
274
275 /* TODO check index*/
276
277 len = usb_stack_configdesc(&serial_bulk_config_desc, buf, BUFFER_SIZE, serial_bulk_fullspeed_function);
278 if (len < 0) {
279 return len;
280 }
281 ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
282 return len;
283}
284
285static int set_config(int config) {
286
287 /* TODO check config*/
288
289 /* enable endpoints */
290 logf("setup %s", dev.in->name);
291 ops->enable(dev.in);
292 logf("setup %s", dev.out->name);
293 ops->enable(dev.out);
294
295 /* store config */
296 logf("using config %d", config);
297 dev.used_config = config;
298
299 return 0;
300}
diff --git a/firmware/usbstack/drivers/device/usb_serial.h b/firmware/usbstack/drivers/device/usb_serial.h
new file mode 100644
index 0000000000..808eaa16e3
--- /dev/null
+++ b/firmware/usbstack/drivers/device/usb_serial.h
@@ -0,0 +1,32 @@
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#ifndef _SERIAL_H_
21#define _SERIAL_H_
22
23#include "usbstack/core.h"
24
25/* register serial driver in usb stack */
26void usb_serial_driver_init(void);
27
28void usb_serial_driver_bind(void* controller_ops);
29int usb_serial_driver_request(struct usb_ctrlrequest* req);
30void usb_serial_driver_speed(enum usb_device_speed speed);
31
32#endif /*_SERIAL_H_*/
diff --git a/firmware/usbstack/drivers/device/usb_storage.c b/firmware/usbstack/drivers/device/usb_storage.c
new file mode 100644
index 0000000000..0cb1f108b5
--- /dev/null
+++ b/firmware/usbstack/drivers/device/usb_storage.c
@@ -0,0 +1,269 @@
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 "usb_storage.h"
21#include <string.h>
22
23/*-------------------------------------------------------------------------*/
24
25static struct usb_dcd_controller_ops* ops;
26
27struct usb_device_driver usb_storage_driver = {
28 .name = "storage",
29 .bind = usb_storage_driver_bind,
30 .unbind = NULL,
31 .request = usb_storage_driver_request,
32 .suspend = NULL,
33 .resume = NULL,
34 .speed = NULL,
35};
36
37struct device {
38 struct usb_ep* in;
39 struct usb_ep* out;
40 struct usb_ep* intr;
41};
42
43static struct device dev;
44
45/*-------------------------------------------------------------------------*/
46
47#define PROTO_BULK 0x50 // Bulk only
48#define SUBCL_SCSI 0x06 // Transparent SCSI
49
50/* Bulk-only class specific requests */
51#define USB_BULK_RESET_REQUEST 0xff
52#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe
53
54/*-------------------------------------------------------------------------*/
55/* usb descriptors */
56
57static struct usb_device_descriptor storage_device_desc = {
58 .bLength = USB_DT_DEVICE_SIZE,
59 .bDescriptorType = USB_DT_DEVICE,
60 .bcdUSB = 0x0200,
61 .bDeviceClass = 0,
62 .bDeviceSubClass = 0,
63 .bDeviceProtocol = 0,
64 .bMaxPacketSize0 = 64,
65 .idVendor = 0xffff,
66 .idProduct = 0x0001,
67 .iManufacturer = 0,
68 .iProduct = 0,
69 .iSerialNumber = 0,
70 .bNumConfigurations = 1,
71};
72
73static struct usb_config_descriptor storage_config_desc = {
74 .bLength = USB_DT_CONFIG_SIZE,
75 .bDescriptorType = USB_DT_CONFIG,
76
77 .bNumInterfaces = 1,
78 .bConfigurationValue = 1,
79 .iConfiguration = 0,
80 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
81 .bMaxPower = 1,
82};
83
84static struct usb_interface_descriptor storage_interface_desc = {
85 .bLength = USB_DT_INTERFACE_SIZE,
86 .bDescriptorType = USB_DT_INTERFACE,
87 .bInterfaceNumber = 0,
88 .bNumEndpoints = 3,
89 .bInterfaceClass = USB_CLASS_MASS_STORAGE,
90 .bInterfaceSubClass = SUBCL_SCSI,
91 .bInterfaceProtocol = PROTO_BULK,
92 .iInterface = 0,
93};
94
95/* endpoint I -> bulk in */
96static struct usb_endpoint_descriptor storage_bulk_in_desc = {
97 .bLength = USB_DT_ENDPOINT_SIZE,
98 .bDescriptorType = USB_DT_ENDPOINT,
99 .bEndpointAddress = USB_DIR_IN,
100 .bmAttributes = USB_ENDPOINT_XFER_BULK,
101 .wMaxPacketSize = 512,
102};
103
104/* endpoint II -> bulk out */
105static struct usb_endpoint_descriptor storage_bulk_out_desc = {
106 .bLength = USB_DT_ENDPOINT_SIZE,
107 .bDescriptorType = USB_DT_ENDPOINT,
108 .bEndpointAddress = USB_DIR_OUT,
109 .bmAttributes = USB_ENDPOINT_XFER_BULK,
110 .wMaxPacketSize = 512,
111};
112
113struct usb_descriptor_header *storage_fullspeed_function[] = {
114 (struct usb_descriptor_header *) &storage_interface_desc,
115 (struct usb_descriptor_header *) &storage_bulk_in_desc,
116 (struct usb_descriptor_header *) &storage_bulk_out_desc,
117 NULL,
118};
119
120#define BUFFER_SIZE 100
121uint8_t buf[BUFFER_SIZE];
122
123struct usb_response res;
124
125/* helper functions */
126static int config_buf(uint8_t *buf, uint8_t type, unsigned index);
127static int set_config(int config);
128
129/*-------------------------------------------------------------------------*/
130
131void usb_storage_driver_init(void) {
132
133 logf("usb storage: register");
134 usb_device_driver_register(&usb_storage_driver);
135}
136
137/*-------------------------------------------------------------------------*/
138/* device driver ops */
139
140void usb_storage_driver_bind(void* controler_ops) {
141
142 ops = controler_ops;
143
144 /* serach and asign endpoints */
145 usb_ep_autoconfig_reset();
146
147 dev.in = usb_ep_autoconfig(&storage_bulk_in_desc);
148 if (!dev.in) {
149 goto autoconf_fail;
150 }
151 dev.in->claimed = true;
152 logf("usb storage: in: %s", dev.in->name);
153
154 dev.out = usb_ep_autoconfig(&storage_bulk_out_desc);
155 if (!dev.out) {
156 goto autoconf_fail;
157 }
158 dev.out->claimed = true;
159 logf("usb storage: out: %s", dev.out->name);
160
161 return;
162
163autoconf_fail:
164 logf("failed to find endpoints");
165}
166
167int usb_storage_driver_request(struct usb_ctrlrequest* request) {
168
169 int ret = -EOPNOTSUPP;
170 logf("usb storage: request");
171
172 res.length = 0;
173 res.buf = NULL;
174
175 switch (request->bRequestType & USB_TYPE_MASK) {
176 case USB_TYPE_STANDARD:
177
178 switch (request->bRequest) {
179 case USB_REQ_GET_DESCRIPTOR:
180
181 switch (request->wValue >> 8) {
182 case USB_DT_DEVICE:
183 logf("usb storage: sending device desc");
184 ret = MIN(sizeof(struct usb_device_descriptor), request->wLength);
185 res.buf = &storage_device_desc;
186 break;
187
188 case USB_DT_CONFIG:
189 logf("usb storage: sending config desc");
190
191 ret = config_buf(buf, request->wValue >> 8, request->wValue & 0xff);
192 if (ret >= 0) {
193 logf("%d, vs %d", request->wLength, ret);
194 ret = MIN(request->wLength, (uint16_t)ret);
195 }
196 res.buf = buf;
197 break;
198 }
199 break;
200
201 case USB_REQ_SET_CONFIGURATION:
202 logf("usb storage: set configuration %d", request->wValue);
203 ret = set_config(request->wValue);
204 break;
205
206 case USB_REQ_SET_INTERFACE:
207 logf("usb storage: set interface");
208 ret = 0;
209 break;
210 }
211
212 case USB_TYPE_CLASS:
213
214 switch (request->bRequest) {
215 case USB_BULK_RESET_REQUEST:
216 logf("usb storage: bulk reset");
217 break;
218
219 case USB_BULK_GET_MAX_LUN_REQUEST:
220 logf("usb storage: get max lun");
221 /* we support no LUNs (Logical Unit Number) */
222 buf[0] = 0;
223 ret = 1;
224 break;
225 }
226 break;
227 }
228
229 if (ret >= 0) {
230 res.length = ret;
231 ret = ops->send(NULL, &res);
232 }
233
234 return ret;
235}
236
237/*-------------------------------------------------------------------------*/
238/* S/GET CONFIGURATION helpers */
239
240static int config_buf(uint8_t *buf, uint8_t type, unsigned index) {
241
242 int len;
243
244 /* only one configuration */
245 if (index != 0) {
246 return -EINVAL;
247 }
248
249 len = usb_stack_configdesc(&storage_config_desc, buf, BUFFER_SIZE, storage_fullspeed_function);
250 if (len < 0) {
251 return len;
252 }
253 ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
254 return len;
255}
256
257static int set_config(int config) {
258
259 /* enable endpoints */
260 logf("setup %s", dev.in->name);
261 ops->enable(dev.in);
262 logf("setup %s", dev.out->name);
263 ops->enable(dev.out);
264
265 /* setup buffers */
266
267 return 0;
268}
269
diff --git a/firmware/usbstack/drivers/device/usb_storage.h b/firmware/usbstack/drivers/device/usb_storage.h
new file mode 100644
index 0000000000..9494aa76ff
--- /dev/null
+++ b/firmware/usbstack/drivers/device/usb_storage.h
@@ -0,0 +1,31 @@
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#ifndef _STORGAGE_H_
21#define _STORGAGE_H_
22
23#include "usbstack/core.h"
24
25/* register serial driver in usb stack */
26void usb_storage_driver_init(void);
27
28void usb_storage_driver_bind(void* controller_ops);
29int usb_storage_driver_request(struct usb_ctrlrequest* req);
30
31#endif /*_STORGAGE_H_*/
diff --git a/firmware/usbstack/host.h b/firmware/usbstack/host.h
new file mode 100644
index 0000000000..cb2f550e46
--- /dev/null
+++ b/firmware/usbstack/host.h
@@ -0,0 +1,31 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: arcotg_udc.c 12340 2007-02-16 22:13:21Z barrywardell $
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#ifndef _USBSTACK_HOST_H_
21#define _USBSTACK_HOST_H_
22
23/*
24 * usb host driver
25 */
26struct usb_host_driver {
27 const char* name;
28 void* data; /* used to store controller specific ops struct */
29};
30
31#endif /*_USBSTACK_HOST_H_*/