summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Gmeiner <christian.gmeiner@gmail.com>2007-08-27 16:04:32 +0000
committerChristian Gmeiner <christian.gmeiner@gmail.com>2007-08-27 16:04:32 +0000
commit8181a0c905a591caef684a2d7487feedbec84c10 (patch)
tree3939183e8e73928d1b5dcfc97b40f33b6baa309b
parent9305c86f5b8fdfd60882428f884ba29bded8da78 (diff)
downloadrockbox-8181a0c905a591caef684a2d7487feedbec84c10.tar.gz
rockbox-8181a0c905a591caef684a2d7487feedbec84c10.zip
Usb Stack: only setup packet handling, and not enabled by default as there is a lot to do.
* settings code is not fully ready -> changing device driver has no effect * clean ups * check copyriths * find a way to detect IN transfers * support for full and highspeed * ... git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14470 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/lang/english.lang70
-rw-r--r--apps/main.c9
-rw-r--r--apps/menus/settings_menu.c89
-rw-r--r--apps/settings.c10
-rw-r--r--apps/settings.h4
-rw-r--r--apps/settings_list.c11
-rw-r--r--firmware/SOURCES15
-rw-r--r--firmware/drivers/usb/arcotg_dcd.c983
-rw-r--r--firmware/drivers/usb/arcotg_dcd.h173
-rw-r--r--firmware/export/arcotg_udc.h4
-rw-r--r--firmware/export/config-e200.h2
-rw-r--r--firmware/export/linkedlist.h710
-rw-r--r--firmware/export/usb_ch9.h762
-rw-r--r--firmware/export/usbstack.h55
-rw-r--r--firmware/target/arm/system-pp502x.c11
-rw-r--r--firmware/target/arm/usb-fw-pp502x.c72
-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
29 files changed, 4585 insertions, 72 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index adc3041119..2503fa500a 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -11156,3 +11156,73 @@
11156 recording: "" 11156 recording: ""
11157 </voice> 11157 </voice>
11158</phrase> 11158</phrase>
11159<phrase>
11160 id: LANG_USBSTACK
11161 desc: in settings_menu
11162 user:
11163 <source>
11164 *: "USB Stack"
11165 </source>
11166 <dest>
11167 *: "USB Stack"
11168 </dest>
11169 <voice>
11170 *: "USB Stack"
11171 </voice>
11172</phrase>
11173<phrase>
11174 id: LANG_USBSTACK_MODE
11175 desc: in usbstack settings
11176 user:
11177 <source>
11178 *: "USB Stack Mode"
11179 </source>
11180 <dest>
11181 *: "USB Stack Mode"
11182 </dest>
11183 <voice>
11184 *: "USB Stack Mode"
11185 </voice>
11186</phrase>
11187<phrase>
11188 id: LANG_USBSTACK_DEVICE
11189 desc: in usbstack settings
11190 user:
11191 <source>
11192 *: "Device"
11193 </source>
11194 <dest>
11195 *: "Device"
11196 </dest>
11197 <voice>
11198 *: "Device"
11199 </voice>
11200</phrase>
11201<phrase>
11202 id: LANG_USBSTACK_HOST
11203 desc: in usbstack settings
11204 user:
11205 <source>
11206 *: "Host"
11207 </source>
11208 <dest>
11209 *: "Host"
11210 </dest>
11211 <voice>
11212 *: "Host"
11213 </voice>
11214</phrase>
11215<phrase>
11216 id: LANG_USBSTACK_DEVICE_DRIVER
11217 desc: in usbstack settings
11218 user:
11219 <source>
11220 *: "Device Driver"
11221 </source>
11222 <dest>
11223 *: "Device Driver"
11224 </dest>
11225 <voice>
11226 *: "Device Driver"
11227 </voice>
11228</phrase> \ No newline at end of file
diff --git a/apps/main.c b/apps/main.c
index df250843e5..54787d6e9e 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -99,6 +99,10 @@
99#include "lcd-remote.h" 99#include "lcd-remote.h"
100#endif 100#endif
101 101
102#ifdef HAVE_USBSTACK
103#include "usbstack.h"
104#endif
105
102#if CONFIG_USBOTG == USBOTG_ISP1362 106#if CONFIG_USBOTG == USBOTG_ISP1362
103#include "isp1362.h" 107#include "isp1362.h"
104#endif 108#endif
@@ -373,7 +377,10 @@ static void init(void)
373#endif 377#endif
374 378
375 adc_init(); 379 adc_init();
376 380
381#ifdef HAVE_USBSTACK
382 usb_stack_init();
383#endif
377 usb_init(); 384 usb_init();
378#if CONFIG_USBOTG == USBOTG_ISP1362 385#if CONFIG_USBOTG == USBOTG_ISP1362
379 isp1362_init(); 386 isp1362_init();
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 039949835b..5c97ac21db 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -42,6 +42,13 @@
42#include "radio.h" 42#include "radio.h"
43#endif 43#endif
44 44
45#ifdef HAVE_USBSTACK
46#include "list.h"
47#include "usbstack.h"
48#include "statusbar.h"
49#include "misc.h"
50#endif
51
45/***********************************/ 52/***********************************/
46/* TAGCACHE MENU */ 53/* TAGCACHE MENU */
47#ifdef HAVE_TAGCACHE 54#ifdef HAVE_TAGCACHE
@@ -442,6 +449,82 @@ MAKE_MENU(voice_settings_menu, ID2P(LANG_VOICE), 0, Icon_Voice,
442/* VOICE MENU */ 449/* VOICE MENU */
443/***********************************/ 450/***********************************/
444 451
452#ifdef HAVE_USBSTACK
453/***********************************/
454/* USB STACK MENU */
455char drivers[16][32];
456static char* usb_menu_getname(int item, void * data, char *buffer)
457{
458 (void)data; (void)buffer;
459 return drivers[item];
460}
461int usbdriver_menuitem(void)
462{
463 struct gui_synclist lists;
464 int action, count = 0;
465 char *s = device_driver_names, *e;
466 do {
467 e = strchr(s, ',');
468 if (e)
469 {
470 strncpy(drivers[count++], s, e-s);
471 s = e+1;
472 }
473 } while (e && count < 16);
474 if (count < 16)
475 strcpy(drivers[count++], s);
476 for (action=0; action<count; action++)
477 {
478 if (!strcmp(drivers[action],
479 global_settings.usb_stack_device_driver))
480 break;
481 }
482
483 gui_synclist_init(&lists, usb_menu_getname, drivers, false, 1);
484 gui_synclist_set_title(&lists, str(LANG_USBSTACK_DEVICE_DRIVER), NOICON);
485 gui_synclist_set_icon_callback(&lists, NULL);
486 gui_synclist_set_nb_items(&lists, count);
487 gui_synclist_select_item(&lists, action==count?0:action);
488 gui_synclist_draw(&lists);
489
490 while(1)
491 {
492 gui_syncstatusbar_draw(&statusbars, true);
493 action = get_action(CONTEXT_STD, HZ/5);
494 if (gui_synclist_do_button(&lists, action, LIST_WRAP_UNLESS_HELD))
495 continue;
496 if (action == ACTION_STD_CANCEL)
497 {
498 // setting was canceled
499 break;
500 }
501 else if (action == ACTION_STD_OK)
502 {
503 // setting was accepted... save
504 strcpy(global_settings.usb_stack_device_driver,
505 drivers[gui_synclist_get_sel_pos(&lists)]);
506 break;
507 }
508 else if (action == ACTION_REDRAW)
509 gui_synclist_draw(&lists);
510 else if(default_event_handler(action) == SYS_USB_CONNECTED)
511 return true;
512 }
513 return false;
514}
515
516MENUITEM_SETTING(usbstack_mode, &global_settings.usb_stack_mode, NULL);
517MENUITEM_FUNCTION(usbdriver, 0, ID2P(LANG_USBSTACK_DEVICE_DRIVER),
518 usbdriver_menuitem, 0, NULL, Icon_NOICON);
519
520MAKE_MENU(usbstack_menu, ID2P(LANG_USBSTACK), 0, Icon_NOICON,
521 &usbstack_mode, &usbdriver);
522/* USB STACK MENU */
523/***********************************/
524#endif
525
526/***********************************/
527
445/***********************************/ 528/***********************************/
446/* SETTINGS MENU */ 529/* SETTINGS MENU */
447static int language_browse(void) 530static int language_browse(void)
@@ -458,6 +541,10 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
458 &tagcache_menu, 541 &tagcache_menu,
459#endif 542#endif
460 &display_menu, &system_menu, 543 &display_menu, &system_menu,
461 &bookmark_settings_menu, &browse_langs, &voice_settings_menu ); 544 &bookmark_settings_menu, &browse_langs, &voice_settings_menu
545#ifdef HAVE_USBSTACK
546 , &usbstack_menu
547#endif
548 );
462/* SETTINGS MENU */ 549/* SETTINGS MENU */
463/***********************************/ 550/***********************************/
diff --git a/apps/settings.c b/apps/settings.c
index cd1c252426..c7c8772975 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -98,6 +98,10 @@ struct system_status global_status;
98#include "lcd-remote.h" 98#include "lcd-remote.h"
99#endif 99#endif
100 100
101#ifdef HAVE_USBSTACK
102#include "usbstack.h"
103#endif
104
101long lasttime = 0; 105long lasttime = 0;
102 106
103/** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/ 107/** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/
@@ -875,11 +879,13 @@ void settings_apply(void)
875 read_color_theme_file(); 879 read_color_theme_file();
876#endif 880#endif
877 881
882#ifdef HAVE_USBSTACK
883 usb_controller_select(global_settings.usb_stack_mode);
884 usb_device_driver_bind(global_settings.usb_stack_device_driver);
885#endif
878} 886}
879 887
880 888
881
882
883/* 889/*
884 * reset all settings to their default value 890 * reset all settings to their default value
885 */ 891 */
diff --git a/apps/settings.h b/apps/settings.h
index 987709ce72..c4cb917c1f 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -748,6 +748,10 @@ struct user_settings
748 int list_accel_start_delay; /* ms before we start increaseing step size */ 748 int list_accel_start_delay; /* ms before we start increaseing step size */
749 int list_accel_wait; /* ms between increases */ 749 int list_accel_wait; /* ms between increases */
750#endif 750#endif
751#ifdef HAVE_USBSTACK
752 int usb_stack_mode; /* device or host */
753 unsigned char usb_stack_device_driver[32]; /* usb device driver to load */
754#endif
751}; 755};
752 756
753/** global variables **/ 757/** global variables **/
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 16c3222b5e..1218dbf3e4 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -47,6 +47,9 @@
47#include "radio.h" 47#include "radio.h"
48#endif 48#endif
49 49
50#ifdef HAVE_USBSTACK
51#include "usbstack.h"
52#endif
50 53
51#define NVRAM(bytes) (bytes<<F_NVRAM_MASK_SHIFT) 54#define NVRAM(bytes) (bytes<<F_NVRAM_MASK_SHIFT)
52/** NOTE: NVRAM_CONFIG_VERSION is in settings_list.h 55/** NOTE: NVRAM_CONFIG_VERSION is in settings_list.h
@@ -1260,6 +1263,14 @@ const struct settings_list settings[] = {
1260 3, "list_accel_wait", UNIT_SEC, 1, 10, 1, 1263 3, "list_accel_wait", UNIT_SEC, 1, 10, 1,
1261 scanaccel_formatter, scanaccel_getlang, NULL), 1264 scanaccel_formatter, scanaccel_getlang, NULL),
1262#endif /* HAVE_SCROLLWHEEL */ 1265#endif /* HAVE_SCROLLWHEEL */
1266#ifdef HAVE_USBSTACK
1267 CHOICE_SETTING(0, usb_stack_mode, LANG_USBSTACK_MODE, 0, "usb mode",
1268 "device,host",
1269 usb_controller_select,
1270 2, ID2P(LANG_USBSTACK_DEVICE), ID2P(LANG_USBSTACK_HOST)),
1271 FILENAME_SETTING(0, usb_stack_device_driver, "usb device driver",
1272 "storage", NULL, NULL, 32),
1273#endif /* HAVE_USBSTACK */
1263}; 1274};
1264 1275
1265const int nb_settings = sizeof(settings)/sizeof(*settings); 1276const int nb_settings = sizeof(settings)/sizeof(*settings);
diff --git a/firmware/SOURCES b/firmware/SOURCES
index cd628fb683..c704bee0e7 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -101,6 +101,7 @@ drivers/dac.c
101drivers/serial.c 101drivers/serial.c
102#endif /* SIMULATOR */ 102#endif /* SIMULATOR */
103 103
104
104/* Storage */ 105/* Storage */
105#ifndef SIMULATOR 106#ifndef SIMULATOR
106#ifdef HAVE_MMC 107#ifdef HAVE_MMC
@@ -221,6 +222,18 @@ drivers/audio/mas35xx.c
221#endif /* defined(HAVE_*) */ 222#endif /* defined(HAVE_*) */
222#endif /* SIMULATOR */ 223#endif /* SIMULATOR */
223 224
225/* USB Stack */
226#if !defined(SIMULATOR)
227#ifdef HAVE_USBSTACK
228usbstack/core/core.c
229usbstack/core/epsetup.c
230usbstack/core/utils.c
231usbstack/core/config.c
232usbstack/drivers/device/usb_serial.c
233usbstack/drivers/device/usb_storage.c
234#endif
235#endif
236
224/* USBOTG */ 237/* USBOTG */
225#if !defined(SIMULATOR) 238#if !defined(SIMULATOR)
226#if CONFIG_USBOTG == USBOTG_ISP1362 239#if CONFIG_USBOTG == USBOTG_ISP1362
@@ -230,7 +243,7 @@ drivers/isp1362.c
230#if CONFIG_USBOTG == USBOTG_M5636 243#if CONFIG_USBOTG == USBOTG_M5636
231drivers/m5636.c 244drivers/m5636.c
232#elif CONFIG_USBOTG == USBOTG_ARC 245#elif CONFIG_USBOTG == USBOTG_ARC
233drivers/arcotg_udc.c 246drivers/usb/arcotg_dcd.c
234#endif /* CONFIG_USBOTG */ 247#endif /* CONFIG_USBOTG */
235#endif /* !defined(BOOTLOADER) */ 248#endif /* !defined(BOOTLOADER) */
236#endif /* !defined(SIMULATOR) */ 249#endif /* !defined(SIMULATOR) */
diff --git a/firmware/drivers/usb/arcotg_dcd.c b/firmware/drivers/usb/arcotg_dcd.c
new file mode 100644
index 0000000000..982fdfb9eb
--- /dev/null
+++ b/firmware/drivers/usb/arcotg_dcd.c
@@ -0,0 +1,983 @@
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 code from the Linux Target Image Builder from Freescale
13 * available at http://www.bitshrine.org/ and
14 * http://www.bitshrine.org/gpp/linux-2.6.16-mx31-usb-2.patch
15 * Adapted for Rockbox in January 2007
16 * Original file: drivers/usb/gadget/arcotg_udc.c
17 *
18 * USB Device Controller Driver
19 * Driver for ARC OTG USB module in the i.MX31 platform, etc.
20 *
21 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
22 *
23 * Based on mpc-udc.h
24 * Author: Li Yang (leoli@freescale.com)
25 * Jiang Bo (Tanya.jiang@freescale.com)
26 *
27 * All files in this archive are subject to the GNU General Public License.
28 * See the file COPYING in the source tree root for full license agreement.
29 *
30 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
31 * KIND, either express or implied.
32 *
33 ****************************************************************************/
34
35#include <string.h>
36#include "arcotg_dcd.h"
37
38/*-------------------------------------------------------------------------*/
39
40static struct arcotg_dcd dcd_controller;
41struct usb_response res;
42
43/* datastructes to controll transfers */
44struct dtd dev_td[USB_MAX_PIPES] IBSS_ATTR;
45struct dqh dev_qh[USB_MAX_PIPES] __attribute((aligned (1 << 11))) IBSS_ATTR;
46
47/* shared memory used by rockbox and dcd to exchange data */
48#define BUFFER_SIZE 512
49unsigned char buffer[BUFFER_SIZE] IBSS_ATTR;
50
51/*-------------------------------------------------------------------------*/
52
53/* description of our device driver operations */
54struct usb_dcd_controller_ops arotg_dcd_ops = {
55 .enable = usb_arcotg_dcd_enable,
56 .disable = NULL,
57 .set_halt = usb_arcotg_dcd_set_halt,
58 .send = usb_arcotg_dcd_send,
59 .receive = usb_arcotg_dcd_receive,
60 .ep0 = &dcd_controller.endpoints[0],
61};
62
63/* description of our usb controller driver */
64struct usb_controller arcotg_dcd = {
65 .name = "arcotg_dcd",
66 .type = DEVICE,
67 .speed = USB_SPEED_UNKNOWN,
68 .init = usb_arcotg_dcd_init,
69 .shutdown = usb_arcotg_dcd_shutdown,
70 .irq = usb_arcotg_dcd_irq,
71 .start = usb_arcotg_dcd_start,
72 .stop = usb_arcotg_dcd_stop,
73 .controller_ops = (void*)&arotg_dcd_ops,
74};
75
76static struct usb_response response;
77
78/*-------------------------------------------------------------------------*/
79
80/* TODO hmmm */
81
82struct timer {
83 unsigned long s;
84 unsigned long e;
85};
86
87void
88timer_set(struct timer * timer, unsigned long val)
89{
90 timer->s = USEC_TIMER;
91 timer->e = timer->s + val + 1;
92}
93
94int
95timer_expired(struct timer * timer)
96{
97 unsigned long val = USEC_TIMER;
98
99 if (timer->e > timer->s) {
100 return !(val >= timer->s && val <= timer->e);
101 } else {
102 return (val > timer->e && val < timer->s);
103 }
104}
105
106#define MAX_PACKET_SIZE USB_MAX_CTRL_PAYLOAD
107
108#define ERROR_TIMEOUT (-3)
109#define ERROR_UNKNOWN (-7)
110
111#define PRIME_TIMER 100000
112#define TRANSFER_TIMER 1000000
113#define RESET_TIMER 5000000
114#define SETUP_TIMER 200000
115
116/*-------------------------------------------------------------------------*/
117
118/* gets called by usb_stack_init() to register
119 * this arcotg device conrtollder driver in the
120 * stack. */
121void usb_dcd_init(void) {
122 usb_controller_register(&arcotg_dcd);
123}
124
125/*-------------------------------------------------------------------------*/
126
127void usb_arcotg_dcd_init(void) {
128
129 struct timer t;
130 int i, ep_num = 0;
131
132 logf("arcotg_dcd: init");
133 memset(&dcd_controller, 0, sizeof(struct arcotg_dcd));
134
135 /* setup list of aviable endpoints */
136 INIT_LIST_HEAD(&arcotg_dcd.endpoints.list);
137
138 for (i = 0; i < USB_MAX_PIPES; i++) {
139
140 dcd_controller.endpoints[i].pipe_num = i;
141
142 if (i % 2 == 0) {
143 dcd_controller.endpoints[i].ep_num = ep_num;
144 } else {
145 dcd_controller.endpoints[i].ep_num = ep_num;
146 ep_num++;
147 }
148
149 logf("pipe %d -> ep %d %s", dcd_controller.endpoints[i].pipe_num, dcd_controller.endpoints[i].ep_num, dcd_controller.endpoints[i].name);
150
151 if (ep_name[i] != NULL) {
152 memcpy(&dcd_controller.endpoints[i].name, ep_name[i], sizeof(dcd_controller.endpoints[i].name));
153
154 if (i != 0) {
155 /* add to list of configurable endpoints */
156 list_add_tail(&dcd_controller.endpoints[i].list, &arcotg_dcd.endpoints.list);
157 }
158 }
159 }
160
161 /* ep0 is special */
162 arcotg_dcd.ep0 = &dcd_controller.endpoints[0];
163 arcotg_dcd.ep0->maxpacket = USB_MAX_CTRL_PAYLOAD;
164
165 /* stop */
166 UDC_USBCMD &= ~USB_CMD_RUN;
167
168 udelay(50000);
169 timer_set(&t, RESET_TIMER);
170
171 /* reset */
172 UDC_USBCMD |= USB_CMD_CTRL_RESET;
173
174 while ((UDC_USBCMD & USB_CMD_CTRL_RESET)) {
175 if (timer_expired(&t)) {
176 logf("TIMEOUT->init");
177 }
178 }
179
180 /* put controller in device mode */
181 UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
182
183 /* init queue heads */
184 qh_init(0, USB_RECV, USB_ENDPOINT_XFER_CONTROL, USB_MAX_CTRL_PAYLOAD, 0, 0);
185 qh_init(0, USB_SEND, USB_ENDPOINT_XFER_CONTROL, USB_MAX_CTRL_PAYLOAD, 0, 0);
186
187 UDC_ENDPOINTLISTADDR = (unsigned int)dev_qh;
188}
189
190void usb_arcotg_dcd_shutdown(void) {
191
192}
193
194void usb_arcotg_dcd_start(void) {
195
196 logf("start");
197
198 if (arcotg_dcd.device_driver != NULL) {
199 logf("YEEEEEEESSSSSSS");
200 } else {
201 logf("NOOOOOO");
202 }
203
204 /* clear stopped bit */
205 dcd_controller.stopped = false;
206
207 UDC_USBCMD |= USB_CMD_RUN;
208}
209
210void usb_arcotg_dcd_stop(void) {
211
212 logf("stop");
213
214 /* set stopped bit */
215 dcd_controller.stopped = true;
216
217 UDC_USBCMD &= ~USB_CMD_RUN;
218}
219
220void usb_arcotg_dcd_irq(void) {
221
222 int i;
223
224 if (dcd_controller.stopped == true) {
225 return;
226 }
227
228 /* check if we need to wake up from suspend */
229 if (!(UDC_USBSTS & USB_STS_SUSPEND) && dcd_controller.resume_state) {
230 resume_int();
231 }
232
233 /* USB Interrupt */
234 if (UDC_USBSTS & USB_STS_INT) {
235
236 /* setup packet, we only support ep0 as control ep */
237 if (UDC_ENDPTSETUPSTAT & EP_SETUP_STATUS_EP0) {
238 /* copy data from queue head to local buffer */
239 memcpy(&dcd_controller.local_setup_buff, (uint8_t *) &dev_qh[0].setup_buffer, 8);
240 /* ack setup packet*/
241 UDC_ENDPTSETUPSTAT = UDC_ENDPTSETUPSTAT;
242 setup_received_int(&dcd_controller.local_setup_buff);
243 }
244
245 if (UDC_ENDPTCOMPLETE) {
246 UDC_ENDPTCOMPLETE = UDC_ENDPTCOMPLETE;
247 }
248 }
249
250 if (UDC_USBSTS & USB_STS_PORT_CHANGE) {
251 port_change_int();
252 }
253
254 if (UDC_USBSTS & USB_STS_SUSPEND) {
255 suspend_int();
256 }
257
258 if (UDC_USBSTS & USB_STS_RESET) {
259 reset_int();
260 }
261
262 if (UDC_USBSTS & USB_STS_ERR) {
263 logf("!!! error !!!");
264 }
265
266 if (UDC_USBSTS & USB_STS_SYS_ERR) {
267 logf("!!! sys error !!!");
268 }
269}
270
271/*-------------------------------------------------------------------------*/
272/* interrupt handlers */
273
274static void setup_received_int(struct usb_ctrlrequest* request) {
275
276 int error = 0;
277 uint8_t address = 0;
278 int handled = 0; /* set to zero if we do not handle the message, */
279 /* and should pass it to the driver */
280
281 logf("setup_int");
282 into_usb_ctrlrequest(request);
283
284 /* handle all requests we support */
285 switch (request->bRequestType & USB_TYPE_MASK) {
286 case USB_TYPE_STANDARD:
287
288 switch (request->bRequest) {
289 case USB_REQ_SET_ADDRESS:
290
291 /* store address as we need to ack before setting it */
292 address = (uint8_t)request->wValue;
293
294 handled = 1;
295 break;
296
297 case USB_REQ_GET_STATUS:
298
299 logf("sending status..");
300 response.buf = &dcd_controller.usb_state;
301 response.length = 2;
302
303 handled = usb_arcotg_dcd_send(NULL, &response);
304 break;
305 }
306
307 case USB_REQ_CLEAR_FEATURE:
308 case USB_REQ_SET_FEATURE:
309 /* we only support set/clear feature for endpoint */
310 if (request->bRequestType == USB_RECIP_ENDPOINT) {
311 int dir = (request->wIndex & 0x0080) ? EP_DIR_IN : EP_DIR_OUT;
312 int num = (request->wIndex & 0x000f);
313 struct usb_ep *ep;
314
315 if (request->wValue != 0 || request->wLength != 0 || (num * 2 + dir) > USB_MAX_PIPES) {
316 break;
317 }
318 ep = &dcd_controller.endpoints[num * 2 + dir];
319
320 if (request->bRequest == USB_REQ_SET_FEATURE) {
321 logf("SET_FEATURE doing set_halt");
322 handled = usb_arcotg_dcd_set_halt(ep, 1);
323 } else {
324 logf("CLEAR_FEATURE doing clear_halt");
325 handled = usb_arcotg_dcd_set_halt(ep, 0);
326 }
327
328 if (handled == 0) {
329 handled = 1; /* dont pass it to driver */
330 }
331 }
332#if 0
333 if (rc == 0) {
334 /* send status only if _arcotg_ep_set_halt success */
335 if (ep0_prime_status(udc, EP_DIR_IN))
336 Ep0Stall(udc);
337 }
338#endif
339 break;
340 }
341
342 /* if dcd can not handle reqeust, ask driver */
343 if (handled == 0) {
344 if (arcotg_dcd.device_driver != NULL && arcotg_dcd.device_driver->request != NULL) {
345 handled = arcotg_dcd.device_driver->request(request);
346 logf("result from driver %d", handled);
347 }
348 }
349
350 if (handled <= 0) {
351 error = handled;
352 }
353
354 /* ack transfer */
355 usb_ack(request, error);
356
357 if (address != 0) {
358 logf("setting address to %d", address);
359 UDC_DEVICEADDR = address << 25;
360 }
361}
362
363static void port_change_int(void) {
364
365 //logf("port_change_int");
366 uint32_t tmp;
367 enum usb_device_speed speed = USB_SPEED_UNKNOWN;
368
369 /* bus resetting is finished */
370 if (!(UDC_PORTSC1 & PORTSCX_PORT_RESET)) {
371 /* Get the speed */
372 tmp = (UDC_PORTSC1 & PORTSCX_PORT_SPEED_MASK);
373 switch (tmp) {
374 case PORTSCX_PORT_SPEED_HIGH:
375 speed = USB_SPEED_HIGH;
376 break;
377 case PORTSCX_PORT_SPEED_FULL:
378 speed = USB_SPEED_FULL;
379 break;
380 case PORTSCX_PORT_SPEED_LOW:
381 speed = USB_SPEED_LOW;
382 break;
383 default:
384 speed = USB_SPEED_UNKNOWN;
385 break;
386 }
387 }
388
389 /* update speed */
390 arcotg_dcd.speed = speed;
391
392 /* update USB state */
393 if (!dcd_controller.resume_state) {
394 dcd_controller.usb_state = USB_STATE_DEFAULT;
395 }
396
397 /* inform device driver */
398 if (arcotg_dcd.device_driver != NULL && arcotg_dcd.device_driver->speed != NULL) {
399 arcotg_dcd.device_driver->speed(speed);
400 }
401}
402
403static void suspend_int(void) {
404
405 //logf("suspend_int");
406 dcd_controller.resume_state = dcd_controller.usb_state;
407 dcd_controller.usb_state = USB_STATE_SUSPENDED;
408
409 /* report suspend to the driver */
410 if (arcotg_dcd.device_driver != NULL && arcotg_dcd.device_driver->suspend != NULL) {
411 arcotg_dcd.device_driver->suspend();
412 }
413}
414
415static void resume_int(void) {
416
417 //logf("resume_int");
418 dcd_controller.usb_state = dcd_controller.resume_state;
419 dcd_controller.resume_state = USB_STATE_NOTATTACHED;
420
421 /* report resume to the driver */
422 if (arcotg_dcd.device_driver != NULL && arcotg_dcd.device_driver->resume != NULL) {
423 arcotg_dcd.device_driver->resume();
424 }
425}
426
427static void reset_int(void) {
428
429 //logf("reset_int");
430 struct timer t;
431
432 timer_set(&t, RESET_TIMER);
433
434 UDC_ENDPTSETUPSTAT = UDC_ENDPTSETUPSTAT;
435 UDC_ENDPTCOMPLETE = UDC_ENDPTCOMPLETE;
436
437 while (UDC_ENDPTPRIME) { /* prime and flush pending transfers */
438 if (timer_expired(&t)) {
439 logf("TIMEOUT->p&f");
440 }
441 }
442
443 UDC_ENDPTFLUSH = ~0;
444
445 if ((UDC_PORTSC1 & (1 << 8)) == 0) {
446 logf("TIMEOUT->port");
447 }
448
449 UDC_USBSTS = (1 << 6);
450
451 while ((UDC_USBSTS & (1 << 2)) == 0) { /* wait for port change */
452 if (timer_expired(&t)) {
453 logf("TIMEOUT->portchange");
454 }
455 }
456
457 UDC_USBSTS = (1 << 2);
458}
459
460
461/*-------------------------------------------------------------------------*/
462/* usb controller ops */
463
464int usb_arcotg_dcd_enable(struct usb_ep* ep) {
465
466 unsigned short max = 0;
467 unsigned char mult = 0, zlt = 0;
468 int retval = 0;
469 char *val = NULL; /* for debug */
470
471 /* catch bogus parameter */
472 if (!ep) {
473 return -EINVAL;
474 }
475
476 logf("ahhh %d", ep->desc->wMaxPacketSize);
477 max = ep->desc->wMaxPacketSize;
478 retval = -EINVAL;
479
480 /* check the max package size validate for this endpoint */
481 /* Refer to USB2.0 spec table 9-13,
482 */
483 switch (ep->desc->bmAttributes & 0x03) {
484 case USB_ENDPOINT_XFER_BULK:
485 zlt = 1;
486 break;
487
488 case USB_ENDPOINT_XFER_INT:
489 zlt = 1;
490 break;
491
492 case USB_ENDPOINT_XFER_ISOC:
493 break;
494
495 case USB_ENDPOINT_XFER_CONTROL:
496 break;
497 }
498
499#if 0
500 switch (ep->desc->bmAttributes & 0x03) {
501 case USB_ENDPOINT_XFER_BULK:
502 if (strstr(ep->ep.name, "-iso") || strstr(ep->ep.name, "-int")) {
503 goto en_done;
504 }
505 mult = 0;
506 zlt = 1;
507
508 switch (arcotg_dcd.speed) {
509 case USB_SPEED_HIGH:
510 if ((max == 128) || (max == 256) || (max == 512)) {
511 break;
512 }
513 default:
514 switch (max) {
515 case 4:
516 case 8:
517 case 16:
518 case 32:
519 case 64:
520 break;
521 default:
522 + case USB_SPEED_LOW:
523 + goto en_done;
524 + }
525 + }
526 + break;
527 + case USB_ENDPOINT_XFER_INT:
528 + if (strstr(ep->ep.name, "-iso")) /* bulk is ok */
529 + goto en_done;
530 + mult = 0;
531 + zlt = 1;
532 + switch (udc->gadget.speed) {
533 + case USB_SPEED_HIGH:
534 + if (max <= 1024)
535 + break;
536 + case USB_SPEED_FULL:
537 + if (max <= 64)
538 + break;
539 + default:
540 + if (max <= 8)
541 + break;
542 + goto en_done;
543 + }
544 + break;
545 + case USB_ENDPOINT_XFER_ISOC:
546 + if (strstr(ep->ep.name, "-bulk") || strstr(ep->ep.name, "-int"))
547 + goto en_done;
548 + mult = (unsigned char)
549 + (1 + ((le16_to_cpu(desc->wMaxPacketSize) >> 11) & 0x03));
550 + zlt = 0;
551 + switch (udc->gadget.speed) {
552 + case USB_SPEED_HIGH:
553 + if (max <= 1024)
554 + break;
555 + case USB_SPEED_FULL:
556 + if (max <= 1023)
557 + break;
558 + default:
559 + goto en_done;
560 + }
561 + break;
562 + case USB_ENDPOINT_XFER_CONTROL:
563 + if (strstr(ep->ep.name, "-iso") || strstr(ep->ep.name, "-int"))
564 + goto en_done;
565 + mult = 0;
566 + zlt = 1;
567 + switch (udc->gadget.speed) {
568 + case USB_SPEED_HIGH:
569 + case USB_SPEED_FULL:
570 + switch (max) {
571 + case 1:
572 + case 2:
573 + case 4:
574 + case 8:
575 + case 16:
576 + case 32:
577 + case 64:
578 + break;
579 + default:
580 + goto en_done;
581 + }
582 + case USB_SPEED_LOW:
583 + switch (max) {
584 + case 1:
585 + case 2:
586 + case 4:
587 + case 8:
588 + break;
589 + default:
590 + goto en_done;
591 + }
592 + default:
593 + goto en_done;
594 + }
595 + break;
596 +
597 + default:
598 + goto en_done;
599 + }
600#endif
601
602 /* here initialize variable of ep */
603 ep->maxpacket = max;
604
605 /* hardware special operation */
606
607 /* Init EPx Queue Head (Ep Capabilites field in QH
608 * according to max, zlt, mult) */
609 qh_init(ep->ep_num,
610 (ep->desc->bEndpointAddress & USB_DIR_IN) ? USB_RECV : USB_SEND,
611 (unsigned char) (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK),
612 max, zlt, mult);
613
614 /* Init endpoint x at here */
615 ep_setup(ep->ep_num,
616 (unsigned char)((ep->desc->bEndpointAddress & USB_DIR_IN) ? USB_RECV : USB_SEND),
617 (unsigned char)(ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
618
619 /* Now HW will be NAKing transfers to that EP,
620 * until a buffer is queued to it. */
621
622 retval = 0;
623 switch (ep->desc->bmAttributes & 0x03) {
624 case USB_ENDPOINT_XFER_BULK:
625 val = "bulk";
626 break;
627 case USB_ENDPOINT_XFER_ISOC:
628 val = "iso";
629 break;
630 case USB_ENDPOINT_XFER_INT:
631 val = "intr";
632 break;
633 default:
634 val = "ctrl";
635 break;
636 }
637
638 logf("ep num %d", (int)ep->ep_num);
639
640 logf("enabled %s (ep%d%s-%s)", ep->name,
641 ep->desc->bEndpointAddress & 0x0f,
642 (ep->desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", val);
643 logf(" maxpacket %d", max);
644
645 return retval;
646}
647
648int usb_arcotg_dcd_set_halt(struct usb_ep* ep, bool halt) {
649
650 int status = -EOPNOTSUPP; /* operation not supported */
651 unsigned char dir = 0;
652 unsigned int tmp_epctrl = 0;
653
654 if (!ep) {
655 status = -EINVAL;
656 goto out;
657 }
658
659 if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
660 status = -EOPNOTSUPP;
661 goto out;
662 }
663
664 status = 0;
665 dir = ep_is_in(ep) ? USB_SEND : USB_RECV;
666
667 tmp_epctrl = UDC_ENDPTCTRL(ep->ep_num);
668
669 if (halt) {
670 /* set the stall bit */
671 if (dir) {
672 tmp_epctrl |= EPCTRL_TX_EP_STALL;
673 } else {
674 tmp_epctrl |= EPCTRL_RX_EP_STALL;
675 }
676 } else {
677 /* clear the stall bit and reset data toggle */
678 if (dir) {
679 tmp_epctrl &= ~EPCTRL_TX_EP_STALL;
680 tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
681 } else {
682 tmp_epctrl &= ~EPCTRL_RX_EP_STALL;
683 tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
684 }
685 }
686 UDC_ENDPTCTRL(ep->ep_num) = tmp_epctrl;
687
688out:
689 logf(" %s %s halt rc=%d", ep->name, halt ? "set" : "clear", status);
690 return status;
691}
692
693int usb_arcotg_dcd_send(struct usb_ep* ep, struct usb_response* res) {
694
695 char* ptr;
696 int todo, error, size, done = 0;
697 int index = 1; /* use as default ep0 tx qh and td */
698 struct dtd* td;
699 struct dqh* qh;
700 unsigned int mask;
701
702 if (res == NULL) {
703 logf("invalid input");
704 return -EINVAL;
705 }
706
707 if (ep != NULL) {
708 index = ep->pipe_num;
709 }
710
711 logf("buff: %x", res->buf);
712 logf("len: %d", res->length);
713
714 ptr = res->buf;
715 size = res->length;
716
717 td = &dev_td[index];
718 qh = &dev_qh[index];
719 mask = 1 << (15 + index);
720 logf("sending mask: %x", mask);
721
722 do {
723 /* calculate how much to copy and send */
724 todo = MIN(size, BUFFER_SIZE);
725
726 /* copy data to shared memory area */
727 memcpy(buffer, ptr, todo);
728
729 /* init transfer descriptor */
730 td_init(td, buffer, todo);
731
732 /* start transfer*/
733 error = td_enqueue(td, qh, mask);
734
735 if (error == 0) {
736 /* waiting for finished transfer */
737 error = td_wait(td, mask);
738 }
739
740 if (error) {
741 done = error;
742 break;
743 }
744
745 size -= todo;
746 ptr += todo;
747 done += todo;
748
749 } while (size > 0);
750
751 logf("usb_send done %d",done);
752 return done;
753}
754
755int usb_arcotg_dcd_receive(struct usb_ep* ep, struct usb_response* res) {
756
757 char* ptr;
758 int todo, error, size, done = 0;
759 int index = 0; /* use as default ep0 rx qh and td */
760 struct dtd* td;
761 struct dqh* qh;
762 unsigned int mask;
763
764 if (res == NULL) {
765 logf("invalid input");
766 return -EINVAL;
767 }
768
769 if (ep != NULL) {
770 index = ep->pipe_num;
771 }
772
773 ptr = res->buf;
774 size = res->length;
775
776 td = &dev_td[index];
777 qh = &dev_qh[index];
778 mask = 1 << index;
779
780 do {
781 /* calculate how much to receive in one step */
782 todo = MIN(size, BUFFER_SIZE);
783
784 /* init transfer descritpor */
785 td_init(td, buffer, size);
786
787 /* start transfer */
788 error = td_enqueue(td, qh, mask);
789
790 if (error == 0) {
791 /* wait until transfer is finished */
792 error = td_wait(td, mask);
793 }
794
795 if (error) {
796 done = error;
797 break;
798 }
799
800 /* copy receive data to buffer */
801 memcpy(ptr, buffer, todo);
802
803 size -= todo;
804 ptr += todo;
805 done += todo;
806
807 } while (size > 0);
808
809 logf("usb_recive done %d",done);
810 return done;
811}
812
813/*-------------------------------------------------------------------------*/
814/* lifecylce */
815
816static void qh_init(unsigned char ep_num, unsigned char dir, unsigned char ep_type,
817 unsigned int max_pkt_len, unsigned int zlt, unsigned char mult) {
818
819 struct dqh *qh = &dev_qh[2 * ep_num + dir];
820 uint32_t tmp = 0;
821 memset(qh, 0, sizeof(struct dqh));
822
823 /* set the Endpoint Capabilites Reg of QH */
824 switch (ep_type) {
825 case USB_ENDPOINT_XFER_CONTROL:
826 /* Interrupt On Setup (IOS). for control ep */
827 tmp = (max_pkt_len << LENGTH_BIT_POS) | INTERRUPT_ON_COMPLETE;
828 break;
829 case USB_ENDPOINT_XFER_ISOC:
830 tmp = (max_pkt_len << LENGTH_BIT_POS) | (mult << EP_QUEUE_HEAD_MULT_POS);
831 break;
832 case USB_ENDPOINT_XFER_BULK:
833 case USB_ENDPOINT_XFER_INT:
834 tmp = max_pkt_len << LENGTH_BIT_POS;
835 if (zlt) {
836 tmp |= EP_QUEUE_HEAD_ZLT_SEL;
837 }
838 break;
839 default:
840 logf("error ep type is %d", ep_type);
841 return;
842 }
843
844 /* see 32.14.4.1 Queue Head Initialization */
845
846 /* write the wMaxPacketSize field as required by the USB Chapter9 or application specific portocol */
847 qh->endpt_cap = tmp;
848
849 /* write the next dTD Terminate bit fild to 1 */
850 qh->dtd_ovrl.next_dtd = 1;
851
852 /* write the Active bit in the status field to 0 */
853 qh->dtd_ovrl.dtd_token &= ~STATUS_ACTIVE;
854
855 /* write the Hald bit in the status field to 0 */
856 qh->dtd_ovrl.dtd_token &= ~STATUS_HALTED;
857
858 logf("qh: init %d", (2 * ep_num + dir));
859}
860
861static void td_init(struct dtd* td, void* buffer, uint32_t todo) {
862
863 /* see 32.14.5.2 Building a Transfer Descriptor */
864
865 /* init first 7 dwords with 0 */
866 memset(td, 0, sizeof(struct dtd)); /* set set all to 0 */
867
868 /* set terminate bit to 1*/
869 td->next_dtd = 1;
870
871 /* fill in total bytes with transfer size */
872 td->dtd_token = (todo << 16);
873
874 /* set interrupt on compilte if desierd */
875 td->dtd_token |= INTERRUPT_ON_COMPLETE;
876
877 /* initialize the status field with the active bit set to 1 and all remaining status bits to 0 */
878 td->dtd_token |= STATUS_ACTIVE;
879
880 td->buf_ptr0 = (uint32_t)buffer;
881}
882
883static void ep_setup(unsigned char ep_num, unsigned char dir, unsigned char ep_type) {
884
885 unsigned int tmp_epctrl = 0;
886 struct timer t;
887
888 tmp_epctrl = UDC_ENDPTCTRL(ep_num);
889 if (dir) {
890 if (ep_num) {
891 tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
892 }
893 logf("tx enablde");
894 tmp_epctrl |= EPCTRL_TX_ENABLE;
895 tmp_epctrl |= ((unsigned int)(ep_type) << EPCTRL_TX_EP_TYPE_SHIFT);
896 } else {
897 if (ep_num) {
898 tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
899 }
900 logf("rx enablde");
901 tmp_epctrl |= EPCTRL_RX_ENABLE;
902 tmp_epctrl |= ((unsigned int)(ep_type) << EPCTRL_RX_EP_TYPE_SHIFT);
903 }
904
905 UDC_ENDPTCTRL(ep_num) = tmp_epctrl;
906
907 /* wait for the write reg to finish */
908
909 timer_set(&t, SETUP_TIMER);
910 while (!(UDC_ENDPTCTRL(ep_num) & (tmp_epctrl & (EPCTRL_TX_ENABLE | EPCTRL_RX_ENABLE)))) {
911 if (timer_expired(&t)) {
912 logf("TIMEOUT: enable ep");
913 return;
914 }
915 }
916}
917
918/*-------------------------------------------------------------------------*/
919/* helpers for sending/receiving */
920
921static int td_enqueue(struct dtd* td, struct dqh* qh, unsigned int mask) {
922
923 struct timer t;
924
925 qh->dtd_ovrl.next_dtd = (unsigned int)td;
926 qh->dtd_ovrl.dtd_token &= ~0xc0;
927
928 timer_set(&t, PRIME_TIMER);
929 UDC_ENDPTPRIME |= mask;
930
931 while ((UDC_ENDPTPRIME & mask)) {
932 if (timer_expired(&t)) {
933 logf("timeout->prime");
934 }
935 }
936
937 if ((UDC_ENDPTSTAT & mask) == 0) {
938 logf("Endptstat 0x%x", UDC_ENDPTSTAT);
939 logf("HW_ERROR");
940 }
941
942 return 0;
943}
944
945static int td_wait(struct dtd* td, unsigned int mask) {
946
947 struct timer t;
948 timer_set(&t, TRANSFER_TIMER);
949
950 for (;;) {
951 if ((UDC_ENDPTCOMPLETE & mask) != 0) {
952 UDC_ENDPTCOMPLETE |= mask;
953 }
954
955 if ((td->dtd_token & (1 << 7)) == 0) {
956 return 0;
957 }
958
959 if (timer_expired(&t)) {
960 return ERROR_TIMEOUT;
961 }
962 }
963}
964
965static int usb_ack(struct usb_ctrlrequest * s, int error) {
966
967 if (error) {
968 logf("STALLing ep0");
969 UDC_ENDPTCTRL0 |= 1 << 16; /* stall */
970 return 0;
971 }
972
973 res.buf = NULL;
974 res.length = 0;
975
976 if (s->bRequestType & 0x80) {
977 logf("ack in");
978 return usb_arcotg_dcd_receive(NULL, &res);
979 } else {
980 logf("ack out");
981 return usb_arcotg_dcd_send(NULL, &res);
982 }
983}
diff --git a/firmware/drivers/usb/arcotg_dcd.h b/firmware/drivers/usb/arcotg_dcd.h
new file mode 100644
index 0000000000..127ee43efa
--- /dev/null
+++ b/firmware/drivers/usb/arcotg_dcd.h
@@ -0,0 +1,173 @@
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 code from the Linux Target Image Builder from Freescale
13 * available at http://www.bitshrine.org/ and
14 * http://www.bitshrine.org/gpp/linux-2.6.16-mx31-usb-2.patch
15 * Adapted for Rockbox in January 2007
16 * Original file: drivers/usb/gadget/arcotg_udc.c
17 *
18 * USB Device Controller Driver
19 * Driver for ARC OTG USB module in the i.MX31 platform, etc.
20 *
21 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
22 *
23 * Based on mpc-udc.h
24 * Author: Li Yang (leoli@freescale.com)
25 * Jiang Bo (Tanya.jiang@freescale.com)
26 *
27 * All files in this archive are subject to the GNU General Public License.
28 * See the file COPYING in the source tree root for full license agreement.
29 *
30 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
31 * KIND, either express or implied.
32 *
33 ****************************************************************************/
34
35#ifndef _ARCOTG_DCD_H_
36#define _ARCOTG_DCD_H_
37
38#include "usbstack/core.h"
39#include "arcotg_udc.h"
40
41/*-------------------------------------------------------------------------*/
42
43#define ep_is_in(EP) (((EP)->desc->bEndpointAddress & USB_DIR_IN)==USB_DIR_IN)
44
45#define EP_DIR_IN 1
46#define EP_DIR_OUT 0
47
48/*-------------------------------------------------------------------------*/
49
50/* pipe direction macro from device view */
51#define USB_RECV (0) /* OUT EP */
52#define USB_SEND (1) /* IN EP */
53
54/* Shared Bit Masks for Endpoint Queue Head and Endpoint Transfer Descriptor */
55#define TERMINATE (1 << 0)
56#define STATUS_ACTIVE (1 << 7)
57#define STATUS_HALTED (1 << 6)
58#define STATUS_DATA_BUFF_ERR (1 << 5)
59#define STATUS_TRANSACTION_ERR (1 << 4)
60#define INTERRUPT_ON_COMPLETE (1 << 15)
61#define LENGTH_BIT_POS (16)
62#define ADDRESS_MASK (0xFFFFFFE0)
63#define ERROR_MASK (DTD_STATUS_HALTED | \
64 DTD_STATUS_DATA_BUFF_ERR | \
65 DTD_STATUS_TRANSACTION_ERR)
66
67#define RESERVED_FIELDS ((1 << 0) | (1 << 2) | (1 << 4) | \
68 (1 << 8) | (1 << 9) | (1 << 12)| \
69 (1 << 13)| (1 << 14)| (1 << 31))
70
71/* Endpoint Queue Head Bit Masks */
72#define EP_QUEUE_HEAD_MULT_POS (30)
73#define EP_QUEUE_HEAD_ZLT_SEL (0x20000000)
74#define EP_QUEUE_HEAD_MAX_PKT_LEN(ep_info) (((ep_info)>>16)&0x07ff)
75#define EP_QUEUE_HEAD_MULTO (0x00000C00)
76#define EP_QUEUE_CURRENT_OFFSET_MASK (0x00000FFF)
77#define EP_QUEUE_FRINDEX_MASK (0x000007FF)
78#define EP_MAX_LENGTH_TRANSFER (0x4000)
79
80/*-------------------------------------------------------------------------*/
81
82/* ep name is important, it should obey the convention of ep_match() */
83/* even numbered EPs are OUT or setup, odd are IN/INTERRUPT */
84static const char* ep_name[] = {
85 "ep0-control", NULL, /* everyone has ep0 */
86 /* 7 configurable endpoints */
87 "ep1out",
88 "ep1in",
89 "ep2out",
90 "ep2in",
91 "ep3out",
92 "ep3in",
93 "ep4out",
94 "ep4in",
95 "ep5out",
96 "ep5in",
97 "ep6out",
98 "ep6in",
99 "ep7out",
100 "ep7in"
101};
102
103/*-------------------------------------------------------------------------*/
104
105/* Endpoint Transfer Descriptor data struct */
106struct dtd {
107 uint32_t next_dtd; /* Next TD pointer(31-5), T(0) set indicate invalid */
108 uint32_t dtd_token; /* Total bytes (30-16), IOC (15), MultO(11-10), STS (7-0) */
109 uint32_t buf_ptr0; /* Buffer pointer Page 0 */
110 uint32_t buf_ptr1; /* Buffer pointer Page 1 */
111 uint32_t buf_ptr2; /* Buffer pointer Page 2 */
112 uint32_t buf_ptr3; /* Buffer pointer Page 3 */
113 uint32_t buf_ptr4; /* Buffer pointer Page 4 */
114 uint32_t res; /* make it an even 8 words */
115} __attribute((packed));
116
117/* Endpoint Queue Head*/
118struct dqh {
119 uint32_t endpt_cap; /* Mult(31-30) , Zlt(29) , Max Pkt len
120 * and IOS(15) */
121 uint32_t cur_dtd; /* Current dTD Pointer(31-5) */
122 struct dtd dtd_ovrl; /* Transfer descriptor */
123 uint32_t setup_buffer[2]; /* Setup data 8 bytes */
124 uint32_t res2[4]; /* pad out to 64 bytes */
125} __attribute((packed));
126
127#define RESPONSE_SIZE 30
128
129/* our controller struct */
130struct arcotg_dcd {
131 struct usb_ctrlrequest local_setup_buff;
132 struct usb_ep endpoints[USB_MAX_PIPES];
133 struct usb_response response[RESPONSE_SIZE];
134 enum usb_device_state usb_state;
135 enum usb_device_state resume_state;
136 bool stopped;
137};
138
139/*-------------------------------------------------------------------------*/
140
141/* usb_controller functions */
142void usb_arcotg_dcd_init(void);
143void usb_arcotg_dcd_shutdown(void);
144void usb_arcotg_dcd_irq(void);
145void usb_arcotg_dcd_start(void);
146void usb_arcotg_dcd_stop(void);
147
148/* usb controller ops */
149int usb_arcotg_dcd_enable(struct usb_ep* ep);
150int usb_arcotg_dcd_disable(struct usb_ep* ep);
151int usb_arcotg_dcd_set_halt(struct usb_ep* ep, bool halt);
152int usb_arcotg_dcd_send(struct usb_ep* ep, struct usb_response* request);
153int usb_arcotg_dcd_receive(struct usb_ep* ep, struct usb_response* res);
154
155/* interrupt handlers */
156static void setup_received_int(struct usb_ctrlrequest* request);
157static void port_change_int(void);
158static void reset_int(void);
159static void suspend_int(void);
160static void resume_int(void);
161
162/* life cycle */
163static void qh_init(unsigned char ep_num, unsigned char dir, unsigned char ep_type,
164 unsigned int max_pkt_len, unsigned int zlt, unsigned char mult);
165static void td_init(struct dtd* td, void* buffer, uint32_t todo);
166static void ep_setup(unsigned char ep_num, unsigned char dir, unsigned char ep_type);
167
168/* helpers for tx/rx */
169static int td_enqueue(struct dtd* td, struct dqh* qh, unsigned int mask);
170static int td_wait(struct dtd* td, unsigned int mask);
171static int usb_ack(struct usb_ctrlrequest * s, int error);
172
173#endif /*_ARCOTG_DCD_H_*/
diff --git a/firmware/export/arcotg_udc.h b/firmware/export/arcotg_udc.h
index e3bf93a52e..e016321b37 100644
--- a/firmware/export/arcotg_udc.h
+++ b/firmware/export/arcotg_udc.h
@@ -37,8 +37,6 @@
37 37
38#include "cpu.h" 38#include "cpu.h"
39 39
40#define ETIMEDOUT 1
41
42#define USB_MAX_ENDPOINTS 8 40#define USB_MAX_ENDPOINTS 8
43#define USB_MAX_PIPES (USB_MAX_ENDPOINTS*2) 41#define USB_MAX_PIPES (USB_MAX_ENDPOINTS*2)
44#define USB_MAX_CTRL_PAYLOAD 64 42#define USB_MAX_CTRL_PAYLOAD 64
@@ -99,7 +97,7 @@
99#define USB_FRINDEX_MASKS (0x3fff) 97#define USB_FRINDEX_MASKS (0x3fff)
100 98
101/* USB CMD Register Bit Masks */ 99/* USB CMD Register Bit Masks */
102#define USB_CMD_RUN_STOP (0x00000001) 100#define USB_CMD_RUN (0x00000001)
103#define USB_CMD_CTRL_RESET (0x00000002) 101#define USB_CMD_CTRL_RESET (0x00000002)
104#define USB_CMD_PERIODIC_SCHEDULE_EN (0x00000010) 102#define USB_CMD_PERIODIC_SCHEDULE_EN (0x00000010)
105#define USB_CMD_ASYNC_SCHEDULE_EN (0x00000020) 103#define USB_CMD_ASYNC_SCHEDULE_EN (0x00000020)
diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h
index 5a23b276eb..453faf5b33 100644
--- a/firmware/export/config-e200.h
+++ b/firmware/export/config-e200.h
@@ -148,6 +148,8 @@
148#define FIRMWARE_OFFSET_FILE_DATA 0x8 148#define FIRMWARE_OFFSET_FILE_DATA 0x8
149 149
150/* #define USB_IPODSTYLE */ 150/* #define USB_IPODSTYLE */
151#define HAVE_USBSTACK
152#define USBSTACK_CAPS CONTROLLER_DEVICE
151 153
152/* USB On-the-go */ 154/* USB On-the-go */
153#define CONFIG_USBOTG USBOTG_ARC 155#define CONFIG_USBOTG USBOTG_ARC
diff --git a/firmware/export/linkedlist.h b/firmware/export/linkedlist.h
new file mode 100644
index 0000000000..299c2f2c85
--- /dev/null
+++ b/firmware/export/linkedlist.h
@@ -0,0 +1,710 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: adc.h 13174 2007-04-15 23:35:56Z amiconn $
9 *
10 * Copyright (C) by Linux Kernel Developers
11 *
12 * Original source can be found in linux kernel: <kernel>/include/list.h
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef _LINKED_LIST_H_
23#define _LINKED_LIST_H_
24
25#include <stddef.h> /* used for offsetof */
26
27static inline void prefetch(const void *x) { (void)x; }
28
29/*
30 * Simple doubly linked list implementation.
31 *
32 * Some of the internal functions ("__xxx") are useful when
33 * manipulating whole lists rather than single entries, as
34 * sometimes we already know the next/prev entries and we can
35 * generate better code by using them directly rather than
36 * using the generic single-entry routines.
37 */
38
39/* TODO move this macro? */
40/* more about this macro: http://www.kroah.com/log/linux/container_of.html */
41#define container_of(ptr, type, member) ({ \
42 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
43 (type *)( (char *)__mptr - offsetof(type,member) );})
44
45/*
46 * These are non-NULL pointers that will result in page faults
47 * under normal circumstances, used to verify that nobody uses
48 * non-initialized list entries.
49 */
50#define LIST_POISON1 ((void *) 0x00100100)
51#define LIST_POISON2 ((void *) 0x00200200)
52
53struct list_head {
54 struct list_head *next, *prev;
55};
56
57#define LIST_HEAD_INIT(name) { &(name), &(name) }
58
59#define LIST_HEAD(name) \
60 struct list_head name = LIST_HEAD_INIT(name)
61
62static inline void INIT_LIST_HEAD(struct list_head *list)
63{
64 list->next = list;
65 list->prev = list;
66}
67
68/*
69 * Insert a new entry between two known consecutive entries.
70 *
71 * This is only for internal list manipulation where we know
72 * the prev/next entries already!
73 */
74static inline void __list_add(struct list_head *new,
75 struct list_head *prev,
76 struct list_head *next)
77{
78 next->prev = new;
79 new->next = next;
80 new->prev = prev;
81 prev->next = new;
82}
83
84
85/**
86 * list_add - add a new entry
87 * @new: new entry to be added
88 * @head: list head to add it after
89 *
90 * Insert a new entry after the specified head.
91 * This is good for implementing stacks.
92 */
93static inline void list_add(struct list_head *new, struct list_head *head)
94{
95 __list_add(new, head, head->next);
96}
97
98
99/**
100 * list_add_tail - add a new entry
101 * @new: new entry to be added
102 * @head: list head to add it before
103 *
104 * Insert a new entry before the specified head.
105 * This is useful for implementing queues.
106 */
107static inline void list_add_tail(struct list_head *new, struct list_head *head)
108{
109 __list_add(new, head->prev, head);
110}
111
112/*
113 * Delete a list entry by making the prev/next entries
114 * point to each other.
115 *
116 * This is only for internal list manipulation where we know
117 * the prev/next entries already!
118 */
119static inline void __list_del(struct list_head * prev, struct list_head * next)
120{
121 next->prev = prev;
122 prev->next = next;
123}
124
125/**
126 * list_del - deletes entry from list.
127 * @entry: the element to delete from the list.
128 * Note: list_empty() on entry does not return true after this, the entry is
129 * in an undefined state.
130 */
131static inline void list_del(struct list_head *entry)
132{
133 __list_del(entry->prev, entry->next);
134 entry->next = LIST_POISON1;
135 entry->prev = LIST_POISON2;
136}
137
138/**
139 * list_replace - replace old entry by new one
140 * @old : the element to be replaced
141 * @new : the new element to insert
142 *
143 * If @old was empty, it will be overwritten.
144 */
145static inline void list_replace(struct list_head *old,
146 struct list_head *new)
147{
148 new->next = old->next;
149 new->next->prev = new;
150 new->prev = old->prev;
151 new->prev->next = new;
152}
153
154static inline void list_replace_init(struct list_head *old,
155 struct list_head *new)
156{
157 list_replace(old, new);
158 INIT_LIST_HEAD(old);
159}
160
161/**
162 * list_del_init - deletes entry from list and reinitialize it.
163 * @entry: the element to delete from the list.
164 */
165static inline void list_del_init(struct list_head *entry)
166{
167 __list_del(entry->prev, entry->next);
168 INIT_LIST_HEAD(entry);
169}
170
171/**
172 * list_move - delete from one list and add as another's head
173 * @list: the entry to move
174 * @head: the head that will precede our entry
175 */
176static inline void list_move(struct list_head *list, struct list_head *head)
177{
178 __list_del(list->prev, list->next);
179 list_add(list, head);
180}
181
182/**
183 * list_move_tail - delete from one list and add as another's tail
184 * @list: the entry to move
185 * @head: the head that will follow our entry
186 */
187static inline void list_move_tail(struct list_head *list,
188 struct list_head *head)
189{
190 __list_del(list->prev, list->next);
191 list_add_tail(list, head);
192}
193
194/**
195 * list_is_last - tests whether @list is the last entry in list @head
196 * @list: the entry to test
197 * @head: the head of the list
198 */
199static inline int list_is_last(const struct list_head *list,
200 const struct list_head *head)
201{
202 return list->next == head;
203}
204
205/**
206 * list_empty - tests whether a list is empty
207 * @head: the list to test.
208 */
209static inline int list_empty(const struct list_head *head)
210{
211 return head->next == head;
212}
213
214static inline void __list_splice(struct list_head *list,
215 struct list_head *head)
216{
217 struct list_head *first = list->next;
218 struct list_head *last = list->prev;
219 struct list_head *at = head->next;
220
221 first->prev = head;
222 head->next = first;
223
224 last->next = at;
225 at->prev = last;
226}
227
228/**
229 * list_splice - join two lists
230 * @list: the new list to add.
231 * @head: the place to add it in the first list.
232 */
233static inline void list_splice(struct list_head *list, struct list_head *head)
234{
235 if (!list_empty(list)) {
236 __list_splice(list, head);
237 }
238}
239
240/**
241 * list_splice_init - join two lists and reinitialise the emptied list.
242 * @list: the new list to add.
243 * @head: the place to add it in the first list.
244 *
245 * The list at @list is reinitialised
246 */
247static inline void list_splice_init(struct list_head *list,
248 struct list_head *head)
249{
250 if (!list_empty(list)) {
251 __list_splice(list, head);
252 INIT_LIST_HEAD(list);
253 }
254}
255
256/**
257 * list_entry - get the struct for this entry
258 * @ptr: the &struct list_head pointer.
259 * @type: the type of the struct this is embedded in.
260 * @member: the name of the list_struct within the struct.
261 */
262#define list_entry(ptr, type, member) \
263 container_of(ptr, type, member)
264
265/**
266 * list_for_each - iterate over a list
267 * @pos: the &struct list_head to use as a loop cursor.
268 * @head: the head for your list.
269 */
270#define list_for_each(pos, head) \
271 for (pos = (head)->next; prefetch(pos->next), pos != (head); \
272 pos = pos->next)
273
274/**
275 * __list_for_each - iterate over a list
276 * @pos: the &struct list_head to use as a loop cursor.
277 * @head: the head for your list.
278 *
279 * This variant differs from list_for_each() in that it's the
280 * simplest possible list iteration code, no prefetching is done.
281 * Use this for code that knows the list to be very short (empty
282 * or 1 entry) most of the time.
283 */
284#define __list_for_each(pos, head) \
285 for (pos = (head)->next; pos != (head); pos = pos->next)
286
287/**
288 * list_for_each_prev - iterate over a list backwards
289 * @pos: the &struct list_head to use as a loop cursor.
290 * @head: the head for your list.
291 */
292#define list_for_each_prev(pos, head) \
293 for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
294 pos = pos->prev)
295
296/**
297 * list_for_each_entry - iterate over list of given type
298 * @pos: the type * to use as a loop cursor.
299 * @head: the head for your list.
300 * @member: the name of the list_struct within the struct.
301 */
302#define list_for_each_entry(pos, head, member) \
303 for (pos = list_entry((head)->next, typeof(*pos), member); \
304 prefetch(pos->member.next), &pos->member != (head); \
305 pos = list_entry(pos->member.next, typeof(*pos), member))
306
307/**
308 * list_for_each_entry_reverse - iterate backwards over list of given type.
309 * @pos: the type * to use as a loop cursor.
310 * @head: the head for your list.
311 * @member: the name of the list_struct within the struct.
312 */
313#define list_for_each_entry_reverse(pos, head, member) \
314 for (pos = list_entry((head)->prev, typeof(*pos), member); \
315 prefetch(pos->member.prev), &pos->member != (head); \
316 pos = list_entry(pos->member.prev, typeof(*pos), member))
317
318/**
319 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
320 * @pos: the type * to use as a start point
321 * @head: the head of the list
322 * @member: the name of the list_struct within the struct.
323 *
324 * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
325 */
326#define list_prepare_entry(pos, head, member) \
327 ((pos) ? : list_entry(head, typeof(*pos), member))
328
329/**
330 * list_for_each_entry_continue - continue iteration over list of given type
331 * @pos: the type * to use as a loop cursor.
332 * @head: the head for your list.
333 * @member: the name of the list_struct within the struct.
334 *
335 * Continue to iterate over list of given type, continuing after
336 * the current position.
337 */
338#define list_for_each_entry_continue(pos, head, member) \
339 for (pos = list_entry(pos->member.next, typeof(*pos), member); \
340 prefetch(pos->member.next), &pos->member != (head); \
341 pos = list_entry(pos->member.next, typeof(*pos), member))
342
343/**
344 * list_for_each_entry_from - iterate over list of given type from the current point
345 * @pos: the type * to use as a loop cursor.
346 * @head: the head for your list.
347 * @member: the name of the list_struct within the struct.
348 *
349 * Iterate over list of given type, continuing from current position.
350 */
351#define list_for_each_entry_from(pos, head, member) \
352 for (; prefetch(pos->member.next), &pos->member != (head); \
353 pos = list_entry(pos->member.next, typeof(*pos), member))
354
355#endif /*_LINKED_LIST_H_*/
356/***************************************************************************
357 * __________ __ ___.
358 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
359 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
360 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
361 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
362 * \/ \/ \/ \/ \/
363 * $Id: adc.h 13174 2007-04-15 23:35:56Z amiconn $
364 *
365 * Copyright (C) by Linux Kernel Developers
366 *
367 * Original source can be found in linux kernel: <kernel>/include/list.h
368 *
369 * All files in this archive are subject to the GNU General Public License.
370 * See the file COPYING in the source tree root for full license agreement.
371 *
372 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
373 * KIND, either express or implied.
374 *
375 ****************************************************************************/
376
377#ifndef _LINKED_LIST_H_
378#define _LINKED_LIST_H_
379
380#include <stddef.h> /* used for offsetof */
381
382static inline void prefetch(const void *x) { (void)x; }
383
384/*
385 * Simple doubly linked list implementation.
386 *
387 * Some of the internal functions ("__xxx") are useful when
388 * manipulating whole lists rather than single entries, as
389 * sometimes we already know the next/prev entries and we can
390 * generate better code by using them directly rather than
391 * using the generic single-entry routines.
392 */
393
394/* TODO move this macro? */
395/* more about this macro: http://www.kroah.com/log/linux/container_of.html */
396#define container_of(ptr, type, member) ({ \
397 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
398 (type *)( (char *)__mptr - offsetof(type,member) );})
399
400/*
401 * These are non-NULL pointers that will result in page faults
402 * under normal circumstances, used to verify that nobody uses
403 * non-initialized list entries.
404 */
405#define LIST_POISON1 ((void *) 0x00100100)
406#define LIST_POISON2 ((void *) 0x00200200)
407
408struct list_head {
409 struct list_head *next, *prev;
410};
411
412#define LIST_HEAD_INIT(name) { &(name), &(name) }
413
414#define LIST_HEAD(name) \
415 struct list_head name = LIST_HEAD_INIT(name)
416
417static inline void INIT_LIST_HEAD(struct list_head *list)
418{
419 list->next = list;
420 list->prev = list;
421}
422
423/*
424 * Insert a new entry between two known consecutive entries.
425 *
426 * This is only for internal list manipulation where we know
427 * the prev/next entries already!
428 */
429static inline void __list_add(struct list_head *new,
430 struct list_head *prev,
431 struct list_head *next)
432{
433 next->prev = new;
434 new->next = next;
435 new->prev = prev;
436 prev->next = new;
437}
438
439
440/**
441 * list_add - add a new entry
442 * @new: new entry to be added
443 * @head: list head to add it after
444 *
445 * Insert a new entry after the specified head.
446 * This is good for implementing stacks.
447 */
448static inline void list_add(struct list_head *new, struct list_head *head)
449{
450 __list_add(new, head, head->next);
451}
452
453
454/**
455 * list_add_tail - add a new entry
456 * @new: new entry to be added
457 * @head: list head to add it before
458 *
459 * Insert a new entry before the specified head.
460 * This is useful for implementing queues.
461 */
462static inline void list_add_tail(struct list_head *new, struct list_head *head)
463{
464 __list_add(new, head->prev, head);
465}
466
467/*
468 * Delete a list entry by making the prev/next entries
469 * point to each other.
470 *
471 * This is only for internal list manipulation where we know
472 * the prev/next entries already!
473 */
474static inline void __list_del(struct list_head * prev, struct list_head * next)
475{
476 next->prev = prev;
477 prev->next = next;
478}
479
480/**
481 * list_del - deletes entry from list.
482 * @entry: the element to delete from the list.
483 * Note: list_empty() on entry does not return true after this, the entry is
484 * in an undefined state.
485 */
486static inline void list_del(struct list_head *entry)
487{
488 __list_del(entry->prev, entry->next);
489 entry->next = LIST_POISON1;
490 entry->prev = LIST_POISON2;
491}
492
493/**
494 * list_replace - replace old entry by new one
495 * @old : the element to be replaced
496 * @new : the new element to insert
497 *
498 * If @old was empty, it will be overwritten.
499 */
500static inline void list_replace(struct list_head *old,
501 struct list_head *new)
502{
503 new->next = old->next;
504 new->next->prev = new;
505 new->prev = old->prev;
506 new->prev->next = new;
507}
508
509static inline void list_replace_init(struct list_head *old,
510 struct list_head *new)
511{
512 list_replace(old, new);
513 INIT_LIST_HEAD(old);
514}
515
516/**
517 * list_del_init - deletes entry from list and reinitialize it.
518 * @entry: the element to delete from the list.
519 */
520static inline void list_del_init(struct list_head *entry)
521{
522 __list_del(entry->prev, entry->next);
523 INIT_LIST_HEAD(entry);
524}
525
526/**
527 * list_move - delete from one list and add as another's head
528 * @list: the entry to move
529 * @head: the head that will precede our entry
530 */
531static inline void list_move(struct list_head *list, struct list_head *head)
532{
533 __list_del(list->prev, list->next);
534 list_add(list, head);
535}
536
537/**
538 * list_move_tail - delete from one list and add as another's tail
539 * @list: the entry to move
540 * @head: the head that will follow our entry
541 */
542static inline void list_move_tail(struct list_head *list,
543 struct list_head *head)
544{
545 __list_del(list->prev, list->next);
546 list_add_tail(list, head);
547}
548
549/**
550 * list_is_last - tests whether @list is the last entry in list @head
551 * @list: the entry to test
552 * @head: the head of the list
553 */
554static inline int list_is_last(const struct list_head *list,
555 const struct list_head *head)
556{
557 return list->next == head;
558}
559
560/**
561 * list_empty - tests whether a list is empty
562 * @head: the list to test.
563 */
564static inline int list_empty(const struct list_head *head)
565{
566 return head->next == head;
567}
568
569static inline void __list_splice(struct list_head *list,
570 struct list_head *head)
571{
572 struct list_head *first = list->next;
573 struct list_head *last = list->prev;
574 struct list_head *at = head->next;
575
576 first->prev = head;
577 head->next = first;
578
579 last->next = at;
580 at->prev = last;
581}
582
583/**
584 * list_splice - join two lists
585 * @list: the new list to add.
586 * @head: the place to add it in the first list.
587 */
588static inline void list_splice(struct list_head *list, struct list_head *head)
589{
590 if (!list_empty(list)) {
591 __list_splice(list, head);
592 }
593}
594
595/**
596 * list_splice_init - join two lists and reinitialise the emptied list.
597 * @list: the new list to add.
598 * @head: the place to add it in the first list.
599 *
600 * The list at @list is reinitialised
601 */
602static inline void list_splice_init(struct list_head *list,
603 struct list_head *head)
604{
605 if (!list_empty(list)) {
606 __list_splice(list, head);
607 INIT_LIST_HEAD(list);
608 }
609}
610
611/**
612 * list_entry - get the struct for this entry
613 * @ptr: the &struct list_head pointer.
614 * @type: the type of the struct this is embedded in.
615 * @member: the name of the list_struct within the struct.
616 */
617#define list_entry(ptr, type, member) \
618 container_of(ptr, type, member)
619
620/**
621 * list_for_each - iterate over a list
622 * @pos: the &struct list_head to use as a loop cursor.
623 * @head: the head for your list.
624 */
625#define list_for_each(pos, head) \
626 for (pos = (head)->next; prefetch(pos->next), pos != (head); \
627 pos = pos->next)
628
629/**
630 * __list_for_each - iterate over a list
631 * @pos: the &struct list_head to use as a loop cursor.
632 * @head: the head for your list.
633 *
634 * This variant differs from list_for_each() in that it's the
635 * simplest possible list iteration code, no prefetching is done.
636 * Use this for code that knows the list to be very short (empty
637 * or 1 entry) most of the time.
638 */
639#define __list_for_each(pos, head) \
640 for (pos = (head)->next; pos != (head); pos = pos->next)
641
642/**
643 * list_for_each_prev - iterate over a list backwards
644 * @pos: the &struct list_head to use as a loop cursor.
645 * @head: the head for your list.
646 */
647#define list_for_each_prev(pos, head) \
648 for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
649 pos = pos->prev)
650
651/**
652 * list_for_each_entry - iterate over list of given type
653 * @pos: the type * to use as a loop cursor.
654 * @head: the head for your list.
655 * @member: the name of the list_struct within the struct.
656 */
657#define list_for_each_entry(pos, head, member) \
658 for (pos = list_entry((head)->next, typeof(*pos), member); \
659 prefetch(pos->member.next), &pos->member != (head); \
660 pos = list_entry(pos->member.next, typeof(*pos), member))
661
662/**
663 * list_for_each_entry_reverse - iterate backwards over list of given type.
664 * @pos: the type * to use as a loop cursor.
665 * @head: the head for your list.
666 * @member: the name of the list_struct within the struct.
667 */
668#define list_for_each_entry_reverse(pos, head, member) \
669 for (pos = list_entry((head)->prev, typeof(*pos), member); \
670 prefetch(pos->member.prev), &pos->member != (head); \
671 pos = list_entry(pos->member.prev, typeof(*pos), member))
672
673/**
674 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
675 * @pos: the type * to use as a start point
676 * @head: the head of the list
677 * @member: the name of the list_struct within the struct.
678 *
679 * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
680 */
681#define list_prepare_entry(pos, head, member) \
682 ((pos) ? : list_entry(head, typeof(*pos), member))
683
684/**
685 * list_for_each_entry_continue - continue iteration over list of given type
686 * @pos: the type * to use as a loop cursor.
687 * @head: the head for your list.
688 * @member: the name of the list_struct within the struct.
689 *
690 * Continue to iterate over list of given type, continuing after
691 * the current position.
692 */
693#define list_for_each_entry_continue(pos, head, member) \
694 for (pos = list_entry(pos->member.next, typeof(*pos), member); \
695 prefetch(pos->member.next), &pos->member != (head); \
696 pos = list_entry(pos->member.next, typeof(*pos), member))
697
698/**
699 * list_for_each_entry_from - iterate over list of given type from the current point
700 * @pos: the type * to use as a loop cursor.
701 * @head: the head for your list.
702 * @member: the name of the list_struct within the struct.
703 *
704 * Iterate over list of given type, continuing from current position.
705 */
706#define list_for_each_entry_from(pos, head, member) \
707 for (; prefetch(pos->member.next), &pos->member != (head); \
708 pos = list_entry(pos->member.next, typeof(*pos), member))
709
710#endif /*_LINKED_LIST_H_*/
diff --git a/firmware/export/usb_ch9.h b/firmware/export/usb_ch9.h
new file mode 100644
index 0000000000..5784ff3242
--- /dev/null
+++ b/firmware/export/usb_ch9.h
@@ -0,0 +1,762 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) by Linux Kernel Developers
11 *
12 * Based on code from the Linux Kernel
13 * available at http://www.kernel.org
14 * Original file: <kernel>/include/linux/usb/ch9.h
15 *
16 * All files in this archive are subject to the GNU General Public License.
17 * See the file COPYING in the source tree root for full license agreement.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24#ifndef _CH9_H_
25#define _CH9_H_
26
27#include <inttypes.h>
28
29/*
30 * USB directions
31 *
32 * This bit flag is used in endpoint descriptors' bEndpointAddress field.
33 * It's also one of three fields in control requests bRequestType.
34 */
35#define USB_DIR_OUT 0 /* to device */
36#define USB_DIR_IN 0x80 /* to host */
37
38/*
39 * USB types, the second of three bRequestType fields
40 */
41#define USB_TYPE_MASK (0x03 << 5)
42#define USB_TYPE_STANDARD (0x00 << 5)
43#define USB_TYPE_CLASS (0x01 << 5)
44#define USB_TYPE_VENDOR (0x02 << 5)
45#define USB_TYPE_RESERVED (0x03 << 5)
46
47/*
48 * USB recipients, the third of three bRequestType fields
49 */
50#define USB_RECIP_MASK 0x1f
51#define USB_RECIP_DEVICE 0x00
52#define USB_RECIP_INTERFACE 0x01
53#define USB_RECIP_ENDPOINT 0x02
54#define USB_RECIP_OTHER 0x03
55
56/*-------------------------------------------------------------------------*/
57
58/**
59 * struct usb_ctrlrequest - SETUP data for a USB device control request
60 * @bRequestType: matches the USB bmRequestType field
61 * @bRequest: matches the USB bRequest field
62 * @wValue: matches the USB wValue field (le16 byte order)
63 * @wIndex: matches the USB wIndex field (le16 byte order)
64 * @wLength: matches the USB wLength field (le16 byte order)
65 */
66struct usb_ctrlrequest {
67 uint8_t bRequestType;
68 uint8_t bRequest;
69 uint16_t wValue;
70 uint16_t wIndex;
71 uint16_t wLength;
72} __attribute__ ((packed));
73
74/*
75 * Standard requests, for the bRequest field of a SETUP packet.
76 *
77 * These are qualified by the bRequestType field, so that for example
78 * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
79 * by a GET_STATUS request.
80 */
81#define USB_REQ_GET_STATUS 0x00
82#define USB_REQ_CLEAR_FEATURE 0x01
83#define USB_REQ_SET_FEATURE 0x03
84#define USB_REQ_SET_ADDRESS 0x05
85#define USB_REQ_GET_DESCRIPTOR 0x06
86#define USB_REQ_SET_DESCRIPTOR 0x07
87#define USB_REQ_GET_CONFIGURATION 0x08
88#define USB_REQ_SET_CONFIGURATION 0x09
89#define USB_REQ_GET_INTERFACE 0x0A
90#define USB_REQ_SET_INTERFACE 0x0B
91#define USB_REQ_SYNCH_FRAME 0x0C
92
93/*-------------------------------------------------------------------------*/
94
95/*
96 * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
97 * (rarely) accepted by SET_DESCRIPTOR.
98 *
99 * Note that all multi-byte values here are encoded in little endian
100 * byte order "on the wire". But when exposed through Linux-USB APIs,
101 * they've been converted to cpu byte order.
102 */
103
104/*
105 * Descriptor types ... USB 2.0 spec table 9.5
106 */
107#define USB_DT_DEVICE 0x01
108#define USB_DT_CONFIG 0x02
109#define USB_DT_STRING 0x03
110#define USB_DT_INTERFACE 0x04
111#define USB_DT_ENDPOINT 0x05
112#define USB_DT_DEVICE_QUALIFIER 0x06
113#define USB_DT_OTHER_SPEED_CONFIG 0x07
114#define USB_DT_INTERFACE_POWER 0x08
115/* these are from a minor usb 2.0 revision (ECN) */
116#define USB_DT_OTG 0x09
117#define USB_DT_DEBUG 0x0a
118#define USB_DT_INTERFACE_ASSOCIATION 0x0b
119/* these are from the Wireless USB spec */
120#define USB_DT_SECURITY 0x0c
121#define USB_DT_KEY 0x0d
122#define USB_DT_ENCRYPTION_TYPE 0x0e
123#define USB_DT_BOS 0x0f
124#define USB_DT_DEVICE_CAPABILITY 0x10
125#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
126#define USB_DT_WIRE_ADAPTER 0x21
127#define USB_DT_RPIPE 0x22
128
129/* Conventional codes for class-specific descriptors. The convention is
130 * defined in the USB "Common Class" Spec (3.11). Individual class specs
131 * are authoritative for their usage, not the "common class" writeup.
132 */
133#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE)
134#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG)
135#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING)
136#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE)
137#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT)
138
139/*-------------------------------------------------------------------------*/
140
141/* USB_DT_DEVICE: Device descriptor */
142struct usb_device_descriptor {
143 uint8_t bLength;
144 uint8_t bDescriptorType;
145 uint16_t bcdUSB;
146 uint8_t bDeviceClass;
147 uint8_t bDeviceSubClass;
148 uint8_t bDeviceProtocol;
149 uint8_t bMaxPacketSize0;
150 uint16_t idVendor;
151 uint16_t idProduct;
152 uint16_t bcdDevice;
153 uint8_t iManufacturer;
154 uint8_t iProduct;
155 uint8_t iSerialNumber;
156 uint8_t bNumConfigurations;
157} __attribute__ ((packed));
158
159#define USB_DT_DEVICE_SIZE 18
160
161/*
162 * Device and/or Interface Class codes
163 * as found in bDeviceClass or bInterfaceClass
164 * and defined by www.usb.org documents
165 */
166#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
167#define USB_CLASS_AUDIO 1
168#define USB_CLASS_COMM 2
169#define USB_CLASS_HID 3
170#define USB_CLASS_PHYSICAL 5
171#define USB_CLASS_STILL_IMAGE 6
172#define USB_CLASS_PRINTER 7
173#define USB_CLASS_MASS_STORAGE 8
174#define USB_CLASS_HUB 9
175#define USB_CLASS_CDC_DATA 0x0a
176#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
177#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
178#define USB_CLASS_VIDEO 0x0e
179#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
180#define USB_CLASS_MISC 0xef
181#define USB_CLASS_APP_SPEC 0xfe
182#define USB_CLASS_VENDOR_SPEC 0xff
183
184/*-------------------------------------------------------------------------*/
185
186/* USB_DT_CONFIG: Configuration descriptor information.
187 *
188 * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
189 * descriptor type is different. Highspeed-capable devices can look
190 * different depending on what speed they're currently running. Only
191 * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
192 * descriptors.
193 */
194struct usb_config_descriptor {
195 uint8_t bLength;
196 uint8_t bDescriptorType;
197 uint16_t wTotalLength;
198 uint8_t bNumInterfaces;
199 uint8_t bConfigurationValue;
200 uint8_t iConfiguration;
201 uint8_t bmAttributes;
202 uint8_t bMaxPower;
203} __attribute__ ((packed));
204
205#define USB_DT_CONFIG_SIZE 9
206
207/* from config descriptor bmAttributes */
208#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
209#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
210#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
211#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */
212
213/*-------------------------------------------------------------------------*/
214
215/* USB_DT_STRING: String descriptor */
216struct usb_string_descriptor {
217 uint8_t bLength;
218 uint8_t bDescriptorType;
219
220 uint16_t wData[1]; /* UTF-16LE encoded */
221} __attribute__ ((packed));
222
223/* note that "string" zero is special, it holds language codes that
224 * the device supports, not Unicode characters.
225 */
226
227/*-------------------------------------------------------------------------*/
228
229/* USB_DT_INTERFACE: Interface descriptor */
230struct usb_interface_descriptor {
231 uint8_t bLength;
232 uint8_t bDescriptorType;
233
234 uint8_t bInterfaceNumber;
235 uint8_t bAlternateSetting;
236 uint8_t bNumEndpoints;
237 uint8_t bInterfaceClass;
238 uint8_t bInterfaceSubClass;
239 uint8_t bInterfaceProtocol;
240 uint8_t iInterface;
241} __attribute__ ((packed));
242
243#define USB_DT_INTERFACE_SIZE 9
244
245/*-------------------------------------------------------------------------*/
246
247/* USB_DT_ENDPOINT: Endpoint descriptor */
248struct usb_endpoint_descriptor {
249 uint8_t bLength;
250 uint8_t bDescriptorType;
251
252 uint8_t bEndpointAddress;
253 uint8_t bmAttributes;
254 uint16_t wMaxPacketSize;
255 uint8_t bInterval;
256
257 /* NOTE: these two are _only_ in audio endpoints. */
258 /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
259 //uint8_t bRefresh;
260 //uint8_t bSynchAddress;
261} __attribute__ ((packed));
262
263#define USB_DT_ENDPOINT_SIZE 7
264#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
265
266/*-------------------------------------------------------------------------*/
267
268/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
269struct usb_qualifier_descriptor {
270 uint8_t bLength;
271 uint8_t bDescriptorType;
272
273 uint16_t bcdUSB;
274 uint8_t bDeviceClass;
275 uint8_t bDeviceSubClass;
276 uint8_t bDeviceProtocol;
277 uint8_t bMaxPacketSize0;
278 uint8_t bNumConfigurations;
279 uint8_t bRESERVED;
280} __attribute__ ((packed));
281
282/*-------------------------------------------------------------------------*/
283
284/* USB_DT_OTG (from OTG 1.0a supplement) */
285struct usb_otg_descriptor {
286 uint8_t bLength;
287 uint8_t bDescriptorType;
288
289 uint8_t bmAttributes; /* support for HNP, SRP, etc */
290} __attribute__ ((packed));
291
292/* from usb_otg_descriptor.bmAttributes */
293#define USB_OTG_SRP (1 << 0)
294#define USB_OTG_HNP (1 << 1) /* swap host/device roles */
295
296/*-------------------------------------------------------------------------*/
297
298/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */
299struct usb_debug_descriptor {
300 uint8_t bLength;
301 uint8_t bDescriptorType;
302
303 /* bulk endpoints with 8 byte maxpacket */
304 uint8_t bDebugInEndpoint;
305 uint8_t bDebugOutEndpoint;
306};
307
308/*-------------------------------------------------------------------------*/
309
310/*
311 * Endpoints
312 */
313#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
314#define USB_ENDPOINT_XFER_CONTROL 0
315#define USB_ENDPOINT_XFER_ISOC 1
316#define USB_ENDPOINT_XFER_BULK 2
317#define USB_ENDPOINT_XFER_INT 3
318
319enum usb_device_speed {
320 USB_SPEED_UNKNOWN = 0, /* enumerating */
321 USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
322 USB_SPEED_HIGH, /* usb 2.0 */
323 USB_SPEED_VARIABLE, /* wireless (usb 2.5) */
324};
325
326enum usb_device_state {
327 /* NOTATTACHED isn't in the USB spec, and this state acts
328 * the same as ATTACHED ... but it's clearer this way.
329 */
330 USB_STATE_NOTATTACHED = 0,
331
332 /* chapter 9 and authentication (wireless) device states */
333 USB_STATE_ATTACHED,
334 USB_STATE_POWERED, /* wired */
335 USB_STATE_UNAUTHENTICATED, /* auth */
336 USB_STATE_RECONNECTING, /* auth */
337 USB_STATE_DEFAULT, /* limited function */
338 USB_STATE_ADDRESS,
339 USB_STATE_CONFIGURED, /* most functions */
340
341 USB_STATE_SUSPENDED
342
343 /* NOTE: there are actually four different SUSPENDED
344 * states, returning to POWERED, DEFAULT, ADDRESS, or
345 * CONFIGURED respectively when SOF tokens flow again.
346 */
347};
348
349/* All standard descriptors have these 2 fields at the beginning */
350struct usb_descriptor_header {
351 uint8_t bLength;
352 uint8_t bDescriptorType;
353} __attribute__ ((packed));
354
355/**
356 * struct usb_string - wraps a C string and its USB id
357 * @id:the (nonzero) ID for this string
358 * @s:the string, in UTF-8 encoding
359 *
360 * If you're using usb_gadget_get_string(), use this to wrap a string
361 * together with its ID.
362 */
363struct usb_string {
364 uint8_t id;
365 const char* s;
366};
367
368/**
369 * struct usb_gadget_strings - a set of USB strings in a given language
370 * @language:identifies the strings' language (0x0409 for en-us)
371 * @strings:array of strings with their ids
372 *
373 * If you're using usb_gadget_get_string(), use this to wrap all the
374 * strings for a given language.
375 */
376struct usb_gadget_strings {
377 uint16_t language; /* 0x0409 for en-us */
378 struct usb_string* strings;
379};
380
381#endif /*_CH9_H_*/
382/***************************************************************************
383 * __________ __ ___.
384 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
385 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
386 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
387 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
388 * \/ \/ \/ \/ \/
389 * $Id: $
390 *
391 * Copyright (C) by Linux Kernel Developers
392 *
393 * Based on code from the Linux Kernel
394 * available at http://www.kernel.org
395 * Original file: <kernel>/include/linux/usb/ch9.h
396 *
397 * All files in this archive are subject to the GNU General Public License.
398 * See the file COPYING in the source tree root for full license agreement.
399 *
400 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
401 * KIND, either express or implied.
402 *
403 ****************************************************************************/
404
405#ifndef _CH9_H_
406#define _CH9_H_
407
408#include <inttypes.h>
409
410/*
411 * USB directions
412 *
413 * This bit flag is used in endpoint descriptors' bEndpointAddress field.
414 * It's also one of three fields in control requests bRequestType.
415 */
416#define USB_DIR_OUT 0 /* to device */
417#define USB_DIR_IN 0x80 /* to host */
418
419/*
420 * USB types, the second of three bRequestType fields
421 */
422#define USB_TYPE_MASK (0x03 << 5)
423#define USB_TYPE_STANDARD (0x00 << 5)
424#define USB_TYPE_CLASS (0x01 << 5)
425#define USB_TYPE_VENDOR (0x02 << 5)
426#define USB_TYPE_RESERVED (0x03 << 5)
427
428/*
429 * USB recipients, the third of three bRequestType fields
430 */
431#define USB_RECIP_MASK 0x1f
432#define USB_RECIP_DEVICE 0x00
433#define USB_RECIP_INTERFACE 0x01
434#define USB_RECIP_ENDPOINT 0x02
435#define USB_RECIP_OTHER 0x03
436
437/*-------------------------------------------------------------------------*/
438
439/**
440 * struct usb_ctrlrequest - SETUP data for a USB device control request
441 * @bRequestType: matches the USB bmRequestType field
442 * @bRequest: matches the USB bRequest field
443 * @wValue: matches the USB wValue field (le16 byte order)
444 * @wIndex: matches the USB wIndex field (le16 byte order)
445 * @wLength: matches the USB wLength field (le16 byte order)
446 */
447struct usb_ctrlrequest {
448 uint8_t bRequestType;
449 uint8_t bRequest;
450 uint16_t wValue;
451 uint16_t wIndex;
452 uint16_t wLength;
453} __attribute__ ((packed));
454
455/*
456 * Standard requests, for the bRequest field of a SETUP packet.
457 *
458 * These are qualified by the bRequestType field, so that for example
459 * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
460 * by a GET_STATUS request.
461 */
462#define USB_REQ_GET_STATUS 0x00
463#define USB_REQ_CLEAR_FEATURE 0x01
464#define USB_REQ_SET_FEATURE 0x03
465#define USB_REQ_SET_ADDRESS 0x05
466#define USB_REQ_GET_DESCRIPTOR 0x06
467#define USB_REQ_SET_DESCRIPTOR 0x07
468#define USB_REQ_GET_CONFIGURATION 0x08
469#define USB_REQ_SET_CONFIGURATION 0x09
470#define USB_REQ_GET_INTERFACE 0x0A
471#define USB_REQ_SET_INTERFACE 0x0B
472#define USB_REQ_SYNCH_FRAME 0x0C
473
474/*-------------------------------------------------------------------------*/
475
476/*
477 * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
478 * (rarely) accepted by SET_DESCRIPTOR.
479 *
480 * Note that all multi-byte values here are encoded in little endian
481 * byte order "on the wire". But when exposed through Linux-USB APIs,
482 * they've been converted to cpu byte order.
483 */
484
485/*
486 * Descriptor types ... USB 2.0 spec table 9.5
487 */
488#define USB_DT_DEVICE 0x01
489#define USB_DT_CONFIG 0x02
490#define USB_DT_STRING 0x03
491#define USB_DT_INTERFACE 0x04
492#define USB_DT_ENDPOINT 0x05
493#define USB_DT_DEVICE_QUALIFIER 0x06
494#define USB_DT_OTHER_SPEED_CONFIG 0x07
495#define USB_DT_INTERFACE_POWER 0x08
496/* these are from a minor usb 2.0 revision (ECN) */
497#define USB_DT_OTG 0x09
498#define USB_DT_DEBUG 0x0a
499#define USB_DT_INTERFACE_ASSOCIATION 0x0b
500/* these are from the Wireless USB spec */
501#define USB_DT_SECURITY 0x0c
502#define USB_DT_KEY 0x0d
503#define USB_DT_ENCRYPTION_TYPE 0x0e
504#define USB_DT_BOS 0x0f
505#define USB_DT_DEVICE_CAPABILITY 0x10
506#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
507#define USB_DT_WIRE_ADAPTER 0x21
508#define USB_DT_RPIPE 0x22
509
510/* Conventional codes for class-specific descriptors. The convention is
511 * defined in the USB "Common Class" Spec (3.11). Individual class specs
512 * are authoritative for their usage, not the "common class" writeup.
513 */
514#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE)
515#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG)
516#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING)
517#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE)
518#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT)
519
520/*-------------------------------------------------------------------------*/
521
522/* USB_DT_DEVICE: Device descriptor */
523struct usb_device_descriptor {
524 uint8_t bLength;
525 uint8_t bDescriptorType;
526 uint16_t bcdUSB;
527 uint8_t bDeviceClass;
528 uint8_t bDeviceSubClass;
529 uint8_t bDeviceProtocol;
530 uint8_t bMaxPacketSize0;
531 uint16_t idVendor;
532 uint16_t idProduct;
533 uint16_t bcdDevice;
534 uint8_t iManufacturer;
535 uint8_t iProduct;
536 uint8_t iSerialNumber;
537 uint8_t bNumConfigurations;
538} __attribute__ ((packed));
539
540#define USB_DT_DEVICE_SIZE 18
541
542/*
543 * Device and/or Interface Class codes
544 * as found in bDeviceClass or bInterfaceClass
545 * and defined by www.usb.org documents
546 */
547#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
548#define USB_CLASS_AUDIO 1
549#define USB_CLASS_COMM 2
550#define USB_CLASS_HID 3
551#define USB_CLASS_PHYSICAL 5
552#define USB_CLASS_STILL_IMAGE 6
553#define USB_CLASS_PRINTER 7
554#define USB_CLASS_MASS_STORAGE 8
555#define USB_CLASS_HUB 9
556#define USB_CLASS_CDC_DATA 0x0a
557#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
558#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
559#define USB_CLASS_VIDEO 0x0e
560#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
561#define USB_CLASS_MISC 0xef
562#define USB_CLASS_APP_SPEC 0xfe
563#define USB_CLASS_VENDOR_SPEC 0xff
564
565/*-------------------------------------------------------------------------*/
566
567/* USB_DT_CONFIG: Configuration descriptor information.
568 *
569 * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
570 * descriptor type is different. Highspeed-capable devices can look
571 * different depending on what speed they're currently running. Only
572 * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
573 * descriptors.
574 */
575struct usb_config_descriptor {
576 uint8_t bLength;
577 uint8_t bDescriptorType;
578 uint16_t wTotalLength;
579 uint8_t bNumInterfaces;
580 uint8_t bConfigurationValue;
581 uint8_t iConfiguration;
582 uint8_t bmAttributes;
583 uint8_t bMaxPower;
584} __attribute__ ((packed));
585
586#define USB_DT_CONFIG_SIZE 9
587
588/* from config descriptor bmAttributes */
589#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
590#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
591#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
592#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */
593
594/*-------------------------------------------------------------------------*/
595
596/* USB_DT_STRING: String descriptor */
597struct usb_string_descriptor {
598 uint8_t bLength;
599 uint8_t bDescriptorType;
600
601 uint16_t wData[1]; /* UTF-16LE encoded */
602} __attribute__ ((packed));
603
604/* note that "string" zero is special, it holds language codes that
605 * the device supports, not Unicode characters.
606 */
607
608/*-------------------------------------------------------------------------*/
609
610/* USB_DT_INTERFACE: Interface descriptor */
611struct usb_interface_descriptor {
612 uint8_t bLength;
613 uint8_t bDescriptorType;
614
615 uint8_t bInterfaceNumber;
616 uint8_t bAlternateSetting;
617 uint8_t bNumEndpoints;
618 uint8_t bInterfaceClass;
619 uint8_t bInterfaceSubClass;
620 uint8_t bInterfaceProtocol;
621 uint8_t iInterface;
622} __attribute__ ((packed));
623
624#define USB_DT_INTERFACE_SIZE 9
625
626/*-------------------------------------------------------------------------*/
627
628/* USB_DT_ENDPOINT: Endpoint descriptor */
629struct usb_endpoint_descriptor {
630 uint8_t bLength;
631 uint8_t bDescriptorType;
632
633 uint8_t bEndpointAddress;
634 uint8_t bmAttributes;
635 uint16_t wMaxPacketSize;
636 uint8_t bInterval;
637
638 /* NOTE: these two are _only_ in audio endpoints. */
639 /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
640 //uint8_t bRefresh;
641 //uint8_t bSynchAddress;
642} __attribute__ ((packed));
643
644#define USB_DT_ENDPOINT_SIZE 7
645#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
646
647/*-------------------------------------------------------------------------*/
648
649/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
650struct usb_qualifier_descriptor {
651 uint8_t bLength;
652 uint8_t bDescriptorType;
653
654 uint16_t bcdUSB;
655 uint8_t bDeviceClass;
656 uint8_t bDeviceSubClass;
657 uint8_t bDeviceProtocol;
658 uint8_t bMaxPacketSize0;
659 uint8_t bNumConfigurations;
660 uint8_t bRESERVED;
661} __attribute__ ((packed));
662
663/*-------------------------------------------------------------------------*/
664
665/* USB_DT_OTG (from OTG 1.0a supplement) */
666struct usb_otg_descriptor {
667 uint8_t bLength;
668 uint8_t bDescriptorType;
669
670 uint8_t bmAttributes; /* support for HNP, SRP, etc */
671} __attribute__ ((packed));
672
673/* from usb_otg_descriptor.bmAttributes */
674#define USB_OTG_SRP (1 << 0)
675#define USB_OTG_HNP (1 << 1) /* swap host/device roles */
676
677/*-------------------------------------------------------------------------*/
678
679/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */
680struct usb_debug_descriptor {
681 uint8_t bLength;
682 uint8_t bDescriptorType;
683
684 /* bulk endpoints with 8 byte maxpacket */
685 uint8_t bDebugInEndpoint;
686 uint8_t bDebugOutEndpoint;
687};
688
689/*-------------------------------------------------------------------------*/
690
691/*
692 * Endpoints
693 */
694#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
695#define USB_ENDPOINT_XFER_CONTROL 0
696#define USB_ENDPOINT_XFER_ISOC 1
697#define USB_ENDPOINT_XFER_BULK 2
698#define USB_ENDPOINT_XFER_INT 3
699
700enum usb_device_speed {
701 USB_SPEED_UNKNOWN = 0, /* enumerating */
702 USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
703 USB_SPEED_HIGH, /* usb 2.0 */
704 USB_SPEED_VARIABLE, /* wireless (usb 2.5) */
705};
706
707enum usb_device_state {
708 /* NOTATTACHED isn't in the USB spec, and this state acts
709 * the same as ATTACHED ... but it's clearer this way.
710 */
711 USB_STATE_NOTATTACHED = 0,
712
713 /* chapter 9 and authentication (wireless) device states */
714 USB_STATE_ATTACHED,
715 USB_STATE_POWERED, /* wired */
716 USB_STATE_UNAUTHENTICATED, /* auth */
717 USB_STATE_RECONNECTING, /* auth */
718 USB_STATE_DEFAULT, /* limited function */
719 USB_STATE_ADDRESS,
720 USB_STATE_CONFIGURED, /* most functions */
721
722 USB_STATE_SUSPENDED
723
724 /* NOTE: there are actually four different SUSPENDED
725 * states, returning to POWERED, DEFAULT, ADDRESS, or
726 * CONFIGURED respectively when SOF tokens flow again.
727 */
728};
729
730/* All standard descriptors have these 2 fields at the beginning */
731struct usb_descriptor_header {
732 uint8_t bLength;
733 uint8_t bDescriptorType;
734} __attribute__ ((packed));
735
736/**
737 * struct usb_string - wraps a C string and its USB id
738 * @id:the (nonzero) ID for this string
739 * @s:the string, in UTF-8 encoding
740 *
741 * If you're using usb_gadget_get_string(), use this to wrap a string
742 * together with its ID.
743 */
744struct usb_string {
745 uint8_t id;
746 const char* s;
747};
748
749/**
750 * struct usb_gadget_strings - a set of USB strings in a given language
751 * @language:identifies the strings' language (0x0409 for en-us)
752 * @strings:array of strings with their ids
753 *
754 * If you're using usb_gadget_get_string(), use this to wrap all the
755 * strings for a given language.
756 */
757struct usb_gadget_strings {
758 uint16_t language; /* 0x0409 for en-us */
759 struct usb_string* strings;
760};
761
762#endif /*_CH9_H_*/
diff --git a/firmware/export/usbstack.h b/firmware/export/usbstack.h
new file mode 100644
index 0000000000..9142b1bdba
--- /dev/null
+++ b/firmware/export/usbstack.h
@@ -0,0 +1,55 @@
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_H_
21#define _USBSTACK_H_
22
23#include <errno.h>
24
25#define USB_STACK_MAX_SETTINGS_NAME 32*10 /* should be enough for > 10 driver names */
26
27/*
28 * error codes
29 */
30#define ENOFREESLOT 1
31#define EWRONGCONTROLLERTYPE 2
32#define ENODRIVERFOUND 3
33#define EHWCRITICAL 4
34
35enum usb_controller_type {
36 DEVICE = 0,
37 HOST,
38};
39
40/*
41 * stack routines
42 */
43void usb_stack_init(void);
44void usb_stack_start(void);
45void usb_stack_stop(void);
46
47void usb_controller_select(int type);
48int usb_stack_get_mode(void);
49int usb_device_driver_bind(const char* name);
50void ubs_device_driver_unbind(void);
51
52/* used by apps settings code */
53unsigned char device_driver_names[USB_STACK_MAX_SETTINGS_NAME];
54
55#endif /*_USBSTACK_H_*/
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c
index 98ee78b0ff..a282564d19 100644
--- a/firmware/target/arm/system-pp502x.c
+++ b/firmware/target/arm/system-pp502x.c
@@ -35,13 +35,20 @@ extern void clickwheel_int(void);
35extern void microsd_int(void); 35extern void microsd_int(void);
36#endif 36#endif
37 37
38#ifdef HAVE_USBSTACK
39#include "usbstack/core.h"
40#endif
41
38void irq(void) 42void irq(void)
39{ 43{
40 if(CURRENT_CORE == CPU) 44 if(CURRENT_CORE == CPU)
41 { 45 {
42 if (CPU_INT_STAT & TIMER1_MASK) 46 if (CPU_INT_STAT & TIMER1_MASK) {
43 TIMER1(); 47 TIMER1();
44 else if (CPU_INT_STAT & TIMER2_MASK) 48#ifdef HAVE_USBSTACK
49 usb_stack_irq();
50#endif
51 } else if (CPU_INT_STAT & TIMER2_MASK)
45 TIMER2(); 52 TIMER2();
46#if defined(IPOD_MINI) /* Mini 1st gen only, mini 2nd gen uses iPod 4G code */ 53#if defined(IPOD_MINI) /* Mini 1st gen only, mini 2nd gen uses iPod 4G code */
47 else if (CPU_HI_INT_STAT & GPIO_MASK) 54 else if (CPU_HI_INT_STAT & GPIO_MASK)
diff --git a/firmware/target/arm/usb-fw-pp502x.c b/firmware/target/arm/usb-fw-pp502x.c
index 92e3dee562..f687782447 100644
--- a/firmware/target/arm/usb-fw-pp502x.c
+++ b/firmware/target/arm/usb-fw-pp502x.c
@@ -22,71 +22,16 @@
22 * 22 *
23 ****************************************************************************/ 23 ****************************************************************************/
24#include "config.h" 24#include "config.h"
25#include "cpu.h"
26#include "kernel.h"
27#include "thread.h"
28#include "system.h" 25#include "system.h"
29#include "debug.h"
30#include "ata.h"
31#include "fat.h"
32#include "disk.h"
33#include "panic.h"
34#include "lcd.h"
35#include "adc.h"
36#include "usb.h" 26#include "usb.h"
37#include "button.h"
38#include "sprintf.h"
39#include "string.h"
40#include "hwcompat.h"
41
42#include "usb-target.h"
43#include "arcotg_udc.h" 27#include "arcotg_udc.h"
44 28
29#ifdef HAVE_USBSTACK
30#include "usbstack.h"
31#endif
32
45void usb_init_device(void) 33void usb_init_device(void)
46{ 34{
47 int r0;
48 outl(inl(0x70000084) | 0x200, 0x70000084);
49
50 outl(inl(0x7000002C) | 0x3000000, 0x7000002C);
51 DEV_EN |= DEV_USB;
52
53 DEV_RS |= DEV_USB; /* reset usb start */
54 DEV_RS &=~DEV_USB;/* reset usb end */
55
56 DEV_INIT |= INIT_USB;
57 while ((inl(0x70000028) & 0x80) == 0);
58
59 UDC_PORTSC1 |= PORTSCX_PORT_RESET;
60 while ((UDC_PORTSC1 & PORTSCX_PORT_RESET) != 0);
61
62 UDC_OTGSC |= 0x5F000000;
63 if( (UDC_OTGSC & 0x100) == 0) {
64 UDC_USBMODE &=~ USB_MODE_CTRL_MODE_HOST;
65 UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
66 outl(inl(0x70000028) | 0x4000, 0x70000028);
67 outl(inl(0x70000028) | 0x2, 0x70000028);
68 } else {
69 UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
70 outl(inl(0x70000028) &~0x4000, 0x70000028);
71 outl(inl(0x70000028) | 0x2, 0x70000028);
72 }
73
74
75 UDC_USBCMD |= USB_CMD_CTRL_RESET;
76 while((UDC_USBCMD & USB_CMD_CTRL_RESET) != 0);
77
78 r0 = UDC_PORTSC1;
79
80 /* Note from IPL source (referring to next 5 lines of code:
81 THIS NEEDS TO BE CHANGED ONCE THERE IS KERNEL USB */
82 DEV_INIT |= INIT_USB;
83 DEV_EN |= DEV_USB;
84 while ((inl(0x70000028) & 0x80) == 0);
85 outl(inl(0x70000028) | 0x2, 0x70000028);
86
87 udelay(0x186A0);
88
89 dr_controller_setup();
90 35
91#if defined(IPOD_COLOR) || defined(IPOD_4G) \ 36#if defined(IPOD_COLOR) || defined(IPOD_4G) \
92 || defined(IPOD_MINI) || defined(IPOD_MINI2G) 37 || defined(IPOD_MINI) || defined(IPOD_MINI2G)
@@ -98,6 +43,7 @@ void usb_init_device(void)
98 43
99void usb_enable(bool on) 44void usb_enable(bool on)
100{ 45{
46#ifndef HAVE_USBSTACK
101 /* This device specific code will eventually give way to proper USB 47 /* This device specific code will eventually give way to proper USB
102 handling, which should be the same for all PP502x targets. */ 48 handling, which should be the same for all PP502x targets. */
103 if (on) 49 if (on)
@@ -125,6 +71,7 @@ void usb_enable(bool on)
125 } 71 }
126#endif 72#endif
127 } 73 }
74#endif
128} 75}
129 76
130bool usb_detect(void) 77bool usb_detect(void)
@@ -151,12 +98,13 @@ bool usb_detect(void)
151 } 98 }
152 99
153 usbstatus1 = (UDC_OTGSC & 0x800) ? true : false; 100 usbstatus1 = (UDC_OTGSC & 0x800) ? true : false;
101#ifdef HAVE_USBSTACK
154 if ((usbstatus1 == true) && (prev_usbstatus1 == false)) { 102 if ((usbstatus1 == true) && (prev_usbstatus1 == false)) {
155 dr_controller_run(); 103 usb_stack_start();
156 } else if ((usbstatus1 == false) && (prev_usbstatus1 == true)) { 104 } else if ((usbstatus1 == false) && (prev_usbstatus1 == true)) {
157 dr_controller_stop(); 105 usb_stack_stop();
158 } 106 }
159 107#endif
160 prev_usbstatus1 = usbstatus1; 108 prev_usbstatus1 = usbstatus1;
161 usbstatus2 = (UDC_PORTSC1 & PORTSCX_CURRENT_CONNECT_STATUS) ? true : false; 109 usbstatus2 = (UDC_PORTSC1 & PORTSCX_CURRENT_CONNECT_STATUS) ? true : false;
162 110
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_*/