summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2007-11-22 20:51:00 +0000
committerBjörn Stenberg <bjorn@haxx.se>2007-11-22 20:51:00 +0000
commitb4e5123e5d78935a3ab961d54ee5902eed37aa32 (patch)
treee0818a8c26e4a435188e70820c3aab387b01d842
parent2e2cbfe4acc22c1c69e38b638280da974630ca7f (diff)
downloadrockbox-b4e5123e5d78935a3ab961d54ee5902eed37aa32.tar.gz
rockbox-b4e5123e5d78935a3ab961d54ee5902eed37aa32.tar.bz2
rockbox-b4e5123e5d78935a3ab961d54ee5902eed37aa32.zip
New USB stack
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15758 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/main.c7
-rw-r--r--apps/menus/settings_menu.c92
-rw-r--r--apps/settings.c16
-rw-r--r--apps/settings_list.c12
-rw-r--r--firmware/FILES4
-rw-r--r--firmware/SOURCES28
-rw-r--r--firmware/drivers/usb/arcotg_dcd.c1032
-rw-r--r--firmware/drivers/usb/arcotg_dcd.h179
-rw-r--r--firmware/drivers/usb/arcotg_udc.c136
-rw-r--r--firmware/export/arcotg_udc.h318
-rw-r--r--firmware/export/config-c200.h6
-rw-r--r--firmware/export/config-e200.h7
-rw-r--r--firmware/export/config-h10.h6
-rw-r--r--firmware/export/config-h10_5gb.h6
-rw-r--r--firmware/export/linkedlist.h355
-rw-r--r--firmware/export/pp5020.h2
-rw-r--r--firmware/export/usb.h2
-rw-r--r--firmware/export/usb_core.h (renamed from firmware/usbstack/drivers/device/usb_serial.h)46
-rw-r--r--firmware/export/usb_drv.h (renamed from firmware/usbstack/drivers/device/usb_storage.h)32
-rw-r--r--firmware/export/usbstack.h63
-rw-r--r--firmware/target/arm/system-pp502x.c15
-rw-r--r--firmware/target/arm/usb-drv-pp502x.c624
-rw-r--r--firmware/target/arm/usb-fw-pp502x.c132
-rw-r--r--firmware/usb.c6
-rw-r--r--firmware/usbstack/controller.h88
-rw-r--r--firmware/usbstack/core.h64
-rw-r--r--firmware/usbstack/core/config.c82
-rw-r--r--firmware/usbstack/core/core.c402
-rw-r--r--firmware/usbstack/core/epsetup.c175
-rw-r--r--firmware/usbstack/core/utils.c176
-rw-r--r--firmware/usbstack/device.h47
-rw-r--r--firmware/usbstack/drivers/device/usb_serial.c358
-rw-r--r--firmware/usbstack/drivers/device/usb_storage.c387
-rw-r--r--firmware/usbstack/usb_benchmark.c125
-rw-r--r--firmware/usbstack/usb_benchmark.h (renamed from firmware/usbstack/utils.h)15
-rw-r--r--firmware/usbstack/usb_core.c537
-rw-r--r--firmware/usbstack/usb_storage.c331
-rw-r--r--firmware/usbstack/usb_storage.h (renamed from firmware/usbstack/host.h)23
-rw-r--r--tools/Makefile3
-rw-r--r--tools/usb_benchmark.c212
40 files changed, 1953 insertions, 4198 deletions
diff --git a/apps/main.c b/apps/main.c
index d75bb726cf..0ce8bcc7ac 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -99,10 +99,6 @@
#include "lcd-remote.h"
#endif
-#ifdef HAVE_USBSTACK
-#include "usbstack.h"
-#endif
-
#if CONFIG_USBOTG == USBOTG_ISP1362
#include "isp1362.h"
#endif
@@ -389,9 +385,6 @@ static void init(void)
adc_init();
-#ifdef HAVE_USBSTACK
- usb_stack_init();
-#endif
usb_init();
#if CONFIG_USBOTG == USBOTG_ISP1362
isp1362_init();
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index d1ca4a8d50..bcb8976a0c 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -42,13 +42,6 @@
#include "radio.h"
#endif
-#ifdef HAVE_USBSTACK
-#include "list.h"
-#include "usbstack.h"
-#include "statusbar.h"
-#include "misc.h"
-#endif
-
/***********************************/
/* TAGCACHE MENU */
#ifdef HAVE_TAGCACHE
@@ -453,88 +446,6 @@ MAKE_MENU(voice_settings_menu, ID2P(LANG_VOICE), 0, Icon_Voice,
/* VOICE MENU */
/***********************************/
-#ifdef HAVE_USBSTACK
-/***********************************/
-/* USB STACK MENU */
-char drivers[16][32];
-static char* usb_menu_getname(int item, void * data, char *buffer)
-{
- (void)data; (void)buffer;
- return drivers[item];
-}
-int usbdriver_menuitem(void)
-{
- struct gui_synclist lists;
- int action, count = 0;
- char *s = device_driver_names, *e;
- do {
- e = strchr(s, ',');
- if (e)
- {
- strncpy(drivers[count++], s, e-s);
- s = e+1;
- }
- } while (e && count < 16);
- if (count < 16)
- strcpy(drivers[count++], s);
- for (action=0; action<count; action++)
- {
- if (!strcmp(drivers[action],
- global_settings.usb_stack_device_driver))
- break;
- }
-
- gui_synclist_init(&lists, usb_menu_getname, drivers, false, 1);
- gui_synclist_set_title(&lists, str(LANG_USBSTACK_DEVICE_DRIVER), NOICON);
- gui_synclist_set_icon_callback(&lists, NULL);
- gui_synclist_set_nb_items(&lists, count);
- gui_synclist_select_item(&lists, action==count?0:action);
- gui_synclist_draw(&lists);
-
- while(1)
- {
- gui_syncstatusbar_draw(&statusbars, true);
- action = get_action(CONTEXT_STD, HZ/5);
- if (gui_synclist_do_button(&lists, &action, LIST_WRAP_UNLESS_HELD))
- continue;
- if (action == ACTION_STD_CANCEL)
- {
- /* setting was canceled */
- break;
- }
- else if (action == ACTION_STD_OK)
- {
- /* setting was accepted... save */
- strcpy(global_settings.usb_stack_device_driver,
- drivers[gui_synclist_get_sel_pos(&lists)]);
-
- /* switch device driver */
- usb_device_driver_bind(drivers[gui_synclist_get_sel_pos(&lists)]);
- break;
- }
- else if (action == ACTION_REDRAW)
- gui_synclist_draw(&lists);
- else if(default_event_handler(action) == SYS_USB_CONNECTED)
- return true;
- }
- return false;
-}
-
-#if USBSTACK_CAPS == (CONTROLLER_DEVICE|CONTROLLER_HOST)
-MENUITEM_SETTING(usbstack_mode, &global_settings.usb_stack_mode, NULL);
-#endif
-MENUITEM_FUNCTION(usbdriver, 0, ID2P(LANG_USBSTACK_DEVICE_DRIVER),
- usbdriver_menuitem, 0, NULL, Icon_NOICON);
-
-MAKE_MENU(usbstack_menu, ID2P(LANG_USBSTACK), 0, Icon_NOICON,
-#if USBSTACK_CAPS == (CONTROLLER_DEVICE|CONTROLLER_HOST)
- &usbstack_mode,
-#endif
- &usbdriver);
-/* USB STACK MENU */
-/***********************************/
-#endif
-
/***********************************/
/***********************************/
@@ -554,9 +465,6 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
#endif
&display_menu, &system_menu,
&bookmark_settings_menu, &browse_langs, &voice_settings_menu
-#ifdef HAVE_USBSTACK
- , &usbstack_menu
-#endif
);
/* SETTINGS MENU */
/***********************************/
diff --git a/apps/settings.c b/apps/settings.c
index add2b24c75..0b82ad41ac 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -97,10 +97,6 @@ struct system_status global_status;
#include "lcd-remote.h"
#endif
-#ifdef HAVE_USBSTACK
-#include "usbstack.h"
-#endif
-
long lasttime = 0;
/** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/
@@ -879,18 +875,6 @@ void settings_apply(void)
read_color_theme_file();
#endif
-#ifdef HAVE_USBSTACK
-
-#if USBSTACK_CAPS == (CONTROLLER_DEVICE|CONTROLLER_HOST)
- usb_controller_select(global_settings.usb_stack_mode);
-#elif USBSTACK_CAPS == (CONTROLLER_DEVICE)
- usb_controller_select(DEVICE);
-#elif USBSTACK_CAPS == (CONTROLLER_HOST)
- usb_controller_select(HOST);
-#endif
-
- usb_device_driver_bind(global_settings.usb_stack_device_driver);
-#endif
}
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 516c65eba2..6f0d7a8ff8 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -47,10 +47,6 @@
#include "radio.h"
#endif
-#ifdef HAVE_USBSTACK
-#include "usbstack.h"
-#endif
-
#define NVRAM(bytes) (bytes<<F_NVRAM_MASK_SHIFT)
/** NOTE: NVRAM_CONFIG_VERSION is in settings_list.h
and you may need to update it if you edit this file */
@@ -1270,14 +1266,6 @@ const struct settings_list settings[] = {
3, "list_accel_wait", UNIT_SEC, 1, 10, 1,
scanaccel_formatter, scanaccel_getlang, NULL),
#endif /* HAVE_SCROLLWHEEL */
-#ifdef HAVE_USBSTACK
- CHOICE_SETTING(0, usb_stack_mode, LANG_USBSTACK_MODE, 0, "usb mode",
- "device,host",
- usb_controller_select,
- 2, ID2P(LANG_USBSTACK_DEVICE), ID2P(LANG_USBSTACK_HOST)),
- FILENAME_SETTING(0, usb_stack_device_driver, "usb device driver",
- "storage", NULL, NULL, 32),
-#endif /* HAVE_USBSTACK */
};
const int nb_settings = sizeof(settings)/sizeof(*settings);
diff --git a/firmware/FILES b/firmware/FILES
index 3420a29f67..91302d3135 100644
--- a/firmware/FILES
+++ b/firmware/FILES
@@ -17,9 +17,7 @@ drivers/usb/*.[ch]
export/*.h
include/*.h
include/sys/*.h
-usbstack/*.h
-usbstack/core/*.c
-usbstack/drivers/device/*.[ch]
+usbstack/*.[ch]
target/arm/*.[chS]
target/arm/archos/av300/*.[chS]
target/arm/imx31/gigabeat-s/*.[chS]
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 52a7ab8d4c..0e159ecb9d 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -227,32 +227,14 @@ drivers/audio/mas35xx.c
/* USB Stack */
#if !defined(SIMULATOR)
#ifdef HAVE_USBSTACK
-usbstack/core/core.c
-usbstack/core/epsetup.c
-usbstack/core/utils.c
-usbstack/core/config.c
-usbstack/drivers/device/usb_serial.c
-usbstack/drivers/device/usb_storage.c
+usbstack/usb_core.c
+usbstack/usb_storage.c
+usbstack/usb_benchmark.c
+#ifdef CPU_PP502x
+target/arm/usb-drv-pp502x.c
#endif
#endif
-
-/* USBOTG */
-#if !defined(SIMULATOR)
-#if CONFIG_USBOTG == USBOTG_ISP1362
-drivers/isp1362.c
-#endif
-#if defined(SANSA_E200) || defined(SANSA_C200) || !defined(BOOTLOADER)
-#if CONFIG_USBOTG == USBOTG_M5636
-drivers/m5636.c
-#elif CONFIG_USBOTG == USBOTG_ARC
-#ifdef HAVE_USBSTACK
-drivers/usb/arcotg_dcd.c
-#else
-drivers/usb/arcotg_udc.c
#endif
-#endif /* CONFIG_USBOTG */
-#endif /* !defined(BOOTLOADER) */
-#endif /* !defined(SIMULATOR) */
/* Other Random Hardware */
#ifdef HAVE_TSC2100
diff --git a/firmware/drivers/usb/arcotg_dcd.c b/firmware/drivers/usb/arcotg_dcd.c
deleted file mode 100644
index c45a790c04..0000000000
--- a/firmware/drivers/usb/arcotg_dcd.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * Based on code from the Linux Target Image Builder from Freescale
- * available at http://www.bitshrine.org/ and
- * http://www.bitshrine.org/gpp/linux-2.6.16-mx31-usb-2.patch
- * Adapted for Rockbox in January 2007
- * Original file: drivers/usb/gadget/arcotg_udc.c
- *
- * USB Device Controller Driver
- * Driver for ARC OTG USB module in the i.MX31 platform, etc.
- *
- * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Based on mpc-udc.h
- * Author: Li Yang (leoli@freescale.com)
- * Jiang Bo (Tanya.jiang@freescale.com)
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include <string.h>
-#include "arcotg_dcd.h"
-
-/*-------------------------------------------------------------------------*/
-
-static struct arcotg_dcd dcd_controller;
-struct usb_response res;
-
-/* datastructes to controll transfers */
-struct dtd dev_td[USB_MAX_PIPES] IBSS_ATTR;
-struct dqh dev_qh[USB_MAX_PIPES] __attribute((aligned (1 << 11))) IBSS_ATTR;
-
-/* shared memory used by rockbox and dcd to exchange data */
-#define BUFFER_SIZE 512
-unsigned char buffer[BUFFER_SIZE] IBSS_ATTR;
-
-/*-------------------------------------------------------------------------*/
-
-/* description of our device driver operations */
-struct usb_dcd_controller_ops arotg_dcd_ops = {
- .enable = usb_arcotg_dcd_enable,
- .disable = usb_arcotg_dcd_disable,
- .set_halt = usb_arcotg_dcd_set_halt,
- .send = usb_arcotg_dcd_send,
- .receive = usb_arcotg_dcd_receive,
- .ep0 = &dcd_controller.endpoints[0],
-};
-
-/* description of our usb controller driver */
-struct usb_controller arcotg_dcd = {
- .name = "arcotg_dcd",
- .type = DEVICE,
- .speed = USB_SPEED_UNKNOWN,
- .init = usb_arcotg_dcd_init,
- .shutdown = usb_arcotg_dcd_shutdown,
- .irq = usb_arcotg_dcd_irq,
- .start = usb_arcotg_dcd_start,
- .stop = usb_arcotg_dcd_stop,
- .controller_ops = (void*)&arotg_dcd_ops,
-};
-
-static struct usb_response response;
-
-/*-------------------------------------------------------------------------*/
-
-/* TODO hmmm */
-
-struct timer {
- unsigned long s;
- unsigned long e;
-};
-
-void
-timer_set(struct timer * timer, unsigned long val)
-{
- timer->s = USEC_TIMER;
- timer->e = timer->s + val + 1;
-}
-
-int
-timer_expired(struct timer * timer)
-{
- unsigned long val = USEC_TIMER;
-
- if (timer->e > timer->s) {
- return !(val >= timer->s && val <= timer->e);
- } else {
- return (val > timer->e && val < timer->s);
- }
-}
-
-#define MAX_PACKET_SIZE USB_MAX_CTRL_PAYLOAD
-
-#define ERROR_TIMEOUT (-3)
-#define ERROR_UNKNOWN (-7)
-
-#define PRIME_TIMER 100000
-#define TRANSFER_TIMER 1000000
-#define RESET_TIMER 5000000
-#define SETUP_TIMER 200000
-
-/*-------------------------------------------------------------------------*/
-
-/* gets called by usb_stack_init() to register
- * this arcotg device controller driver in the
- * stack. */
-void usb_dcd_init(void)
-{
- usb_controller_register(&arcotg_dcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-void usb_arcotg_dcd_init(void)
-{
- struct timer t;
- int i, ep_num = 0;
-
- logf("arcotg_dcd: init");
- memset(&dcd_controller, 0, sizeof(struct arcotg_dcd));
-
- /* setup list of aviable endpoints */
- INIT_LIST_HEAD(&arcotg_dcd.endpoints.list);
-
- for (i = 0; i < USB_MAX_PIPES; i++) {
-
- dcd_controller.endpoints[i].pipe_num = i;
-
- if (i % 2 == 0) {
- dcd_controller.endpoints[i].ep_num = ep_num;
- } else {
- dcd_controller.endpoints[i].ep_num = ep_num;
- ep_num++;
- }
-
- logf("pipe %d -> ep %d %s", dcd_controller.endpoints[i].pipe_num,
- dcd_controller.endpoints[i].ep_num,
- dcd_controller.endpoints[i].name);
-
- if (ep_name[i] != NULL) {
- memcpy(&dcd_controller.endpoints[i].name, ep_name[i],
- sizeof(dcd_controller.endpoints[i].name));
-
- if (i != 0) {
- /* add to list of configurable endpoints */
- list_add_tail(&dcd_controller.endpoints[i].list,
- &arcotg_dcd.endpoints.list);
- }
- }
- }
-
- /* ep0 is special */
- arcotg_dcd.ep0 = &dcd_controller.endpoints[0];
- arcotg_dcd.ep0->maxpacket = USB_MAX_CTRL_PAYLOAD;
-
- /* stop */
- UDC_USBCMD &= ~USB_CMD_RUN;
-
- udelay(50000);
- timer_set(&t, RESET_TIMER);
-
- /* reset */
- UDC_USBCMD |= USB_CMD_CTRL_RESET;
-
- while ((UDC_USBCMD & USB_CMD_CTRL_RESET)) {
- if (timer_expired(&t)) {
- logf("TIMEOUT->init");
- }
- }
-
- /* put controller in device mode */
- UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
-
- /* init queue heads */
- qh_init(0, USB_RECV, USB_ENDPOINT_XFER_CONTROL, USB_MAX_CTRL_PAYLOAD, 0, 0);
- qh_init(0, USB_SEND, USB_ENDPOINT_XFER_CONTROL, USB_MAX_CTRL_PAYLOAD, 0, 0);
-
- UDC_ENDPOINTLISTADDR = (unsigned int)dev_qh;
-}
-
-void usb_arcotg_dcd_shutdown(void)
-{
-
-}
-
-void usb_arcotg_dcd_start(void)
-{
- logf("start");
-
- /* clear stopped bit */
- dcd_controller.stopped = false;
-
- UDC_USBCMD |= USB_CMD_RUN;
-}
-
-void usb_arcotg_dcd_stop(void)
-{
- logf("stop");
-
- /* set stopped bit */
- dcd_controller.stopped = true;
-
- UDC_USBCMD &= ~USB_CMD_RUN;
-}
-
-void usb_arcotg_dcd_irq(void)
-{
- if (dcd_controller.stopped == true) {
- return;
- }
-
- /* check if we need to wake up from suspend */
- if (!(UDC_USBSTS & USB_STS_SUSPEND) && dcd_controller.resume_state) {
- resume_int();
- }
-
- /* USB Interrupt */
- if (UDC_USBSTS & USB_STS_INT) {
-
- /* setup packet, we only support ep0 as control ep */
- if (UDC_ENDPTSETUPSTAT & EP_SETUP_STATUS_EP0) {
- /* copy data from queue head to local buffer */
- memcpy(&dcd_controller.local_setup_buff,
- (uint8_t *) &dev_qh[0].setup_buffer, 8);
-
- /* ack setup packet */
- UDC_ENDPTSETUPSTAT = UDC_ENDPTSETUPSTAT;
- setup_received_int(&dcd_controller.local_setup_buff);
- }
-
- if (UDC_ENDPTCOMPLETE) {
- dtd_complete();
- }
- }
-
- if (UDC_USBSTS & USB_STS_PORT_CHANGE) {
- port_change_int();
- }
-
- if (UDC_USBSTS & USB_STS_SUSPEND) {
- suspend_int();
- }
-
- if (UDC_USBSTS & USB_STS_RESET) {
- reset_int();
- }
-
- if (UDC_USBSTS & USB_STS_ERR) {
- logf("!!! error !!!");
- }
-
- if (UDC_USBSTS & USB_STS_SYS_ERR) {
- logf("!!! sys error !!!");
- }
-}
-
-/*-------------------------------------------------------------------------*/
-/* interrupt handlers */
-
-static void setup_received_int(struct usb_ctrlrequest* request)
-{
- int error = 0;
- uint8_t address = 0;
- bool set_config = false;
- int handled = 0; /* set to zero if we do not handle the message, */
- /* and should pass it to the driver */
-
- into_usb_ctrlrequest(request);
-
- /* handle all requests we support */
- switch (request->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
-
- switch (request->bRequest) {
- case USB_REQ_SET_ADDRESS:
- /* store address as we need to ack before setting it */
- address = (uint8_t)request->wValue;
-
- handled = 1;
- break;
-
- case USB_REQ_SET_CONFIGURATION:
- set_config = true;
- break;
-
- case USB_REQ_GET_STATUS:
- response.buf = &dcd_controller.usb_state;
- response.length = 2;
-
- handled = usb_arcotg_dcd_send(NULL, &response);
- break;
- }
-
- case USB_REQ_CLEAR_FEATURE:
- case USB_REQ_SET_FEATURE:
- if (request->bRequestType != USB_RECIP_ENDPOINT) {
- break;
- }
-
- int dir = (request->wIndex & 0x0080) ? EP_DIR_IN : EP_DIR_OUT;
- int num = (request->wIndex & 0x000f);
- struct usb_ep *ep;
-
- if (request->wValue != 0 ||
- request->wLength != 0 ||
- (num * 2 + dir) > USB_MAX_PIPES) {
- break;
- }
- ep = &dcd_controller.endpoints[num * 2 + dir];
-
- if (request->bRequest == USB_REQ_SET_FEATURE) {
- logf("HALT");
- handled = usb_arcotg_dcd_set_halt(ep, true);
- } else {
- logf("UNHALT");
- handled = usb_arcotg_dcd_set_halt(ep, false);
- }
-
- if (handled == 0) {
- handled = 1; /* dont pass it to driver */
- }
-
- break;
- }
-
- /* if dcd can not handle reqeust, ask driver */
- if (handled == 0) {
- if (arcotg_dcd.device_driver != NULL &&
- arcotg_dcd.device_driver->request != NULL) {
- handled = arcotg_dcd.device_driver->request(request);
- logf("result from driver %d", handled);
- }
- }
-
- if (handled <= 0) {
- error = handled;
- }
-
- /* ack transfer */
- usb_ack(request, error);
-
- /* set address and usb state after USB_REQ_SET_ADDRESS */
- if (address != 0) {
- logf("setting address to %d", address);
- UDC_DEVICEADDR = address << 25;
- dcd_controller.usb_state = USB_STATE_ADDRESS;
- }
-
- /* update usb state after successfull USB_REQ_SET_CONFIGURATION */
- if (set_config) {
- if (handled > 0) {
- dcd_controller.usb_state = USB_STATE_CONFIGURED;
- }
- }
-}
-
-static void port_change_int(void)
-{
- uint32_t tmp;
- enum usb_device_speed speed = USB_SPEED_UNKNOWN;
-
- /* bus resetting is finished */
- if (!(UDC_PORTSC1 & PORTSCX_PORT_RESET)) {
- /* Get the speed */
- tmp = (UDC_PORTSC1 & PORTSCX_PORT_SPEED_MASK);
- switch (tmp) {
- case PORTSCX_PORT_SPEED_HIGH:
- speed = USB_SPEED_HIGH;
- break;
- case PORTSCX_PORT_SPEED_FULL:
- speed = USB_SPEED_FULL;
- break;
- case PORTSCX_PORT_SPEED_LOW:
- speed = USB_SPEED_LOW;
- break;
- default:
- speed = USB_SPEED_UNKNOWN;
- break;
- }
- }
-
- if (arcotg_dcd.speed == speed) {
- return;
- }
-
- /* update speed */
- arcotg_dcd.speed = speed;
-
- /* update USB state */
- if (!dcd_controller.resume_state) {
- dcd_controller.usb_state = USB_STATE_DEFAULT;
- }
-
- /* inform device driver */
- if (arcotg_dcd.device_driver != NULL &&
- arcotg_dcd.device_driver->speed != NULL) {
- arcotg_dcd.device_driver->speed(speed);
- }
-}
-
-static void dtd_complete(void) {
-
- uint32_t bit_pos;
- int i, ep_num, direction, bit_mask /*, status*/;
-
- /* clear the bits in the register */
- bit_pos = UDC_ENDPTCOMPLETE;
- UDC_ENDPTCOMPLETE = bit_pos;
-
- if (!bit_pos) {
- return;
- }
-
- for (i = 0; i < USB_MAX_ENDPOINTS * 2; i++) {
- ep_num = i >> 1;
- direction = i % 2;
-
- bit_mask = 1 << (ep_num + 16 * direction);
-
- if (!(bit_pos & bit_mask)) {
- continue;
- }
-
- logf(" ");
- logf("TRAFFIC");
- logf(" -> on ep %d dir %d", i, direction);
- }
-}
-
-static void suspend_int(void)
-{
- dcd_controller.resume_state = dcd_controller.usb_state;
- dcd_controller.usb_state = USB_STATE_SUSPENDED;
-
- /* report suspend to the driver */
- if (arcotg_dcd.device_driver != NULL &&
- arcotg_dcd.device_driver->suspend != NULL) {
- arcotg_dcd.device_driver->suspend();
- }
-}
-
-static void resume_int(void)
-{
- dcd_controller.usb_state = dcd_controller.resume_state;
- dcd_controller.resume_state = USB_STATE_NOTATTACHED;
-
- /* report resume to the driver */
- if (arcotg_dcd.device_driver != NULL &&
- arcotg_dcd.device_driver->resume != NULL) {
- arcotg_dcd.device_driver->resume();
- }
-}
-
-static void reset_int(void)
-{
- /* clear device address */
- UDC_DEVICEADDR = 0 << 25;
-
- /* update usb state */
- dcd_controller.usb_state = USB_STATE_DEFAULT;
-
- UDC_ENDPTSETUPSTAT = UDC_ENDPTSETUPSTAT;
- UDC_ENDPTCOMPLETE = UDC_ENDPTCOMPLETE;
-
- /* prime and flush pending transfers */
- while (UDC_ENDPTPRIME);
- UDC_ENDPTFLUSH = ~0;
-
- if ((UDC_PORTSC1 & PORTSCX_PORT_RESET) == 0) {
- logf("TIMEOUT->port");
- }
-
- /* clear USB Reset status bit */
- UDC_USBSTS |= USB_STS_RESET;
-}
-
-/*-------------------------------------------------------------------------*/
-/* usb controller ops */
-
-int usb_arcotg_dcd_enable(struct usb_ep* ep,
- struct usb_endpoint_descriptor* desc)
-{
- unsigned short max = 0;
- unsigned char mult = 0, zlt = 0;
- int retval = 0;
- char *val = NULL; /* for debug */
-
- /* catch bogus parameter */
- if (!ep) {
- return -EINVAL;
- }
-
- max = desc->wMaxPacketSize;
- retval = -EINVAL;
-
- /* check the max package size validate for this endpoint
- * Refer to USB2.0 spec table 9-13, */
- switch (desc->bmAttributes & 0x03) {
- case USB_ENDPOINT_XFER_BULK:
- if (strstr(ep->name, "-iso") || strstr(ep->name, "-int")) {
- goto en_done;
- }
- mult = 0;
- zlt = 1;
-
- switch (arcotg_dcd.speed) {
- case USB_SPEED_HIGH:
- if ((max == 128) || (max == 256) || (max == 512)) {
- break;
- }
- default:
- switch (max) {
- case 4:
- case 8:
- case 16:
- case 32:
- case 64:
- break;
- default:
- case USB_SPEED_LOW:
- goto en_done;
- }
- }
- break;
-
- case USB_ENDPOINT_XFER_INT:
- if (strstr(ep->name, "-iso")) { /* bulk is ok */
- goto en_done;
- }
- mult = 0;
- zlt = 1;
-
- switch (arcotg_dcd.speed) {
- case USB_SPEED_HIGH:
- if (max <= 1024) {
- break;
- }
- case USB_SPEED_FULL:
- if (max <= 64) {
- break;
- }
- default:
- if (max <= 8) {
- break;
- }
- goto en_done;
- }
- break;
-
- case USB_ENDPOINT_XFER_ISOC:
- if (strstr(ep->name, "-bulk") || strstr(ep->name, "-int")) {
- goto en_done;
- }
- mult = (unsigned char) (1 +((desc->wMaxPacketSize >> 11) & 0x03));
- zlt = 0;
-
- switch (arcotg_dcd.speed) {
- case USB_SPEED_HIGH:
- if (max <= 1024) {
- break;
- }
- case USB_SPEED_FULL:
- if (max <= 1023) {
- break;
- }
- default:
- goto en_done;
- }
- break;
-
- case USB_ENDPOINT_XFER_CONTROL:
- if (strstr(ep->name, "-iso") || strstr(ep->name, "-int")) {
- goto en_done;
- }
- mult = 0;
- zlt = 1;
-
- switch (arcotg_dcd.speed) {
- case USB_SPEED_HIGH:
- case USB_SPEED_FULL:
- switch (max) {
- case 1:
- case 2:
- case 4:
- case 8:
- case 16:
- case 32:
- case 64:
- break;
- default:
- goto en_done;
- }
- case USB_SPEED_LOW:
- switch (max) {
- case 1:
- case 2:
- case 4:
- case 8:
- break;
- default:
- goto en_done;
- }
- default:
- goto en_done;
- }
- break;
-
- default:
- goto en_done;
- }
-
-
- /* here initialize variable of ep */
- ep->maxpacket = max;
- ep->desc = desc;
-
- /* hardware special operation */
-
- /* Init EPx Queue Head (Ep Capabilites field in QH
- * according to max, zlt, mult) */
- qh_init(ep->ep_num,
- (desc->bEndpointAddress & USB_DIR_IN) ? USB_RECV : USB_SEND,
- (unsigned char) (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK),
- max, zlt, mult);
-
- /* Init endpoint x at here */
- ep_setup(ep->ep_num,
- (unsigned char)(desc->bEndpointAddress & USB_DIR_IN) ?
- USB_RECV : USB_SEND,
- (unsigned char)(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
-
- /* Now HW will be NAKing transfers to that EP,
- * until a buffer is queued to it. */
-
- retval = 0;
- switch (desc->bmAttributes & 0x03) {
- case USB_ENDPOINT_XFER_BULK:
- val = "bulk";
- break;
- case USB_ENDPOINT_XFER_ISOC:
- val = "iso";
- break;
- case USB_ENDPOINT_XFER_INT:
- val = "intr";
- break;
- default:
- val = "ctrl";
- break;
- }
-
- logf("ep num %d", (int)ep->ep_num);
-
- logf("enabled %s (ep%d%s-%s)", ep->name,
- desc->bEndpointAddress & 0x0f,
- (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", val);
- logf(" maxpacket %d", max);
-
-en_done:
- return retval;
-}
-
-int usb_arcotg_dcd_disable(struct usb_ep* ep)
-{
- if (ep == NULL || ep->desc == NULL) {
- logf("failed to disabled %s", ep ? ep->name : NULL);
- return -EINVAL;
- }
-
- ep->desc = NULL;
-
- logf("disabled %s", ep->name);
- return 0;
-}
-
-int usb_arcotg_dcd_set_halt(struct usb_ep* ep, bool halt)
-{
- int status = -EOPNOTSUPP; /* operation not supported */
- unsigned char dir = 0;
- unsigned int tmp_epctrl = 0;
-
- if (!ep) {
- status = -EINVAL;
- goto out;
- }
-
- if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
- status = -EOPNOTSUPP;
- goto out;
- }
-
- dir = ep_is_in(ep) ? USB_RECV : USB_SEND;
-
- logf("modify halt of %d", ep->ep_num);
- tmp_epctrl = UDC_ENDPTCTRL(ep->ep_num);
- logf("reg %x", tmp_epctrl);
-
- if (halt) {
- logf("halting...");
- /* set the stall bit */
- if (dir) {
- logf("..tx..");
- tmp_epctrl |= EPCTRL_TX_EP_STALL;
- } else {
- logf("..rx..");
- tmp_epctrl |= EPCTRL_RX_EP_STALL;
- }
- } else {
- logf("UNhalting...");
- /* clear the stall bit and reset data toggle */
- if (dir) {
- logf("..tx..");
- tmp_epctrl &= ~EPCTRL_TX_EP_STALL;
- tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
- } else {
- logf("..rx..");
- tmp_epctrl &= ~EPCTRL_RX_EP_STALL;
- tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
- }
- }
- UDC_ENDPTCTRL(ep->ep_num) = tmp_epctrl;
- logf("reg %x", tmp_epctrl);
-
-out:
- logf("%s %s halt", ep->name, halt ? "set" : "clear");
- return 0;
-}
-
-int usb_arcotg_dcd_send(struct usb_ep* ep, struct usb_response* res)
-{
- char* ptr;
- int todo, error, size, done = 0;
- int index = 1; /* use as default ep0 tx qh and td */
- struct dtd* td;
- struct dqh* qh;
- unsigned int mask;
-
- if (res == NULL) {
- logf("invalid input");
- return -EINVAL;
- }
-
- if (ep != NULL) {
- index = ep->pipe_num;
- }
-
- ptr = res->buf;
- size = res->length;
-
- td = &dev_td[index];
- qh = &dev_qh[index];
- mask = 1 << (15 + index);
-
- do {
- /* calculate how much to copy and send */
- todo = MIN(size, BUFFER_SIZE);
-
- /* copy data to shared memory area */
- memcpy(buffer, ptr, todo);
-
- /* init transfer descriptor */
- td_init(td, buffer, todo);
-
- /* start transfer*/
- error = td_enqueue(td, qh, mask);
-
- if (error == 0) {
- /* waiting for finished transfer */
- error = td_wait(td, mask);
- }
-
- if (error) {
- done = error;
- break;
- }
-
- size -= todo;
- ptr += todo;
- done += todo;
-
- } while (size > 0);
-
- logf("usb_send done %d",done);
- return done;
-}
-
-int usb_arcotg_dcd_receive(struct usb_ep* ep, struct usb_response* res)
-{
- char* ptr;
- int todo, error, size, done = 0;
- int index = 0; /* use as default ep0 rx qh and td */
- struct dtd* td;
- struct dqh* qh;
- unsigned int mask;
-
- if (res == NULL) {
- logf("invalid input");
- return -EINVAL;
- }
-
- if (ep != NULL) {
- index = ep->pipe_num;
- }
-
- ptr = res->buf;
- size = res->length;
-
- td = &dev_td[index];
- qh = &dev_qh[index];
- mask = 1 << index;
-
- do {
- /* calculate how much to receive in one step */
- todo = MIN(size, BUFFER_SIZE);
-
- /* init transfer descritpor */
- td_init(td, buffer, size);
-
- /* start transfer */
- error = td_enqueue(td, qh, mask);
-
- if (error == 0) {
- /* wait until transfer is finished */
- error = td_wait(td, mask);
- }
-
- if (error) {
- done = error;
- break;
- }
-
- /* copy receive data to buffer */
- memcpy(ptr, buffer, todo);
-
- size -= todo;
- ptr += todo;
- done += todo;
-
- } while (size > 0);
-
- logf("usb_recive done %d",done);
- return done;
-}
-
-/*-------------------------------------------------------------------------*/
-/* lifecylce */
-
-static void qh_init(unsigned char ep_num, unsigned char dir,
- unsigned char ep_type, unsigned int max_pkt_len,
- unsigned int zlt, unsigned char mult)
-{
- struct dqh *qh = &dev_qh[2 * ep_num + dir];
- uint32_t tmp = 0;
- memset(qh, 0, sizeof(struct dqh));
-
- /* set the Endpoint Capabilites Reg of QH */
- switch (ep_type) {
- case USB_ENDPOINT_XFER_CONTROL:
- /* Interrupt On Setup (IOS). for control ep */
- tmp = (max_pkt_len << LENGTH_BIT_POS) | INTERRUPT_ON_COMPLETE;
- break;
- case USB_ENDPOINT_XFER_ISOC:
- tmp = (max_pkt_len << LENGTH_BIT_POS) |
- (mult << EP_QUEUE_HEAD_MULT_POS);
- break;
- case USB_ENDPOINT_XFER_BULK:
- case USB_ENDPOINT_XFER_INT:
- tmp = max_pkt_len << LENGTH_BIT_POS;
- if (zlt) {
- tmp |= EP_QUEUE_HEAD_ZLT_SEL;
- }
- break;
- default:
- logf("error ep type is %d", ep_type);
- return;
- }
-
- /* see 32.14.4.1 Queue Head Initialization */
-
- /* write the wMaxPacketSize field as required by the USB Chapter9 or
- application specific portocol */
- qh->endpt_cap = tmp;
-
- /* write the next dTD Terminate bit fild to 1 */
- qh->dtd_ovrl.next_dtd = 1;
-
- /* write the Active bit in the status field to 0 */
- qh->dtd_ovrl.dtd_token &= ~STATUS_ACTIVE;
-
- /* write the Hald bit in the status field to 0 */
- qh->dtd_ovrl.dtd_token &= ~STATUS_HALTED;
-
- logf("qh: init %d", (2 * ep_num + dir));
-}
-
-static void td_init(struct dtd* td, void* buffer, uint32_t todo)
-{
- /* see 32.14.5.2 Building a Transfer Descriptor */
-
- /* init first 7 dwords with 0 */
- memset(td, 0, sizeof(struct dtd)); /* set set all to 0 */
-
- /* set terminate bit to 1*/
- td->next_dtd = 1;
-
- /* fill in total bytes with transfer size */
- td->dtd_token = (todo << 16);
-
- /* set interrupt on compilte if desierd */
- td->dtd_token |= INTERRUPT_ON_COMPLETE;
-
- /* initialize the status field with the active bit set to 1 and all
- remaining status bits to 0 */
- td->dtd_token |= STATUS_ACTIVE;
-
- td->buf_ptr0 = (uint32_t)buffer;
-}
-
-static void ep_setup(unsigned char ep_num, unsigned char dir,
- unsigned char ep_type)
-{
- unsigned int tmp_epctrl = 0;
- struct timer t;
-
- tmp_epctrl = UDC_ENDPTCTRL(ep_num);
- if (dir) {
- if (ep_num) {
- tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
- }
- logf("tx enablde");
- tmp_epctrl |= EPCTRL_TX_ENABLE;
- tmp_epctrl |= ((unsigned int)(ep_type) << EPCTRL_TX_EP_TYPE_SHIFT);
- } else {
- if (ep_num) {
- tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
- }
- logf("rx enablde");
- tmp_epctrl |= EPCTRL_RX_ENABLE;
- tmp_epctrl |= ((unsigned int)(ep_type) << EPCTRL_RX_EP_TYPE_SHIFT);
- }
-
- UDC_ENDPTCTRL(ep_num) = tmp_epctrl;
-
- /* wait for the write reg to finish */
-
- timer_set(&t, SETUP_TIMER);
- while (!(UDC_ENDPTCTRL(ep_num) &
- (tmp_epctrl & (EPCTRL_TX_ENABLE | EPCTRL_RX_ENABLE)))) {
- if (timer_expired(&t)) {
- logf("TIMEOUT: enable ep");
- return;
- }
- }
-}
-
-/*-------------------------------------------------------------------------*/
-/* helpers for sending/receiving */
-
-static int td_enqueue(struct dtd* td, struct dqh* qh, unsigned int mask)
-{
- struct timer t;
-
- qh->dtd_ovrl.next_dtd = (unsigned int)td;
- qh->dtd_ovrl.dtd_token &= ~0xc0;
-
- timer_set(&t, PRIME_TIMER);
- UDC_ENDPTPRIME |= mask;
-
- while ((UDC_ENDPTPRIME & mask)) {
- if (timer_expired(&t)) {
- logf("timeout->prime");
- }
- }
-
- if ((UDC_ENDPTSTAT & mask) == 0) {
- logf("Endptstat 0x%x", UDC_ENDPTSTAT);
- logf("HW_ERROR");
- }
-
- return 0;
-}
-
-static int td_wait(struct dtd* td, unsigned int mask)
-{
- struct timer t;
- timer_set(&t, TRANSFER_TIMER);
-
- for (;;) {
- if ((UDC_ENDPTCOMPLETE & mask) != 0) {
- UDC_ENDPTCOMPLETE |= mask;
- }
-
- if ((td->dtd_token & (1 << 7)) == 0) {
- return 0;
- }
-
- if (timer_expired(&t)) {
- return ERROR_TIMEOUT;
- }
- }
-}
-
-static int usb_ack(struct usb_ctrlrequest * s, int error)
-{
- if (error) {
- logf("STALLing ep0");
- UDC_ENDPTCTRL0 |= 1 << 16; /* stall */
- return 0;
- }
-
- res.buf = NULL;
- res.length = 0;
-
- if (s->bRequestType & 0x80) {
- return usb_arcotg_dcd_receive(NULL, &res);
- } else {
- return usb_arcotg_dcd_send(NULL, &res);
- }
-}
diff --git a/firmware/drivers/usb/arcotg_dcd.h b/firmware/drivers/usb/arcotg_dcd.h
deleted file mode 100644
index 79f03f1bcc..0000000000
--- a/firmware/drivers/usb/arcotg_dcd.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * Based on code from the Linux Target Image Builder from Freescale
- * available at http://www.bitshrine.org/ and
- * http://www.bitshrine.org/gpp/linux-2.6.16-mx31-usb-2.patch
- * Adapted for Rockbox in January 2007
- * Original file: drivers/usb/gadget/arcotg_udc.c
- *
- * USB Device Controller Driver
- * Driver for ARC OTG USB module in the i.MX31 platform, etc.
- *
- * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Based on mpc-udc.h
- * Author: Li Yang (leoli@freescale.com)
- * Jiang Bo (Tanya.jiang@freescale.com)
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#ifndef _ARCOTG_DCD_H_
-#define _ARCOTG_DCD_H_
-
-#include "usbstack/core.h"
-#include "arcotg_udc.h"
-
-/*-------------------------------------------------------------------------*/
-
-#define ep_is_in(EP) (((EP)->desc->bEndpointAddress & USB_DIR_IN)==USB_DIR_IN)
-
-#define EP_DIR_IN 1
-#define EP_DIR_OUT 0
-
-/*-------------------------------------------------------------------------*/
-
-/* pipe direction macro from device view */
-#define USB_RECV (0) /* OUT EP */
-#define USB_SEND (1) /* IN EP */
-
-/* Shared Bit Masks for Endpoint Queue Head and Endpoint Transfer Descriptor */
-#define TERMINATE (1 << 0)
-#define STATUS_ACTIVE (1 << 7)
-#define STATUS_HALTED (1 << 6)
-#define STATUS_DATA_BUFF_ERR (1 << 5)
-#define STATUS_TRANSACTION_ERR (1 << 4)
-#define INTERRUPT_ON_COMPLETE (1 << 15)
-#define LENGTH_BIT_POS (16)
-#define ADDRESS_MASK (0xFFFFFFE0)
-#define ERROR_MASK (DTD_STATUS_HALTED | \
- DTD_STATUS_DATA_BUFF_ERR | \
- DTD_STATUS_TRANSACTION_ERR)
-
-#define RESERVED_FIELDS ((1 << 0) | (1 << 2) | (1 << 4) | \
- (1 << 8) | (1 << 9) | (1 << 12)| \
- (1 << 13)| (1 << 14)| (1 << 31))
-
-/* Endpoint Queue Head Bit Masks */
-#define EP_QUEUE_HEAD_MULT_POS (30)
-#define EP_QUEUE_HEAD_ZLT_SEL (0x20000000)
-#define EP_QUEUE_HEAD_MAX_PKT_LEN(ep_info) (((ep_info)>>16)&0x07ff)
-#define EP_QUEUE_HEAD_MULTO (0x00000C00)
-#define EP_QUEUE_CURRENT_OFFSET_MASK (0x00000FFF)
-#define EP_QUEUE_FRINDEX_MASK (0x000007FF)
-#define EP_MAX_LENGTH_TRANSFER (0x4000)
-
-/*-------------------------------------------------------------------------*/
-
-/* ep name is important, it should obey the convention of ep_match() */
-/* even numbered EPs are OUT or setup, odd are IN/INTERRUPT */
-static const char* ep_name[] = {
- "ep0-control", NULL, /* everyone has ep0 */
- /* 7 configurable endpoints */
- "ep1out",
- "ep1in",
- "ep2out",
- "ep2in",
- "ep3out",
- "ep3in",
- "ep4out",
- "ep4in",
- "ep5out",
- "ep5in",
- "ep6out",
- "ep6in",
- "ep7out",
- "ep7in"
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* Endpoint Transfer Descriptor data struct */
-struct dtd {
- uint32_t next_dtd; /* Next TD pointer(31-5),
- T(0) set indicate invalid */
- uint32_t dtd_token; /* Total bytes (30-16), IOC (15),
- MultO(11-10), STS (7-0) */
- uint32_t buf_ptr0; /* Buffer pointer Page 0 */
- uint32_t buf_ptr1; /* Buffer pointer Page 1 */
- uint32_t buf_ptr2; /* Buffer pointer Page 2 */
- uint32_t buf_ptr3; /* Buffer pointer Page 3 */
- uint32_t buf_ptr4; /* Buffer pointer Page 4 */
- uint32_t res; /* make it an even 8 words */
-} __attribute((packed));
-
-/* Endpoint Queue Head*/
-struct dqh {
- uint32_t endpt_cap; /* Mult(31-30) , Zlt(29) , Max Pkt len
- * and IOS(15) */
- uint32_t cur_dtd; /* Current dTD Pointer(31-5) */
- struct dtd dtd_ovrl; /* Transfer descriptor */
- uint32_t setup_buffer[2]; /* Setup data 8 bytes */
- uint32_t res2[4]; /* pad out to 64 bytes */
-} __attribute((packed));
-
-#define RESPONSE_SIZE 30
-
-/* our controller struct */
-struct arcotg_dcd {
- struct usb_ctrlrequest local_setup_buff;
- struct usb_ep endpoints[USB_MAX_PIPES];
- struct usb_response response[RESPONSE_SIZE];
- enum usb_device_state usb_state;
- enum usb_device_state resume_state;
- bool stopped;
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* usb_controller functions */
-void usb_arcotg_dcd_init(void);
-void usb_arcotg_dcd_shutdown(void);
-void usb_arcotg_dcd_irq(void);
-void usb_arcotg_dcd_start(void);
-void usb_arcotg_dcd_stop(void);
-
-/* usb controller ops */
-int usb_arcotg_dcd_enable(struct usb_ep* ep,
- struct usb_endpoint_descriptor* desc);
-int usb_arcotg_dcd_disable(struct usb_ep* ep);
-int usb_arcotg_dcd_set_halt(struct usb_ep* ep, bool halt);
-int usb_arcotg_dcd_send(struct usb_ep* ep, struct usb_response* request);
-int usb_arcotg_dcd_receive(struct usb_ep* ep, struct usb_response* res);
-
-/* interrupt handlers */
-static void setup_received_int(struct usb_ctrlrequest* request);
-static void port_change_int(void);
-static void dtd_complete(void);
-static void reset_int(void);
-static void suspend_int(void);
-static void resume_int(void);
-
-/* life cycle */
-static void qh_init(unsigned char ep_num, unsigned char dir,
- unsigned char ep_type, unsigned int max_pkt_len,
- unsigned int zlt, unsigned char mult);
-static void td_init(struct dtd* td, void* buffer, uint32_t todo);
-static void ep_setup(unsigned char ep_num, unsigned char dir,
- unsigned char ep_type);
-
-/* helpers for tx/rx */
-static int td_enqueue(struct dtd* td, struct dqh* qh, unsigned int mask);
-static int td_wait(struct dtd* td, unsigned int mask);
-static int usb_ack(struct usb_ctrlrequest * s, int error);
-
-#endif /*_ARCOTG_DCD_H_*/
diff --git a/firmware/drivers/usb/arcotg_udc.c b/firmware/drivers/usb/arcotg_udc.c
deleted file mode 100644
index c4ae6f8d64..0000000000
--- a/firmware/drivers/usb/arcotg_udc.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Barry Wardell
- *
- * Based on code from the Linux Target Image Builder from Freescale
- * available at http://www.bitshrine.org/ and
- * http://www.bitshrine.org/gpp/linux-2.6.16-mx31-usb-2.patch
- * Adapted for Rockbox in January 2007
- * Original file: drivers/usb/gadget/arcotg_udc.c
- *
- * USB Device Controller Driver
- * Driver for ARC OTG USB module in the i.MX31 platform, etc.
- *
- * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Based on mpc-udc.h
- * Author: Li Yang (leoli@freescale.com)
- * Jiang Bo (Tanya.jiang@freescale.com)
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-#include "arcotg_udc.h"
-#include "logf.h"
-#include "errno.h"
-
-static int timeout;
-
-/* @qh_addr is the aligned virt addr of ep QH addr
- * it is used to set endpointlistaddr Reg */
-/* was static int dr_controller_setup(void *qh_addr) */
-int dr_controller_setup(void)
-{
-#if 0
- struct arc_usb_config *config;
-
- config = udc_controller->config;
-
- /* before here, make sure usb_slave_regs has been initialized */
- if (!qh_addr)
- return -EINVAL;
-#endif
-
- /* Stop and reset the usb controller */
- UDC_USBCMD &= ~USB_CMD_RUN;
-
- UDC_USBCMD |= USB_CMD_CTRL_RESET;
-
- /* Wait for reset to complete */
- timeout = 10000000;
- while ((UDC_USBCMD & USB_CMD_CTRL_RESET) &&
- --timeout) {
- continue;
- }
- if (timeout == 0) {
- logf("%s: TIMEOUT", __FUNCTION__);
- return -ETIMEDOUT;
- }
-
- /* Set the controller as device mode and disable setup lockout */
- UDC_USBMODE |= (USB_MODE_CTRL_MODE_DEVICE | USB_MODE_SETUP_LOCK_OFF);
-
- /* Clear the setup status */
- UDC_USBSTS = 0;
-#if 0
- UDC_ENDPOINTLISTADDR = (unsigned int)qh_addr & USB_EP_LIST_ADDRESS_MASK;
-
- VDBG("qh_addr=0x%x epla_reg=0x%8x", qh_addr, UOG_ASYNCLISTADDR);
-#endif
- UDC_PORTSC1 = (UDC_PORTSC1 & ~PORTSCX_PHY_TYPE_SEL) | PORTSCX_PTS_UTMI;
-#if 0
- if (config->set_vbus_power)
- config->set_vbus_power(0);
-#endif
-
- return 0;
-}
-
-/* just Enable DR irq reg and Set Dr controller Run */
-/* was static void dr_controller_run(struct arcotg_udc *udc) */
-void dr_controller_run(void)
-{
- /*Enable DR irq reg */
- UDC_USBINTR = USB_INTR_INT_EN | USB_INTR_ERR_INT_EN |
- USB_INTR_PTC_DETECT_EN | USB_INTR_RESET_EN |
- USB_INTR_DEVICE_SUSPEND | USB_INTR_SYS_ERR_EN;
-#if 0
- /* Clear stopped bit */
- udc->stopped = 0;
-#endif
- /* Set the controller as device mode */
- UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
-
- /* Set controller to Run */
- UDC_USBCMD |= USB_CMD_RUN;
-
- return;
-}
-
-/* just Enable DR irq reg and Set Dr controller Run */
-/* was static void dr_controller_stop(struct arcotg_udc *udc) */
-void dr_controller_stop(void)
-{
-#if 0
- /* if we're in OTG mode, and the Host is currently using the port,
- * stop now and don't rip the controller out from under the
- * ehci driver
- */
- if (udc->gadget.is_otg) {
- if (!(UDC_OTGSC & OTGSC_STS_USB_ID)) {
- logf("Leaving early");
- return;
- }
- }
-#endif
-
- /* disable all INTR */
- UDC_USBINTR = 0;
-#if 0
- /* Set stopped bit */
- udc->stopped = 1;
-#endif
- /* Set controller to Stop */
- UDC_USBCMD &= ~USB_CMD_RUN;
-}
diff --git a/firmware/export/arcotg_udc.h b/firmware/export/arcotg_udc.h
deleted file mode 100644
index e016321b37..0000000000
--- a/firmware/export/arcotg_udc.h
+++ /dev/null
@@ -1,318 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Barry Wardell
- *
- * ARC OTG USB device driver based on code from the Linux Target Image Builder
- * from Freescale - http://www.bitshrine.org/ and
- * http://www.bitshrine.org/gpp/linux-2.6.16-mx31-usb-2.patch
- * Adapted for Rockbox in January 2007
- * Original file: drivers/usb/gadget/arcotg_udc.h
- *
- * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Based on mpc-udc.h
- * Author: Li Yang (leoli@freescale.com)
- * Jiang Bo (Tanya.jiang@freescale.com)
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-/*
- * Freescale USB device/endpoint management registers
- */
-#ifndef __ARCOTG_UDC_H
-#define __ARCOTG_UDC_H
-
-#include "cpu.h"
-
-#define USB_MAX_ENDPOINTS 8
-#define USB_MAX_PIPES (USB_MAX_ENDPOINTS*2)
-#define USB_MAX_CTRL_PAYLOAD 64
-
-/* USB DR device mode registers (Little Endian) */
-/* Identification registers */
-#define UDC_ID (*(volatile unsigned int *)(USB_BASE+0x000))
-#define UDC_HWGENERAL (*(volatile unsigned int *)(USB_BASE+0x004))
-#define UDC_HWHOST (*(volatile unsigned int *)(USB_BASE+0x008))
-#define UDC_HWTXBUF (*(volatile unsigned int *)(USB_BASE+0x010))
-#define UDC_HWRXBUF (*(volatile unsigned int *)(USB_BASE+0x014))
-
-/* Capability registers */
-#define UDC_CAPLENGTH (*(volatile unsigned char *)(USB_BASE+0x100)) /* Capability Register Length */
-#define UDC_HCIVERSION (*(volatile unsigned short *)(USB_BASE+0x102)) /* Host Controller Interface Version */
-#define UDC_HCSPARAMS (*(volatile unsigned int *)(USB_BASE+0x104)) /* Host Controller Structual Parameters */
-#define UDC_HCCPARAMS (*(volatile unsigned int *)(USB_BASE+0x108)) /* Host Controller Capability Parameters */
-#define UDC_DCIVERSION (*(volatile unsigned short *)(USB_BASE+0x120)) /* Device Controller Interface Version */
-#define UDC_DCCPARAMS (*(volatile unsigned int *)(USB_BASE+0x124)) /* Device Controller Capability Parameters */
-
-/* Operation registers */
-#define UDC_USBCMD (*(volatile unsigned int *)(USB_BASE+0x140)) /* USB Command Register */
-#define UDC_USBSTS (*(volatile unsigned int *)(USB_BASE+0x144)) /* USB Status Register */
-#define UDC_USBINTR (*(volatile unsigned int *)(USB_BASE+0x148)) /* USB Interrupt Enable Register */
-#define UDC_FRINDEX (*(volatile unsigned int *)(USB_BASE+0x14c)) /* Frame Index Register */
-#define UDC_DEVICEADDR (*(volatile unsigned int *)(USB_BASE+0x154)) /* Device Address */
-#define UDC_ENDPOINTLISTADDR (*(volatile unsigned int *)(USB_BASE+0x158)) /* Endpoint List Address Register */
-#define UDC_BURSTSIZE (*(volatile unsigned int *)(USB_BASE+0x160)) /* Master Interface Data Burst Size Register */
-#define UDC_TXFILLTUNING (*(volatile unsigned int *)(USB_BASE+0x164)) /* Transmit FIFO Tuning Controls Register */
-#define UDC_ULPIVIEW (*(volatile unsigned int *)(USB_BASE+0x170))
-#define UDC_CFGFLAG (*(volatile unsigned int *)(USB_BASE+0x180)) /* Configure Flag Register */
-#define UDC_PORTSC1 (*(volatile unsigned int *)(USB_BASE+0x184)) /* Port 1 Status and Control Register */
-#define UDC_OTGSC (*(volatile unsigned int *)(USB_BASE+0x1a4)) /* On-The-Go Status and Control */
-#define UDC_USBMODE (*(volatile unsigned int *)(USB_BASE+0x1a8)) /* USB Mode Register */
-#define UDC_ENDPTSETUPSTAT (*(volatile unsigned int *)(USB_BASE+0x1ac)) /* Endpoint Setup Status Register */
-#define UDC_ENDPTPRIME (*(volatile unsigned int *)(USB_BASE+0x1b0)) /* Endpoint Initialization Register */
-#define UDC_ENDPTFLUSH (*(volatile unsigned int *)(USB_BASE+0x1b4)) /* Endpoint Flush Register */
-#define UDC_ENDPTSTAT (*(volatile unsigned int *)(USB_BASE+0x1b8)) /* Endpoint Status Register */
-#define UDC_ENDPTCOMPLETE (*(volatile unsigned int *)(USB_BASE+0x1bc)) /* Endpoint Complete Register */
-#define UDC_ENDPTCTRL0 (*(volatile unsigned int *)(USB_BASE+0x1c0)) /* Endpoint 0 Control Register */
-#define UDC_ENDPTCTRL1 (*(volatile unsigned int *)(USB_BASE+0x1c4)) /* Endpoint 1 Control Register */
-#define UDC_ENDPTCTRL2 (*(volatile unsigned int *)(USB_BASE+0x1c8)) /* Endpoint 2 Control Register */
-#define UDC_ENDPTCTRL3 (*(volatile unsigned int *)(USB_BASE+0x1cc)) /* Endpoint 3 Control Register */
-#define UDC_ENDPTCTRL4 (*(volatile unsigned int *)(USB_BASE+0x1d0)) /* Endpoint 4 Control Register */
-#define UDC_ENDPTCTRL5 (*(volatile unsigned int *)(USB_BASE+0x1d4)) /* Endpoint 5 Control Register */
-#define UDC_ENDPTCTRL6 (*(volatile unsigned int *)(USB_BASE+0x1d8)) /* Endpoint 6 Control Register */
-#define UDC_ENDPTCTRL7 (*(volatile unsigned int *)(USB_BASE+0x1dc)) /* Endpoint 7 Control Register */
-#define UDC_ENDPTCTRL(x) (*(volatile unsigned int *)(USB_BASE+0x1c0+4*(x))) /* Endpoint X Control Register */
-
-/* ep0 transfer state */
-#define WAIT_FOR_SETUP 0
-#define DATA_STATE_XMIT 1
-#define DATA_STATE_NEED_ZLP 2
-#define WAIT_FOR_OUT_STATUS 3
-#define DATA_STATE_RECV 4
-
-/* Frame Index Register Bit Masks */
-#define USB_FRINDEX_MASKS (0x3fff)
-
-/* USB CMD Register Bit Masks */
-#define USB_CMD_RUN (0x00000001)
-#define USB_CMD_CTRL_RESET (0x00000002)
-#define USB_CMD_PERIODIC_SCHEDULE_EN (0x00000010)
-#define USB_CMD_ASYNC_SCHEDULE_EN (0x00000020)
-#define USB_CMD_INT_AA_DOORBELL (0x00000040)
-#define USB_CMD_ASP (0x00000300)
-#define USB_CMD_ASYNC_SCH_PARK_EN (0x00000800)
-#define USB_CMD_SUTW (0x00002000)
-#define USB_CMD_ATDTW (0x00004000)
-#define USB_CMD_ITC (0x00FF0000)
-
-/* bit 15,3,2 are frame list size */
-#define USB_CMD_FRAME_SIZE_1024 (0x00000000)
-#define USB_CMD_FRAME_SIZE_512 (0x00000004)
-#define USB_CMD_FRAME_SIZE_256 (0x00000008)
-#define USB_CMD_FRAME_SIZE_128 (0x0000000C)
-#define USB_CMD_FRAME_SIZE_64 (0x00008000)
-#define USB_CMD_FRAME_SIZE_32 (0x00008004)
-#define USB_CMD_FRAME_SIZE_16 (0x00008008)
-#define USB_CMD_FRAME_SIZE_8 (0x0000800C)
-
-/* bit 9-8 are async schedule park mode count */
-#define USB_CMD_ASP_00 (0x00000000)
-#define USB_CMD_ASP_01 (0x00000100)
-#define USB_CMD_ASP_10 (0x00000200)
-#define USB_CMD_ASP_11 (0x00000300)
-#define USB_CMD_ASP_BIT_POS (8)
-
-/* bit 23-16 are interrupt threshold control */
-#define USB_CMD_ITC_NO_THRESHOLD (0x00000000)
-#define USB_CMD_ITC_1_MICRO_FRM (0x00010000)
-#define USB_CMD_ITC_2_MICRO_FRM (0x00020000)
-#define USB_CMD_ITC_4_MICRO_FRM (0x00040000)
-#define USB_CMD_ITC_8_MICRO_FRM (0x00080000)
-#define USB_CMD_ITC_16_MICRO_FRM (0x00100000)
-#define USB_CMD_ITC_32_MICRO_FRM (0x00200000)
-#define USB_CMD_ITC_64_MICRO_FRM (0x00400000)
-#define USB_CMD_ITC_BIT_POS (16)
-
-/* USB STS Register Bit Masks */
-#define USB_STS_INT (0x00000001)
-#define USB_STS_ERR (0x00000002)
-#define USB_STS_PORT_CHANGE (0x00000004)
-#define USB_STS_FRM_LST_ROLL (0x00000008)
-#define USB_STS_SYS_ERR (0x00000010)
-#define USB_STS_IAA (0x00000020)
-#define USB_STS_RESET (0x00000040)
-#define USB_STS_SOF (0x00000080)
-#define USB_STS_SUSPEND (0x00000100)
-#define USB_STS_HC_HALTED (0x00001000)
-#define USB_STS_RCL (0x00002000)
-#define USB_STS_PERIODIC_SCHEDULE (0x00004000)
-#define USB_STS_ASYNC_SCHEDULE (0x00008000)
-
-/* USB INTR Register Bit Masks */
-#define USB_INTR_INT_EN (0x00000001)
-#define USB_INTR_ERR_INT_EN (0x00000002)
-#define USB_INTR_PTC_DETECT_EN (0x00000004)
-#define USB_INTR_FRM_LST_ROLL_EN (0x00000008)
-#define USB_INTR_SYS_ERR_EN (0x00000010)
-#define USB_INTR_ASYN_ADV_EN (0x00000020)
-#define USB_INTR_RESET_EN (0x00000040)
-#define USB_INTR_SOF_EN (0x00000080)
-#define USB_INTR_DEVICE_SUSPEND (0x00000100)
-
-/* Device Address bit masks */
-#define USB_DEVICE_ADDRESS_MASK (0xFE000000)
-#define USB_DEVICE_ADDRESS_BIT_POS (25)
-
-/* endpoint list address bit masks */
-#define USB_EP_LIST_ADDRESS_MASK (0xfffff800)
-
-/* PORTSCX Register Bit Masks */
-#define PORTSCX_CURRENT_CONNECT_STATUS (0x00000001)
-#define PORTSCX_CONNECT_STATUS_CHANGE (0x00000002)
-#define PORTSCX_PORT_ENABLE (0x00000004)
-#define PORTSCX_PORT_EN_DIS_CHANGE (0x00000008)
-#define PORTSCX_OVER_CURRENT_ACT (0x00000010)
-#define PORTSCX_OVER_CURRENT_CHG (0x00000020)
-#define PORTSCX_PORT_FORCE_RESUME (0x00000040)
-#define PORTSCX_PORT_SUSPEND (0x00000080)
-#define PORTSCX_PORT_RESET (0x00000100)
-#define PORTSCX_LINE_STATUS_BITS (0x00000C00)
-#define PORTSCX_PORT_POWER (0x00001000)
-#define PORTSCX_PORT_INDICTOR_CTRL (0x0000C000)
-#define PORTSCX_PORT_TEST_CTRL (0x000F0000)
-#define PORTSCX_WAKE_ON_CONNECT_EN (0x00100000)
-#define PORTSCX_WAKE_ON_CONNECT_DIS (0x00200000)
-#define PORTSCX_WAKE_ON_OVER_CURRENT (0x00400000)
-#define PORTSCX_PHY_LOW_POWER_SPD (0x00800000)
-#define PORTSCX_PORT_FORCE_FULL_SPEED (0x01000000)
-#define PORTSCX_PORT_SPEED_MASK (0x0C000000)
-#define PORTSCX_PORT_WIDTH (0x10000000)
-#define PORTSCX_PHY_TYPE_SEL (0xC0000000)
-
-/* bit 11-10 are line status */
-#define PORTSCX_LINE_STATUS_SE0 (0x00000000)
-#define PORTSCX_LINE_STATUS_JSTATE (0x00000400)
-#define PORTSCX_LINE_STATUS_KSTATE (0x00000800)
-#define PORTSCX_LINE_STATUS_UNDEF (0x00000C00)
-#define PORTSCX_LINE_STATUS_BIT_POS (10)
-
-/* bit 15-14 are port indicator control */
-#define PORTSCX_PIC_OFF (0x00000000)
-#define PORTSCX_PIC_AMBER (0x00004000)
-#define PORTSCX_PIC_GREEN (0x00008000)
-#define PORTSCX_PIC_UNDEF (0x0000C000)
-#define PORTSCX_PIC_BIT_POS (14)
-
-/* bit 19-16 are port test control */
-#define PORTSCX_PTC_DISABLE (0x00000000)
-#define PORTSCX_PTC_JSTATE (0x00010000)
-#define PORTSCX_PTC_KSTATE (0x00020000)
-#define PORTSCX_PTC_SEQNAK (0x00030000)
-#define PORTSCX_PTC_PACKET (0x00040000)
-#define PORTSCX_PTC_FORCE_EN (0x00050000)
-#define PORTSCX_PTC_BIT_POS (16)
-
-/* bit 27-26 are port speed */
-#define PORTSCX_PORT_SPEED_FULL (0x00000000)
-#define PORTSCX_PORT_SPEED_LOW (0x04000000)
-#define PORTSCX_PORT_SPEED_HIGH (0x08000000)
-#define PORTSCX_PORT_SPEED_UNDEF (0x0C000000)
-#define PORTSCX_SPEED_BIT_POS (26)
-
-/* bit 28 is parallel transceiver width for UTMI interface */
-#define PORTSCX_PTW (0x10000000)
-#define PORTSCX_PTW_8BIT (0x00000000)
-#define PORTSCX_PTW_16BIT (0x10000000)
-
-/* bit 31-30 are port transceiver select */
-#define PORTSCX_PTS_UTMI (0x00000000)
-#define PORTSCX_PTS_ULPI (0x80000000)
-#define PORTSCX_PTS_FSLS (0xC0000000)
-#define PORTSCX_PTS_BIT_POS (30)
-
-/* USB MODE Register Bit Masks */
-#define USB_MODE_CTRL_MODE_IDLE (0x00000000)
-#define USB_MODE_CTRL_MODE_DEVICE (0x00000002)
-#define USB_MODE_CTRL_MODE_HOST (0x00000003)
-#define USB_MODE_CTRL_MODE_RSV (0x00000001)
-#define USB_MODE_SETUP_LOCK_OFF (0x00000008)
-#define USB_MODE_STREAM_DISABLE (0x00000010)
-
-/* Endpoint Flush Register */
-#define EPFLUSH_TX_OFFSET (0x00010000)
-#define EPFLUSH_RX_OFFSET (0x00000000)
-
-/* Endpoint Setup Status bit masks */
-#define EP_SETUP_STATUS_MASK (0x0000003F)
-#define EP_SETUP_STATUS_EP0 (0x00000001)
-
-/* ENDPOINTCTRLx Register Bit Masks */
-#define EPCTRL_TX_ENABLE (0x00800000)
-#define EPCTRL_TX_DATA_TOGGLE_RST (0x00400000) /* Not EP0 */
-#define EPCTRL_TX_DATA_TOGGLE_INH (0x00200000) /* Not EP0 */
-#define EPCTRL_TX_TYPE (0x000C0000)
-#define EPCTRL_TX_DATA_SOURCE (0x00020000) /* Not EP0 */
-#define EPCTRL_TX_EP_STALL (0x00010000)
-#define EPCTRL_RX_ENABLE (0x00000080)
-#define EPCTRL_RX_DATA_TOGGLE_RST (0x00000040) /* Not EP0 */
-#define EPCTRL_RX_DATA_TOGGLE_INH (0x00000020) /* Not EP0 */
-#define EPCTRL_RX_TYPE (0x0000000C)
-#define EPCTRL_RX_DATA_SINK (0x00000002) /* Not EP0 */
-#define EPCTRL_RX_EP_STALL (0x00000001)
-
-/* bit 19-18 and 3-2 are endpoint type */
-#define EPCTRL_EP_TYPE_CONTROL (0)
-#define EPCTRL_EP_TYPE_ISO (1)
-#define EPCTRL_EP_TYPE_BULK (2)
-#define EPCTRL_EP_TYPE_INTERRUPT (3)
-#define EPCTRL_TX_EP_TYPE_SHIFT (18)
-#define EPCTRL_RX_EP_TYPE_SHIFT (2)
-
-/* SNOOPn Register Bit Masks */
-#define SNOOP_ADDRESS_MASK (0xFFFFF000)
-#define SNOOP_SIZE_ZERO (0x00) /* snooping disable */
-#define SNOOP_SIZE_4KB (0x0B) /* 4KB snoop size */
-#define SNOOP_SIZE_8KB (0x0C)
-#define SNOOP_SIZE_16KB (0x0D)
-#define SNOOP_SIZE_32KB (0x0E)
-#define SNOOP_SIZE_64KB (0x0F)
-#define SNOOP_SIZE_128KB (0x10)
-#define SNOOP_SIZE_256KB (0x11)
-#define SNOOP_SIZE_512KB (0x12)
-#define SNOOP_SIZE_1MB (0x13)
-#define SNOOP_SIZE_2MB (0x14)
-#define SNOOP_SIZE_4MB (0x15)
-#define SNOOP_SIZE_8MB (0x16)
-#define SNOOP_SIZE_16MB (0x17)
-#define SNOOP_SIZE_32MB (0x18)
-#define SNOOP_SIZE_64MB (0x19)
-#define SNOOP_SIZE_128MB (0x1A)
-#define SNOOP_SIZE_256MB (0x1B)
-#define SNOOP_SIZE_512MB (0x1C)
-#define SNOOP_SIZE_1GB (0x1D)
-#define SNOOP_SIZE_2GB (0x1E) /* 2GB snoop size */
-
-/* pri_ctrl Register Bit Masks */
-#define PRI_CTRL_PRI_LVL1 (0x0000000C)
-#define PRI_CTRL_PRI_LVL0 (0x00000003)
-
-/* si_ctrl Register Bit Masks */
-#define SI_CTRL_ERR_DISABLE (0x00000010)
-#define SI_CTRL_IDRC_DISABLE (0x00000008)
-#define SI_CTRL_RD_SAFE_EN (0x00000004)
-#define SI_CTRL_RD_PREFETCH_DISABLE (0x00000002)
-#define SI_CTRL_RD_PREFEFETCH_VAL (0x00000001)
-
-/* control Register Bit Masks */
-#define USB_CTRL_IOENB (0x00000004)
-#define USB_CTRL_ULPI_INT0EN (0x00000001)
-
-/* Externally used functions */
-int dr_controller_setup(void);
-void dr_controller_run(void);
-void dr_controller_stop(void);
-
-#endif /* __ARCOTG_UDC_H */
diff --git a/firmware/export/config-c200.h b/firmware/export/config-c200.h
index 8a1d6a37fa..53ff97326a 100644
--- a/firmware/export/config-c200.h
+++ b/firmware/export/config-c200.h
@@ -162,10 +162,10 @@
/* USB On-the-go */
#define CONFIG_USBOTG USBOTG_ARC
-/* enable these for the experimental usb stack
+/* enable these for the experimental usb stack */
#define HAVE_USBSTACK
-#define USBSTACK_CAPS CONTROLLER_DEVICE
-*/
+#define USB_VENDOR_ID 0x0781
+#define USB_PRODUCT_ID 0x7450
/* Virtual LED (icon) */
#define CONFIG_LED LED_VIRTUAL
diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h
index f5ba8f0c4d..c49ee23841 100644
--- a/firmware/export/config-e200.h
+++ b/firmware/export/config-e200.h
@@ -157,11 +157,10 @@
/* USB On-the-go */
#define CONFIG_USBOTG USBOTG_ARC
-/* enable these for the experimental usb stack
+/* enable these for the experimental usb stack */
#define HAVE_USBSTACK
-#define USBSTACK_CAPS CONTROLLER_DEVICE
-*/
-
+#define USB_VENDOR_ID 0x0781
+#define USB_PRODUCT_ID 0x7421
/* Virtual LED (icon) */
#define CONFIG_LED LED_VIRTUAL
diff --git a/firmware/export/config-h10.h b/firmware/export/config-h10.h
index aa60b106da..c69b433503 100644
--- a/firmware/export/config-h10.h
+++ b/firmware/export/config-h10.h
@@ -152,10 +152,10 @@
/* USB On-the-go */
#define CONFIG_USBOTG USBOTG_ARC
-/* enable these for the experimental usb stack
+/* enable these for the experimental usb stack */
#define HAVE_USBSTACK
-#define USBSTACK_CAPS CONTROLLER_DEVICE
-*/
+#define USB_VENDOR_ID 0x0B70
+#define USB_PRODUCT_ID 0x00BA
/* Virtual LED (icon) */
#define CONFIG_LED LED_VIRTUAL
diff --git a/firmware/export/config-h10_5gb.h b/firmware/export/config-h10_5gb.h
index e8f7d7562a..efb62c03fb 100644
--- a/firmware/export/config-h10_5gb.h
+++ b/firmware/export/config-h10_5gb.h
@@ -135,10 +135,10 @@
/* USB On-the-go */
#define CONFIG_USBOTG USBOTG_ARC
-/* enable these for the experimental usb stack
+/* enable these for the experimental usb stack */
#define HAVE_USBSTACK
-#define USBSTACK_CAPS CONTROLLER_DEVICE
-*/
+#define USB_VENDOR_ID 0x0B70
+#define USB_PRODUCT_ID 0x00BA
/* Virtual LED (icon) */
#define CONFIG_LED LED_VIRTUAL
diff --git a/firmware/export/linkedlist.h b/firmware/export/linkedlist.h
deleted file mode 100644
index bea41eeca5..0000000000
--- a/firmware/export/linkedlist.h
+++ /dev/null
@@ -1,355 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) by Linux Kernel Developers
- *
- * Original source can be found in linux kernel: <kernel>/include/list.h
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#ifndef _LINKED_LIST_H_
-#define _LINKED_LIST_H_
-
-#include <stddef.h> /* used for offsetof */
-
-static inline void prefetch(const void *x) { (void)x; }
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-/* TODO move this macro? */
-/* more about this macro: http://www.kroah.com/log/linux/container_of.html */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
-/*
- * These are non-NULL pointers that will result in page faults
- * under normal circumstances, used to verify that nobody uses
- * non-initialized list entries.
- */
-#define LIST_POISON1 ((void *) 0x00100100)
-#define LIST_POISON2 ((void *) 0x00200200)
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-static inline void INIT_LIST_HEAD(struct list_head *list)
-{
- list->next = list;
- list->prev = list;
-}
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head * prev, struct list_head * next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
-}
-
-/**
- * list_replace - replace old entry by new one
- * @old : the element to be replaced
- * @new : the new element to insert
- *
- * If @old was empty, it will be overwritten.
- */
-static inline void list_replace(struct list_head *old,
- struct list_head *new)
-{
- new->next = old->next;
- new->next->prev = new;
- new->prev = old->prev;
- new->prev->next = new;
-}
-
-static inline void list_replace_init(struct list_head *old,
- struct list_head *new)
-{
- list_replace(old, new);
- INIT_LIST_HEAD(old);
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_move - delete from one list and add as another's head
- * @list: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
-{
- __list_del(list->prev, list->next);
- list_add(list, head);
-}
-
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @list: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
- struct list_head *head)
-{
- __list_del(list->prev, list->next);
- list_add_tail(list, head);
-}
-
-/**
- * list_is_last - tests whether @list is the last entry in list @head
- * @list: the entry to test
- * @head: the head of the list
- */
-static inline int list_is_last(const struct list_head *list,
- const struct list_head *head)
-{
- return list->next == head;
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(const struct list_head *head)
-{
- return head->next == head;
-}
-
-static inline void __list_splice(struct list_head *list,
- struct list_head *head)
-{
- struct list_head *first = list->next;
- struct list_head *last = list->prev;
- struct list_head *at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
-}
-
-/**
- * list_splice - join two lists
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice(struct list_head *list, struct list_head *head)
-{
- if (!list_empty(list)) {
- __list_splice(list, head);
- }
-}
-
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * The list at @list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
- struct list_head *head)
-{
- if (!list_empty(list)) {
- __list_splice(list, head);
- INIT_LIST_HEAD(list);
- }
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-/**
- * list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
- */
-#define list_for_each(pos, head) \
- for (pos = (head)->next; prefetch(pos->next), pos != (head); \
- pos = pos->next)
-
-/**
- * __list_for_each - iterate over a list
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
- *
- * This variant differs from list_for_each() in that it's the
- * simplest possible list iteration code, no prefetching is done.
- * Use this for code that knows the list to be very short (empty
- * or 1 entry) most of the time.
- */
-#define __list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_prev - iterate over a list backwards
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
- */
-#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
- pos = pos->prev)
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_reverse - iterate backwards over list of given type.
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- */
-#define list_for_each_entry_reverse(pos, head, member) \
- for (pos = list_entry((head)->prev, typeof(*pos), member); \
- prefetch(pos->member.prev), &pos->member != (head); \
- pos = list_entry(pos->member.prev, typeof(*pos), member))
-
-/**
- * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
- * @pos: the type * to use as a start point
- * @head: the head of the list
- * @member: the name of the list_struct within the struct.
- *
- * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
- */
-#define list_prepare_entry(pos, head, member) \
- ((pos) ? : list_entry(head, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue - continue iteration over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- *
- * Continue to iterate over list of given type, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue(pos, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member); \
- prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_from - iterate over list of given type from the current point
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_struct within the struct.
- *
- * Iterate over list of given type, continuing from current position.
- */
-#define list_for_each_entry_from(pos, head, member) \
- for (; prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-#endif /*_LINKED_LIST_H_*/
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h
index b559aa3665..845c89c616 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -92,8 +92,8 @@
#define TIMER2_IRQ 1
#define MAILBOX_IRQ 4
#define IIS_IRQ 10
+#define USB_IRQ 20
#define IDE_IRQ 23
-#define USB_IRQ 24
#define FIREWIRE_IRQ 25
#define HI_IRQ 30
#define GPIO0_IRQ (32+0) /* Ports A..D */
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index 17dbafa10e..0977ff4d7d 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -51,7 +51,7 @@
#define USBPOWER_BUTTON BUTTON_MENU
#define USBPOWER_BTN_IGNORE BUTTON_BACK
#elif CONFIG_KEYPAD == IRIVER_H10_PAD
-#define USBPOWER_BUTTON BUTTON_NONE
+#define USBPOWER_BUTTON BUTTON_RIGHT
#define USBPOWER_BTN_IGNORE BUTTON_POWER
#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
(CONFIG_KEYPAD == SANSA_C200_PAD)
diff --git a/firmware/usbstack/drivers/device/usb_serial.h b/firmware/export/usb_core.h
index cc5d9c488f..be3e4789d9 100644
--- a/firmware/usbstack/drivers/device/usb_serial.h
+++ b/firmware/export/usb_core.h
@@ -5,9 +5,9 @@
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
- * $Id$
+ * $Id: $
*
- * Copyright (C) 2007 by Christian Gmeiner
+ * Copyright (C) 2007 by Bjrn Stenberg
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
@@ -16,18 +16,40 @@
* KIND, either express or implied.
*
****************************************************************************/
+#ifndef USB_CORE_H
+#define USB_CORE_H
-#ifndef _SERIAL_H_
-#define _SERIAL_H_
+#include "usb_ch9.h"
-#include "usbstack/core.h"
+#if defined(CPU_PP)
+#define USB_IRAM_ORIGIN ((unsigned char *)0x4000c000)
+#define USB_IRAM_SIZE ((size_t)0xc000)
+#endif
-/* register serial driver in usb stack */
-void usb_serial_driver_init(void);
+/* endpoints */
+enum {
+ EP_CONTROL = 0,
+ EP_RX,
+ EP_TX,
+ NUM_ENDPOINTS
+};
-int usb_serial_driver_bind(void* controller_ops);
-void usb_serial_driver_unbind(void);
-int usb_serial_driver_request(struct usb_ctrlrequest* req);
-void usb_serial_driver_speed(enum usb_device_speed speed);
+/* queue events */
+#define USB_TRANSFER_COMPLETE 1
+
+struct queue_msg {
+ int endpoint;
+ int length;
+ void* data;
+};
+
+extern int usb_max_pkt_size;
+
+void usb_core_init(void);
+void usb_core_exit(void);
+void usb_core_control_request(struct usb_ctrlrequest* req);
+void usb_core_transfer_complete(int endpoint, bool in);
+void usb_core_bus_reset(void);
+
+#endif
-#endif /*_SERIAL_H_*/
diff --git a/firmware/usbstack/drivers/device/usb_storage.h b/firmware/export/usb_drv.h
index de53a06097..a30f2ec494 100644
--- a/firmware/usbstack/drivers/device/usb_storage.h
+++ b/firmware/export/usb_drv.h
@@ -5,9 +5,9 @@
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
- * $Id$
+ * $Id: $
*
- * Copyright (C) 2007 by Christian Gmeiner
+ * Copyright (C) 2007 by Bjrn Stenberg
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
@@ -16,18 +16,20 @@
* KIND, either express or implied.
*
****************************************************************************/
+#ifndef ARCOTG_DRV_H
+#define ARCOTG_DRV_H
+#include "usb_ch9.h"
+#include "kernel.h"
-#ifndef _STORGAGE_H_
-#define _STORGAGE_H_
+void usb_drv_init(void);
+void usb_drv_exit(void);
+void usb_drv_int(void);
+void usb_drv_stall(int endpoint, bool stall);
+void usb_drv_send(int endpoint, void* ptr, int length);
+void usb_drv_recv(int endpoint, void* ptr, int length);
+void usb_drv_ack(struct usb_ctrlrequest* req);
+void usb_drv_set_address(int address);
+void usb_drv_reset_endpoint(int endpoint, bool send);
+void usb_drv_wait(int endpoint, bool send);
-#include "usbstack/core.h"
-
-/* register storage driver in usb stack */
-void usb_storage_driver_init(void);
-
-int usb_storage_driver_bind(void* controller_ops);
-void usb_storage_driver_unbind(void);
-int usb_storage_driver_request(struct usb_ctrlrequest* req);
-void usb_storage_driver_speed(enum usb_device_speed speed);
-
-#endif /*_STORGAGE_H_*/
+#endif
diff --git a/firmware/export/usbstack.h b/firmware/export/usbstack.h
deleted file mode 100644
index 4ad477ec97..0000000000
--- a/firmware/export/usbstack.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#ifndef _USBSTACK_H_
-#define _USBSTACK_H_
-
-#include <errno.h>
-
-#define USB_STACK_MAX_SETTINGS_NAME 32*10 /* should be enough for > 10 driver names */
-
-/* usb stack configuration */
-#ifndef USBSTACK_CAPS
-#define USBSTACK_CAPS 0 /* default: use no controller */
-#endif
-
-#define CONTROLLER_DEVICE (1 << 0)
-#define CONTROLLER_HOST (1 << 1)
-
-/*
- * error codes
- */
-#define ENOFREESLOT 1
-#define EWRONGCONTROLLERTYPE 2
-#define ENODRIVERFOUND 3
-#define EHWCRITICAL 4
-
-enum usb_controller_type {
- DEVICE = 0,
- HOST,
-};
-
-/*
- * stack routines
- */
-void usb_stack_init(void);
-void usb_stack_start(void);
-void usb_stack_stop(void);
-
-void usb_controller_select(int type);
-int usb_stack_get_mode(void);
-int usb_device_driver_bind(const char* name);
-void ubs_device_driver_unbind(void);
-
-/* used by apps settings code */
-unsigned char device_driver_names[USB_STACK_MAX_SETTINGS_NAME];
-
-#endif /*_USBSTACK_H_*/
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c
index 4d7e603a16..5dfcfa9ea9 100644
--- a/firmware/target/arm/system-pp502x.c
+++ b/firmware/target/arm/system-pp502x.c
@@ -21,6 +21,9 @@
#include "i2s.h"
#include "i2c-pp.h"
#include "as3514.h"
+#ifdef HAVE_USBSTACK
+#include "usb_drv.h"
+#endif
#ifndef BOOTLOADER
extern void TIMER1(void);
@@ -33,19 +36,12 @@ extern void button_int(void);
extern void clickwheel_int(void);
#endif
-#ifdef HAVE_USBSTACK
-#include "usbstack/core.h"
-#endif
-
void irq(void)
{
if(CURRENT_CORE == CPU)
{
if (CPU_INT_STAT & TIMER1_MASK) {
TIMER1();
-#ifdef HAVE_USBSTACK
- usb_stack_irq();
-#endif
} else if (CPU_INT_STAT & TIMER2_MASK)
TIMER2();
#if defined(IPOD_MINI) /* Mini 1st gen only, mini 2nd gen uses iPod 4G code */
@@ -71,6 +67,11 @@ void irq(void)
microsd_int();
}
#endif
+#ifdef HAVE_USBSTACK
+ else if (CPU_INT_STAT & USB_MASK) {
+ usb_drv_int();
+ }
+#endif
} else {
if (COP_INT_STAT & TIMER2_MASK)
TIMER2();
diff --git a/firmware/target/arm/usb-drv-pp502x.c b/firmware/target/arm/usb-drv-pp502x.c
new file mode 100644
index 0000000000..a837728a4e
--- /dev/null
+++ b/firmware/target/arm/usb-drv-pp502x.c
@@ -0,0 +1,624 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: $
+ *
+ * Driver for ARC USBOTG Device Controller
+ *
+ * Copyright (C) 2007 by Bjrn Stenberg
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "system.h"
+#include "string.h"
+#include "usb_ch9.h"
+#include "usb_core.h"
+//#define LOGF_ENABLE
+#include "logf.h"
+
+/* USB device mode registers (Little Endian) */
+
+#define REG_ID (*(volatile unsigned int *)(USB_BASE+0x000))
+#define REG_HWGENERAL (*(volatile unsigned int *)(USB_BASE+0x004))
+#define REG_CAPLENGTH (*(volatile unsigned char*)(USB_BASE+0x100))
+#define REG_DCIVERSION (*(volatile unsigned int *)(USB_BASE+0x120))
+#define REG_DCCPARAMS (*(volatile unsigned int *)(USB_BASE+0x124))
+#define REG_USBCMD (*(volatile unsigned int *)(USB_BASE+0x140))
+#define REG_USBSTS (*(volatile unsigned int *)(USB_BASE+0x144))
+#define REG_USBINTR (*(volatile unsigned int *)(USB_BASE+0x148))
+#define REG_FRINDEX (*(volatile unsigned int *)(USB_BASE+0x14c))
+#define REG_DEVICEADDR (*(volatile unsigned int *)(USB_BASE+0x154))
+#define REG_ENDPOINTLISTADDR (*(volatile unsigned int *)(USB_BASE+0x158))
+#define REG_BURSTSIZE (*(volatile unsigned int *)(USB_BASE+0x160))
+#define REG_CONFIGFLAG (*(volatile unsigned int *)(USB_BASE+0x180))
+#define REG_PORTSC1 (*(volatile unsigned int *)(USB_BASE+0x184))
+#define REG_OTGSC (*(volatile unsigned int *)(USB_BASE+0x1a4))
+#define REG_USBMODE (*(volatile unsigned int *)(USB_BASE+0x1a8))
+#define REG_ENDPTSETUPSTAT (*(volatile unsigned int *)(USB_BASE+0x1ac))
+#define REG_ENDPTPRIME (*(volatile unsigned int *)(USB_BASE+0x1b0))
+#define REG_ENDPTFLUSH (*(volatile unsigned int *)(USB_BASE+0x1b4))
+#define REG_ENDPTSTATUS (*(volatile unsigned int *)(USB_BASE+0x1b8))
+#define REG_ENDPTCOMPLETE (*(volatile unsigned int *)(USB_BASE+0x1bc))
+#define REG_ENDPTCTRL0 (*(volatile unsigned int *)(USB_BASE+0x1c0))
+#define REG_ENDPTCTRL1 (*(volatile unsigned int *)(USB_BASE+0x1c4))
+#define REG_ENDPTCTRL2 (*(volatile unsigned int *)(USB_BASE+0x1c8))
+#define REG_ENDPTCTRL(_x_) (*(volatile unsigned int *)(USB_BASE+0x1c0+4*(_x_)))
+
+/* Frame Index Register Bit Masks */
+#define USB_FRINDEX_MASKS (0x3fff)
+
+/* USB CMD Register Bit Masks */
+#define USBCMD_RUN (0x00000001)
+#define USBCMD_CTRL_RESET (0x00000002)
+#define USBCMD_PERIODIC_SCHEDULE_EN (0x00000010)
+#define USBCMD_ASYNC_SCHEDULE_EN (0x00000020)
+#define USBCMD_INT_AA_DOORBELL (0x00000040)
+#define USBCMD_ASP (0x00000300)
+#define USBCMD_ASYNC_SCH_PARK_EN (0x00000800)
+#define USBCMD_SUTW (0x00002000)
+#define USBCMD_ATDTW (0x00004000)
+#define USBCMD_ITC (0x00FF0000)
+
+/* bit 15,3,2 are frame list size */
+#define USBCMD_FRAME_SIZE_1024 (0x00000000)
+#define USBCMD_FRAME_SIZE_512 (0x00000004)
+#define USBCMD_FRAME_SIZE_256 (0x00000008)
+#define USBCMD_FRAME_SIZE_128 (0x0000000C)
+#define USBCMD_FRAME_SIZE_64 (0x00008000)
+#define USBCMD_FRAME_SIZE_32 (0x00008004)
+#define USBCMD_FRAME_SIZE_16 (0x00008008)
+#define USBCMD_FRAME_SIZE_8 (0x0000800C)
+
+/* bit 9-8 are async schedule park mode count */
+#define USBCMD_ASP_00 (0x00000000)
+#define USBCMD_ASP_01 (0x00000100)
+#define USBCMD_ASP_10 (0x00000200)
+#define USBCMD_ASP_11 (0x00000300)
+#define USBCMD_ASP_BIT_POS (8)
+
+/* bit 23-16 are interrupt threshold control */
+#define USBCMD_ITC_NO_THRESHOLD (0x00000000)
+#define USBCMD_ITC_1_MICRO_FRM (0x00010000)
+#define USBCMD_ITC_2_MICRO_FRM (0x00020000)
+#define USBCMD_ITC_4_MICRO_FRM (0x00040000)
+#define USBCMD_ITC_8_MICRO_FRM (0x00080000)
+#define USBCMD_ITC_16_MICRO_FRM (0x00100000)
+#define USBCMD_ITC_32_MICRO_FRM (0x00200000)
+#define USBCMD_ITC_64_MICRO_FRM (0x00400000)
+#define USBCMD_ITC_BIT_POS (16)
+
+/* USB STS Register Bit Masks */
+#define USBSTS_INT (0x00000001)
+#define USBSTS_ERR (0x00000002)
+#define USBSTS_PORT_CHANGE (0x00000004)
+#define USBSTS_FRM_LST_ROLL (0x00000008)
+#define USBSTS_SYS_ERR (0x00000010) /* not used */
+#define USBSTS_IAA (0x00000020)
+#define USBSTS_RESET (0x00000040)
+#define USBSTS_SOF (0x00000080)
+#define USBSTS_SUSPEND (0x00000100)
+#define USBSTS_HC_HALTED (0x00001000)
+#define USBSTS_RCL (0x00002000)
+#define USBSTS_PERIODIC_SCHEDULE (0x00004000)
+#define USBSTS_ASYNC_SCHEDULE (0x00008000)
+
+/* USB INTR Register Bit Masks */
+#define USBINTR_INT_EN (0x00000001)
+#define USBINTR_ERR_INT_EN (0x00000002)
+#define USBINTR_PTC_DETECT_EN (0x00000004)
+#define USBINTR_FRM_LST_ROLL_EN (0x00000008)
+#define USBINTR_SYS_ERR_EN (0x00000010)
+#define USBINTR_ASYN_ADV_EN (0x00000020)
+#define USBINTR_RESET_EN (0x00000040)
+#define USBINTR_SOF_EN (0x00000080)
+#define USBINTR_DEVICE_SUSPEND (0x00000100)
+
+/* Device Address bit masks */
+#define USBDEVICEADDRESS_MASK (0xFE000000)
+#define USBDEVICEADDRESS_BIT_POS (25)
+
+/* endpoint list address bit masks */
+#define USB_EP_LIST_ADDRESS_MASK (0xfffff800)
+
+/* PORTSCX Register Bit Masks */
+#define PORTSCX_CURRENT_CONNECT_STATUS (0x00000001)
+#define PORTSCX_CONNECT_STATUS_CHANGE (0x00000002)
+#define PORTSCX_PORT_ENABLE (0x00000004)
+#define PORTSCX_PORT_EN_DIS_CHANGE (0x00000008)
+#define PORTSCX_OVER_CURRENT_ACT (0x00000010)
+#define PORTSCX_OVER_CURRENT_CHG (0x00000020)
+#define PORTSCX_PORT_FORCE_RESUME (0x00000040)
+#define PORTSCX_PORT_SUSPEND (0x00000080)
+#define PORTSCX_PORT_RESET (0x00000100)
+#define PORTSCX_LINE_STATUS_BITS (0x00000C00)
+#define PORTSCX_PORT_POWER (0x00001000)
+#define PORTSCX_PORT_INDICTOR_CTRL (0x0000C000)
+#define PORTSCX_PORT_TEST_CTRL (0x000F0000)
+#define PORTSCX_WAKE_ON_CONNECT_EN (0x00100000)
+#define PORTSCX_WAKE_ON_CONNECT_DIS (0x00200000)
+#define PORTSCX_WAKE_ON_OVER_CURRENT (0x00400000)
+#define PORTSCX_PHY_LOW_POWER_SPD (0x00800000)
+#define PORTSCX_PORT_FORCE_FULL_SPEED (0x01000000)
+#define PORTSCX_PORT_SPEED_MASK (0x0C000000)
+#define PORTSCX_PORT_WIDTH (0x10000000)
+#define PORTSCX_PHY_TYPE_SEL (0xC0000000)
+
+/* bit 11-10 are line status */
+#define PORTSCX_LINE_STATUS_SE0 (0x00000000)
+#define PORTSCX_LINE_STATUS_JSTATE (0x00000400)
+#define PORTSCX_LINE_STATUS_KSTATE (0x00000800)
+#define PORTSCX_LINE_STATUS_UNDEF (0x00000C00)
+#define PORTSCX_LINE_STATUS_BIT_POS (10)
+
+/* bit 15-14 are port indicator control */
+#define PORTSCX_PIC_OFF (0x00000000)
+#define PORTSCX_PIC_AMBER (0x00004000)
+#define PORTSCX_PIC_GREEN (0x00008000)
+#define PORTSCX_PIC_UNDEF (0x0000C000)
+#define PORTSCX_PIC_BIT_POS (14)
+
+/* bit 19-16 are port test control */
+#define PORTSCX_PTC_DISABLE (0x00000000)
+#define PORTSCX_PTC_JSTATE (0x00010000)
+#define PORTSCX_PTC_KSTATE (0x00020000)
+#define PORTSCX_PTC_SEQNAK (0x00030000)
+#define PORTSCX_PTC_PACKET (0x00040000)
+#define PORTSCX_PTC_FORCE_EN (0x00050000)
+#define PORTSCX_PTC_BIT_POS (16)
+
+/* bit 27-26 are port speed */
+#define PORTSCX_PORT_SPEED_FULL (0x00000000)
+#define PORTSCX_PORT_SPEED_LOW (0x04000000)
+#define PORTSCX_PORT_SPEED_HIGH (0x08000000)
+#define PORTSCX_PORT_SPEED_UNDEF (0x0C000000)
+#define PORTSCX_SPEED_BIT_POS (26)
+
+/* bit 28 is parallel transceiver width for UTMI interface */
+#define PORTSCX_PTW (0x10000000)
+#define PORTSCX_PTW_8BIT (0x00000000)
+#define PORTSCX_PTW_16BIT (0x10000000)
+
+/* bit 31-30 are port transceiver select */
+#define PORTSCX_PTS_UTMI (0x00000000)
+#define PORTSCX_PTS_ULPI (0x80000000)
+#define PORTSCX_PTS_FSLS (0xC0000000)
+#define PORTSCX_PTS_BIT_POS (30)
+
+/* USB MODE Register Bit Masks */
+#define USBMODE_CTRL_MODE_IDLE (0x00000000)
+#define USBMODE_CTRL_MODE_DEVICE (0x00000002)
+#define USBMODE_CTRL_MODE_HOST (0x00000003)
+#define USBMODE_CTRL_MODE_RSV (0x00000001)
+#define USBMODE_SETUP_LOCK_OFF (0x00000008)
+#define USBMODE_STREAM_DISABLE (0x00000010)
+
+/* Endpoint Flush Register */
+#define EPFLUSH_TX_OFFSET (0x00010000)
+#define EPFLUSH_RX_OFFSET (0x00000000)
+
+/* Endpoint Setup Status bit masks */
+#define EPSETUP_STATUS_MASK (0x0000003F)
+#define EPSETUP_STATUS_EP0 (0x00000001)
+
+/* ENDPOINTCTRLx Register Bit Masks */
+#define EPCTRL_TX_ENABLE (0x00800000)
+#define EPCTRL_TX_DATA_TOGGLE_RST (0x00400000) /* Not EP0 */
+#define EPCTRL_TX_DATA_TOGGLE_INH (0x00200000) /* Not EP0 */
+#define EPCTRL_TX_TYPE (0x000C0000)
+#define EPCTRL_TX_DATA_SOURCE (0x00020000) /* Not EP0 */
+#define EPCTRL_TX_EP_STALL (0x00010000)
+#define EPCTRL_RX_ENABLE (0x00000080)
+#define EPCTRL_RX_DATA_TOGGLE_RST (0x00000040) /* Not EP0 */
+#define EPCTRL_RX_DATA_TOGGLE_INH (0x00000020) /* Not EP0 */
+#define EPCTRL_RX_TYPE (0x0000000C)
+#define EPCTRL_RX_DATA_SINK (0x00000002) /* Not EP0 */
+#define EPCTRL_RX_EP_STALL (0x00000001)
+
+/* bit 19-18 and 3-2 are endpoint type */
+#define EPCTRL_EP_TYPE_CONTROL (0)
+#define EPCTRL_EP_TYPE_ISO (1)
+#define EPCTRL_EP_TYPE_BULK (2)
+#define EPCTRL_EP_TYPE_INTERRUPT (3)
+#define EPCTRL_TX_EP_TYPE_SHIFT (18)
+#define EPCTRL_RX_EP_TYPE_SHIFT (2)
+
+/* pri_ctrl Register Bit Masks */
+#define PRI_CTRL_PRI_LVL1 (0x0000000C)
+#define PRI_CTRL_PRI_LVL0 (0x00000003)
+
+/* si_ctrl Register Bit Masks */
+#define SI_CTRL_ERR_DISABLE (0x00000010)
+#define SI_CTRL_IDRC_DISABLE (0x00000008)
+#define SI_CTRL_RD_SAFE_EN (0x00000004)
+#define SI_CTRL_RD_PREFETCH_DISABLE (0x00000002)
+#define SI_CTRL_RD_PREFEFETCH_VAL (0x00000001)
+
+/* control Register Bit Masks */
+#define USB_CTRL_IOENB (0x00000004)
+#define USB_CTRL_ULPI_INT0EN (0x00000001)
+
+#define QH_MULT_POS (30)
+#define QH_ZLT_SEL (0x20000000)
+#define QH_MAX_PKT_LEN_POS (16)
+#define QH_IOS (0x00008000)
+#define QH_NEXT_TERMINATE (0x00000001)
+#define QH_IOC (0x00008000)
+#define QH_MULTO (0x00000C00)
+#define QH_STATUS_HALT (0x00000040)
+#define QH_STATUS_ACTIVE (0x00000080)
+#define EP_QUEUE_CURRENT_OFFSET_MASK (0x00000FFF)
+#define EP_QUEUE_HEAD_NEXT_POINTER_MASK (0xFFFFFFE0)
+#define EP_QUEUE_FRINDEX_MASK (0x000007FF)
+#define EP_MAX_LENGTH_TRANSFER (0x4000)
+
+#define DTD_NEXT_TERMINATE (0x00000001)
+#define DTD_IOC (0x00008000)
+#define DTD_STATUS_ACTIVE (0x00000080)
+#define DTD_STATUS_HALTED (0x00000040)
+#define DTD_STATUS_DATA_BUFF_ERR (0x00000020)
+#define DTD_STATUS_TRANSACTION_ERR (0x00000008)
+#define DTD_RESERVED_FIELDS (0x80007300)
+#define DTD_ADDR_MASK (0xFFFFFFE0)
+#define DTD_PACKET_SIZE (0x7FFF0000)
+#define DTD_LENGTH_BIT_POS (16)
+#define DTD_ERROR_MASK (DTD_STATUS_HALTED | \
+ DTD_STATUS_DATA_BUFF_ERR | \
+ DTD_STATUS_TRANSACTION_ERR)
+
+/*-------------------------------------------------------------------------*/
+
+/* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */
+struct transfer_descriptor {
+ unsigned int next_td_ptr; /* Next TD pointer(31-5), T(0) set
+ indicate invalid */
+ unsigned int size_ioc_sts; /* Total bytes (30-16), IOC (15),
+ MultO(11-10), STS (7-0) */
+ unsigned int buff_ptr0; /* Buffer pointer Page 0 */
+ unsigned int buff_ptr1; /* Buffer pointer Page 1 */
+ unsigned int buff_ptr2; /* Buffer pointer Page 2 */
+ unsigned int buff_ptr3; /* Buffer pointer Page 3 */
+ unsigned int buff_ptr4; /* Buffer pointer Page 4 */
+ unsigned int reserved;
+} __attribute__ ((packed));
+
+static struct transfer_descriptor _td_array[NUM_ENDPOINTS*2] __attribute((aligned (32)));
+static struct transfer_descriptor* td_array;
+
+/* manual: 32.13.1 Endpoint Queue Head (dQH) */
+struct queue_head {
+ unsigned int max_pkt_length; /* Mult(31-30) , Zlt(29) , Max Pkt len
+ and IOS(15) */
+ unsigned int curr_dtd_ptr; /* Current dTD Pointer(31-5) */
+ struct transfer_descriptor dtd; /* dTD overlay */
+ unsigned int setup_buffer[2]; /* Setup data 8 bytes */
+ unsigned int reserved[4];
+} __attribute__((packed));
+
+static struct queue_head _qh_array[NUM_ENDPOINTS*2] __attribute((aligned (2048)));
+static struct queue_head* qh_array;
+
+
+static const unsigned int pipe2mask[NUM_ENDPOINTS*2] = {
+ 0x01, 0x010000,
+ 0x02, 0x020000,
+ 0x04, 0x040000,
+};
+
+/*-------------------------------------------------------------------------*/
+static void transfer_completed(void);
+static void prime_transfer(int endpoint, void* ptr, int len, bool send);
+static void bus_reset(void);
+static void init_queue_heads(void);
+static void init_endpoints(void);
+/*-------------------------------------------------------------------------*/
+
+
+/* manual: 32.14.1 Device Controller Initialization */
+void usb_drv_init(void)
+{
+ REG_USBCMD &= ~USBCMD_RUN;
+ udelay(50000);
+ REG_USBCMD |= USBCMD_CTRL_RESET;
+ while (REG_USBCMD & USBCMD_CTRL_RESET);
+
+ REG_USBMODE = USBMODE_CTRL_MODE_DEVICE;
+
+ td_array = (struct transfer_descriptor*)UNCACHED_ADDR(&_td_array);
+ qh_array = (struct queue_head*)UNCACHED_ADDR(&_qh_array);
+ init_queue_heads();
+ memset(td_array, 0, sizeof _td_array);
+
+ REG_ENDPOINTLISTADDR = (unsigned int)qh_array;
+ REG_DEVICEADDR = 0;
+
+ /* enable USB interrupts */
+ REG_USBINTR =
+ USBINTR_INT_EN |
+ USBINTR_ERR_INT_EN |
+ USBINTR_PTC_DETECT_EN |
+ USBINTR_RESET_EN |
+ USBINTR_SYS_ERR_EN;
+
+ /* enable USB IRQ in CPU */
+ CPU_INT_EN |= USB_MASK;
+
+ /* go go go */
+ REG_USBCMD |= USBCMD_RUN;
+
+ logf("usb_drv_init() finished");
+ logf("usb id %x", REG_ID);
+ logf("usb dciversion %x", REG_DCIVERSION);
+ logf("usb dccparams %x", REG_DCCPARAMS);
+
+ /* now a bus reset will occur. see bus_reset() */
+}
+
+void usb_drv_exit(void)
+{
+ /* disable interrupts */
+ REG_USBINTR = 0;
+
+ /* stop usb controller */
+ REG_USBCMD &= ~USBCMD_RUN;
+}
+
+void usb_drv_int(void)
+{
+ unsigned int status = REG_USBSTS;
+
+#if 0
+ if (status & USBSTS_INT) logf("int: usb ioc");
+ if (status & USBSTS_ERR) logf("int: usb err");
+ if (status & USBSTS_PORT_CHANGE) logf("int: portchange");
+ if (status & USBSTS_RESET) logf("int: reset");
+ if (status & USBSTS_SYS_ERR) logf("int: syserr");
+#endif
+
+ /* usb transaction interrupt */
+ if (status & USBSTS_INT) {
+ REG_USBSTS |= USBSTS_INT;
+
+ /* a control packet? */
+ if (REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0) {
+ /* copy setup data from packet */
+ unsigned int tmp[2];
+ tmp[0] = qh_array[0].setup_buffer[0];
+ tmp[1] = qh_array[0].setup_buffer[1];
+
+ /* acknowledge packet recieved */
+ REG_ENDPTSETUPSTAT |= EPSETUP_STATUS_EP0;
+
+ usb_core_control_request((struct usb_ctrlrequest*)tmp);
+ }
+
+ if (REG_ENDPTCOMPLETE)
+ transfer_completed();
+ }
+
+ /* error interrupt */
+ if (status & USBSTS_ERR) {
+ REG_USBSTS |= USBSTS_ERR;
+ logf("usb error int");
+ }
+
+ /* reset interrupt */
+ if (status & USBSTS_RESET) {
+ REG_USBSTS |= USBSTS_RESET;
+ bus_reset();
+ usb_core_bus_reset(); /* tell mom */
+ }
+
+ /* port change */
+ if (status & USBSTS_PORT_CHANGE) {
+ REG_USBSTS |= USBSTS_PORT_CHANGE;
+ }
+}
+
+void usb_drv_stall(int endpoint, bool stall)
+{
+ logf("%sstall %d", stall?"":"un", endpoint);
+
+ if (stall) {
+ REG_ENDPTCTRL(endpoint) |= EPCTRL_RX_EP_STALL;
+ REG_ENDPTCTRL(endpoint) |= EPCTRL_TX_EP_STALL;
+ }
+ else {
+ REG_ENDPTCTRL(endpoint) &= ~EPCTRL_RX_EP_STALL;
+ REG_ENDPTCTRL(endpoint) &= ~EPCTRL_TX_EP_STALL;
+ }
+}
+
+void usb_drv_send(int endpoint, void* ptr, int length)
+{
+ prime_transfer(endpoint, ptr, length, true);
+}
+
+void usb_drv_recv(int endpoint, void* ptr, int length)
+{
+ //logf("usbrecv(%x, %d)", ptr, length);
+ prime_transfer(endpoint, ptr, length, false);
+}
+
+void usb_drv_wait(int endpoint, bool send)
+{
+ int pipe = endpoint * 2 + (send ? 1 : 0);
+ struct queue_head* qh = &qh_array[pipe];
+
+ while (qh->dtd.size_ioc_sts & QH_STATUS_ACTIVE) {
+ if (REG_USBSTS & USBSTS_RESET)
+ break;
+ }
+}
+
+
+void usb_drv_set_address(int address)
+{
+ REG_DEVICEADDR = address << USBDEVICEADDRESS_BIT_POS;
+ init_endpoints();
+}
+
+void usb_drv_reset_endpoint(int endpoint, bool send)
+{
+ int pipe = endpoint * 2 + (send ? 1 : 0);
+ unsigned int mask = pipe2mask[pipe];
+ REG_ENDPTFLUSH = mask;
+ while (REG_ENDPTFLUSH & mask);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* manual: 32.14.5.2 */
+static void prime_transfer(int endpoint, void* ptr, int len, bool send)
+{
+ int timeout;
+ int pipe = endpoint * 2 + (send ? 1 : 0);
+ unsigned int mask = pipe2mask[pipe];
+ struct transfer_descriptor* td = &td_array[pipe];
+ struct queue_head* qh = &qh_array[pipe];
+
+ if (send && endpoint > EP_CONTROL) {
+ logf("usb: sent %d bytes", len);
+ }
+
+ memset(td, 0, sizeof(struct transfer_descriptor));
+ td->next_td_ptr = DTD_NEXT_TERMINATE;
+ td->size_ioc_sts = (len << DTD_LENGTH_BIT_POS) |
+ DTD_STATUS_ACTIVE | DTD_IOC;
+ td->buff_ptr0 = (unsigned int)ptr;
+ td->buff_ptr1 = (unsigned int)ptr + 0x1000;
+ td->buff_ptr2 = (unsigned int)ptr + 0x2000;
+ td->buff_ptr3 = (unsigned int)ptr + 0x3000;
+ td->buff_ptr4 = (unsigned int)ptr + 0x4000;
+ td->reserved = len;
+ qh->dtd.next_td_ptr = (unsigned int)td;
+ qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE);
+
+ REG_ENDPTPRIME |= mask;
+
+ timeout = 10000;
+ while ((REG_ENDPTPRIME & mask) && --timeout) {
+ if (REG_USBSTS & USBSTS_RESET)
+ break;
+ }
+ if (!timeout) {
+ logf("prime timeout");
+ }
+
+ if (!(REG_ENDPTSTATUS & mask)) {
+ logf("no prime! %d %d %x", endpoint, pipe, qh->dtd.size_ioc_sts & 0xff );
+ }
+
+ if (send) {
+ /* wait for transfer to finish */
+ timeout = 100000;
+ while ((td->size_ioc_sts & DTD_STATUS_ACTIVE) && --timeout) {
+ if (REG_ENDPTCOMPLETE & mask)
+ REG_ENDPTCOMPLETE |= mask;
+
+ if (REG_USBSTS & USBSTS_RESET)
+ return;
+ }
+ if (!timeout) {
+ logf("td never finished");
+ return;
+ }
+ }
+}
+
+static void transfer_completed(void)
+{
+ int i;
+ unsigned int mask = REG_ENDPTCOMPLETE;
+ REG_ENDPTCOMPLETE |= mask;
+
+ //logf("usb comp %x", mask);
+
+ for (i=0; i<NUM_ENDPOINTS; i++) {
+ int x;
+ for (x=0; x<2; x++) {
+ int pipe = i * 2 + x;
+ if (mask & pipe2mask[pipe])
+ usb_core_transfer_complete(i, x ? true : false);
+
+ if ((mask & pipe2mask[pipe]) &&
+ (td_array[pipe].size_ioc_sts & DTD_ERROR_MASK)) {
+ logf("pipe %d err %x", pipe, td_array[pipe].size_ioc_sts & DTD_ERROR_MASK);
+ }
+ }
+ }
+}
+
+/* manual: 32.14.2.1 Bus Reset */
+static void bus_reset(void)
+{
+ int i;
+ logf("usb bus_reset");
+
+ REG_DEVICEADDR = 0;
+ REG_ENDPTSETUPSTAT = REG_ENDPTSETUPSTAT;
+ REG_ENDPTCOMPLETE = REG_ENDPTCOMPLETE;
+
+ for (i=0; i<100; i++) {
+ if (!REG_ENDPTPRIME)
+ break;
+
+ if (REG_USBSTS & USBSTS_RESET) {
+ logf("usb: double reset");
+ return;
+ }
+
+ udelay(100);
+ }
+ if (REG_ENDPTPRIME) {
+ logf("usb: short reset timeout");
+ }
+
+ REG_ENDPTFLUSH = ~0;
+ //while (REG_ENDPTFLUSH);
+
+ if (!(REG_PORTSC1 & PORTSCX_PORT_RESET)) {
+ logf("usb: slow reset!");
+ }
+}
+
+/* manual: 32.14.4.1 Queue Head Initialization */
+static void init_queue_heads(void)
+{
+ memset(qh_array, 0, sizeof _qh_array);
+
+ /*** control ***/
+ qh_array[EP_CONTROL].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS | QH_IOS;
+ qh_array[EP_CONTROL].dtd.next_td_ptr = QH_NEXT_TERMINATE;
+ qh_array[EP_CONTROL+1].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS;
+ qh_array[EP_CONTROL+1].dtd.next_td_ptr = QH_NEXT_TERMINATE;
+
+ /*** bulk ***/
+ qh_array[EP_RX*2].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS;
+ qh_array[EP_RX*2].dtd.next_td_ptr = QH_NEXT_TERMINATE;
+ qh_array[EP_TX*2+1].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS;
+ qh_array[EP_TX*2+1].dtd.next_td_ptr = QH_NEXT_TERMINATE;
+}
+
+static void init_endpoints(void)
+{
+ /* bulk */
+ REG_ENDPTCTRL(EP_RX) =
+ EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE |
+ (EPCTRL_EP_TYPE_BULK << EPCTRL_RX_EP_TYPE_SHIFT) |
+ (EPCTRL_EP_TYPE_BULK << EPCTRL_TX_EP_TYPE_SHIFT);
+
+ REG_ENDPTCTRL(EP_TX) =
+ EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE |
+ (EPCTRL_EP_TYPE_BULK << EPCTRL_RX_EP_TYPE_SHIFT) |
+ (EPCTRL_EP_TYPE_BULK << EPCTRL_TX_EP_TYPE_SHIFT);
+}
diff --git a/firmware/target/arm/usb-fw-pp502x.c b/firmware/target/arm/usb-fw-pp502x.c
index d8eb0c6352..2d9a52ead8 100644
--- a/firmware/target/arm/usb-fw-pp502x.c
+++ b/firmware/target/arm/usb-fw-pp502x.c
@@ -27,15 +27,13 @@
#include "button.h"
#include "ata.h"
#include "string.h"
-#include "arcotg_udc.h"
-
#ifdef HAVE_USBSTACK
-#include "usbstack.h"
+#include "usb_core.h"
#endif
void usb_init_device(void)
{
- int r0;
+ /* enable usb module */
GPO32_ENABLE |= 0x200;
outl(inl(0x7000002C) | 0x3000000, 0x7000002C);
@@ -46,41 +44,9 @@ void usb_init_device(void)
DEV_INIT2 |= INIT_USB;
while ((inl(0x70000028) & 0x80) == 0);
-
- UDC_PORTSC1 |= PORTSCX_PORT_RESET;
- while ((UDC_PORTSC1 & PORTSCX_PORT_RESET) != 0);
-
- UDC_OTGSC |= 0x5F000000;
- if( (UDC_OTGSC & 0x100) == 0) {
- UDC_USBMODE &=~ USB_MODE_CTRL_MODE_HOST;
- UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
- outl(inl(0x70000028) | 0x4000, 0x70000028);
- outl(inl(0x70000028) | 0x2, 0x70000028);
- } else {
- UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
- outl(inl(0x70000028) &~0x4000, 0x70000028);
- outl(inl(0x70000028) | 0x2, 0x70000028);
- }
-
-
- UDC_USBCMD |= USB_CMD_CTRL_RESET;
- while((UDC_USBCMD & USB_CMD_CTRL_RESET) != 0);
-
- r0 = UDC_PORTSC1;
-
- /* Note from IPL source (referring to next 5 lines of code:
- THIS NEEDS TO BE CHANGED ONCE THERE IS KERNEL USB */
- DEV_INIT2 |= INIT_USB;
- DEV_EN |= DEV_USB;
- while ((inl(0x70000028) & 0x80) == 0);
outl(inl(0x70000028) | 0x2, 0x70000028);
-
udelay(0x186A0);
-#ifndef HAVE_USBSTACK
- dr_controller_setup();
-#endif
-
#if defined(IPOD_COLOR) || defined(IPOD_4G) \
|| defined(IPOD_MINI) || defined(IPOD_MINI2G)
/* GPIO C bit 1 is firewire detect */
@@ -92,9 +58,10 @@ void usb_init_device(void)
void usb_enable(bool on)
{
#ifdef HAVE_USBSTACK
- if (!on) {
- usb_stack_stop();
- }
+ if (on)
+ usb_core_init();
+ else
+ usb_core_exit();
#else
/* This device specific code will eventually give way to proper USB
handling, which should be the same for all PP502x targets. */
@@ -131,11 +98,6 @@ void usb_enable(bool on)
int usb_detect(void)
{
- static int countdown = 0;
- static int status = USB_EXTRACTED;
- static bool prev_usbstatus1 = false;
- bool usbstatus1, usbstatus2;
-
#if defined(IPOD_COLOR) || defined(IPOD_4G) \
|| defined(IPOD_MINI) || defined(IPOD_MINI2G)
/* GPIO C bit 1 is firewire detect */
@@ -143,75 +105,19 @@ int usb_detect(void)
return USB_INSERTED;
#endif
- if (countdown > 0)
- {
- countdown--;
-
- usbstatus2 = (UDC_PORTSC1 & PORTSCX_CURRENT_CONNECT_STATUS) ? true : false;
- if ((countdown == 0) || usbstatus2)
- {
- countdown = 0;
- status = usbstatus2 ? USB_INSERTED : USB_POWERED;
-#ifndef HAVE_USBSTACK
- dr_controller_stop();
-#endif
- }
- return status;
- }
-
- /* UDC_ID should have the bit format:
- [31:24] = 0x0
- [23:16] = 0x22 (Revision number)
- [15:14] = 0x3 (Reserved)
- [13:8] = 0x3a (NID - 1's compliment of ID)
- [7:6] = 0x0 (Reserved)
- [5:0] = 0x05 (ID) */
- if (UDC_ID != 0x22FA05) {
- /* This should never occur - do we even need to test? */
- return USB_EXTRACTED;
- }
-
- usbstatus1 = (UDC_OTGSC & 0x800) ? true : false;
-
- if (usbstatus1 == prev_usbstatus1)
- {
- /* Nothing has changed, so just return previous status */
- return status;
- }
- prev_usbstatus1 = usbstatus1;
-
- if (!usbstatus1)
- { /* We have just been disconnected */
- status = USB_EXTRACTED;
- return status;
- }
-
- /* We now know that we have just been connected to either a charger
- or a computer */
-
- if((button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON)
- {
- /* The user wants to charge, so it doesn't matter what we are
- connected to. */
-
- status = USB_POWERED;
- return status;
- }
-
- /* Run the USB controller for long enough to detect if we're connected
- to a computer, then stop it again. */
-
-#ifndef HAVE_USBSTACK
- dr_controller_run();
-#else
- usb_stack_start();
+#if defined(SANSA_C200)
+ /* GPIO H bit 1 is usb detect */
+ if (GPIOH_INPUT_VAL & 0x02)
+ return USB_INSERTED;
+#elif defined(SANSA_E200)
+ /* GPIO B bit 4 is usb detect */
+ if (GPIOB_INPUT_VAL & 0x10)
+ return USB_INSERTED;
+#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
+ /* GPIO L bit 2 is usb detect */
+ if (GPIOL_INPUT_VAL & 0x4)
+ return USB_INSERTED;
#endif
- /* Wait for 50 ticks (500ms) before deciding there is no computer
- attached. The required value varied a lot between different users
- when this feature was being tested. */
-
- countdown = 50;
-
- return status;
+ return USB_EXTRACTED;
}
diff --git a/firmware/usb.c b/firmware/usb.c
index f4b92f07d0..75ee4759ca 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -87,9 +87,11 @@ static void usb_slave_mode(bool on)
else
{
DEBUGF("Leaving USB slave mode\n");
-
+
+#ifndef HAVE_USBSTACK
/* Let the ISDx00 settle */
sleep(HZ*1);
+#endif
usb_enable(false);
@@ -402,7 +404,7 @@ bool usb_charging_enabled(void)
/* TODO: implement it for other targets... */
#endif
- logf("usb_charging_enabled: %s\n", rc ? "true" : "false" );
+ logf("usb charging %s", rc ? "enabled" : "disabled" );
return rc;
}
#endif
diff --git a/firmware/usbstack/controller.h b/firmware/usbstack/controller.h
deleted file mode 100644
index c91eab785a..0000000000
--- a/firmware/usbstack/controller.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#ifndef _USBSTACK_CONTROLLER_H_
-#define _USBSTACK_CONTROLLER_H_
-
-/*
- * stack datatypes
- */
-struct usb_response {
- void* buf;
- uint32_t length;
-};
-
-struct usb_ep {
- const char name[15];
- uint8_t type;
- uint32_t ep_num; /* which endpoint? */
- uint32_t pipe_num; /* which pipe? */
- uint32_t maxpacket;
- bool claimed;
-
- struct usb_endpoint_descriptor *desc;
- struct list_head list;
-};
-
-struct usb_controller {
- const char* name;
- enum usb_controller_type type;
- enum usb_device_speed speed;
- void (*init)(void);
- void (*shutdown)(void);
- void (*irq)(void);
- void (*start)(void);
- void (*stop)(void);
- void* controller_ops;
- struct usb_device_driver* device_driver;
- struct usb_host_driver* host_driver;
- struct usb_ep* ep0;
- struct usb_ep endpoints;
-};
-
-struct usb_dcd_controller_ops {
- /* endpoint management */
- int (*enable)(struct usb_ep* ep, struct usb_endpoint_descriptor* desc);
- int (*disable)(struct usb_ep* ep);
- int (*set_halt)(struct usb_ep* ep, bool hald);
-
- /* transmitting */
- int (*send)(struct usb_ep* ep, struct usb_response* req);
- int (*receive)(struct usb_ep* ep, struct usb_response* res);
-
- /* ep0 */
- struct usb_ep* ep0;
-};
-
-int usb_controller_register(struct usb_controller* ctrl);
-int usb_controller_unregister(struct usb_controller* ctrl);
-
-/*
- * dcd - device controller driver
- */
-void usb_dcd_init(void);
-void usb_dcd_shutdown(void);
-
-/*
- * hcd - host controller driver
- */
-void usb_hcd_init(void);
-void usb_hcd_shutdown(void);
-
-#endif /*_USBSTACK_CONTROLLER_H_*/
diff --git a/firmware/usbstack/core.h b/firmware/usbstack/core.h
deleted file mode 100644
index c47232f120..0000000000
--- a/firmware/usbstack/core.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#ifndef _USBSTACK_CORE_H_
-#define _USBSTACK_CORE_H_
-
-#include "linkedlist.h"
-#include "usb_ch9.h"
-#include "logf.h"
-#include "system.h"
-
-#include "usbstack.h"
-
-#include "usbstack/controller.h"
-#include "usbstack/device.h"
-#include "usbstack/host.h"
-
-#define NUM_DRIVERS 3
-
-/*
- * usb core
- */
-struct usb_core {
- /* we can have maximum two controllers (one device, one host) */
- struct usb_controller* controller[2];
- struct usb_controller* active_controller;
- /* device driver used by stack */
- struct usb_device_driver* device_driver;
- /* for each type of driver use own array */
- struct usb_host_driver* host_drivers[NUM_DRIVERS];
- struct usb_device_driver* device_drivers[NUM_DRIVERS];
- enum usb_controller_type mode;
- bool running;
-};
-
-void usb_stack_irq(void);
-void usb_stack_work(void);
-
-/* endpoint configuration */
-void usb_ep_autoconfig_reset(void);
-struct usb_ep* usb_ep_autoconfig(struct usb_endpoint_descriptor* desc);
-
-/* only used for debug */
-void into_usb_ctrlrequest(struct usb_ctrlrequest* request);
-
-extern struct usb_core usbcore;
-
-#endif /*_USBSTACK_CORE_H_*/
diff --git a/firmware/usbstack/core/config.c b/firmware/usbstack/core/config.c
deleted file mode 100644
index 1a9b12508e..0000000000
--- a/firmware/usbstack/core/config.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * Based on linux/drivers/usb/gadget/config.c
- * Copyright (C) 2003 David Brownell
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include <string.h>
-#include "usbstack/core.h"
-
-static int usb_descriptor_fillbuf(void* buf, unsigned buflen,
- struct usb_descriptor_header** src)
-{
- uint8_t* dest = buf;
-
- if (!src) {
- return -EINVAL;
- }
-
- /* fill buffer from src[] until null descriptor ptr */
- for (; 0 != *src; src++) {
- unsigned len = (*src)->bLength;
-
- if (len > buflen)
- return -EINVAL;
-
- memcpy(dest, *src, len);
- buflen -= len;
- dest += len;
- }
- return dest - (uint8_t *)buf;
-}
-
-int usb_stack_configdesc(const struct usb_config_descriptor* config, void* buf,
- unsigned length, struct usb_descriptor_header** desc)
-{
- struct usb_config_descriptor* cp = buf;
- int len;
-
- if (length < USB_DT_CONFIG_SIZE || !desc) {
- return -EINVAL;
- }
-
- /* config descriptor first */
- *cp = *config;
-
- /* then interface/endpoint/class/vendor/... */
- len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (uint8_t*)buf,
- length - USB_DT_CONFIG_SIZE, desc);
-
- if (len < 0) {
- return len;
- }
-
- len += USB_DT_CONFIG_SIZE;
- if (len > 0xffff) {
- return -EINVAL;
- }
-
- /* patch up the config descriptor */
- cp->bLength = USB_DT_CONFIG_SIZE;
- cp->bDescriptorType = USB_DT_CONFIG;
- cp->wTotalLength = len;
- cp->bmAttributes |= USB_CONFIG_ATT_ONE;
-
- return len;
-}
diff --git a/firmware/usbstack/core/core.c b/firmware/usbstack/core/core.c
deleted file mode 100644
index f72b3bbed8..0000000000
--- a/firmware/usbstack/core/core.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include <errno.h>
-#include <string.h>
-#include <ctype.h>
-#include "config.h"
-
-#include "usbstack.h"
-#include "usbstack/core.h"
-#include "usbstack/controller.h"
-#include "usbstack/drivers/device/usb_serial.h"
-#include "usbstack/drivers/device/usb_storage.h"
-
-struct usb_core usbcore;
-
-/* private used functions */
-static void update_driver_names(unsigned char* result);
-static void bind_device_driver(struct usb_device_driver* driver);
-
-/**
- * Initialize usb stack.
- */
-void usb_stack_init(void)
-{
- int i;
- logf("usb_stack_init");
-
- /* init datastructures */
- usbcore.controller[0] = NULL;
- usbcore.controller[1] = NULL;
- usbcore.active_controller = NULL;
- usbcore.device_driver = NULL;
- usbcore.running = false;
-
- memset(&device_driver_names, 0, USB_STACK_MAX_SETTINGS_NAME);
-
- /* init arrays */
- for (i = 0; i < NUM_DRIVERS; i++) {
- usbcore.device_drivers[i] = NULL;
- usbcore.host_drivers[i] = NULL;
- }
-
- /* init controllers */
-#if (USBSTACK_CAPS & CONTROLLER_DEVICE)
- usb_dcd_init();
-#endif
-
-#if (USBSTACK_CAPS & CONTROLLER_HOST)
- usb_hcd_init();
-#endif
-
- /* init drivers */
- usb_serial_driver_init();
- usb_storage_driver_init();
-}
-
-/**
- * Start processing of usb stack. This function init
- * active usb controller.
- */
-void usb_stack_start(void)
-{
- /* are we allready running? */
- if (usbcore.running) {
- logf("allready running!");
- return;
- }
-
- if (usbcore.active_controller == NULL) {
- logf("no active controller!");
- return;
- }
-
- /* forward to controller */
- logf("starting controller");
- usbcore.active_controller->start();
- usbcore.running = true;
-
- /* look if started controller is a device controller
- * and if it has a device driver bind to it */
- logf("check for auto bind");
- if (usbcore.active_controller->type == DEVICE) {
- if (usbcore.active_controller->device_driver == NULL &&
- usbcore.device_driver != NULL) {
- /* bind driver */
- logf("binding...");
- bind_device_driver(usbcore.device_driver);
- }
- }
-}
-
-/**
- * Stop processing of usb stack. This function shutsdown
- * active usb controller.
- */
-void usb_stack_stop(void)
-{
- /* are we allready stopped? */
- if (usbcore.running == false) {
- return;
- }
-
- /* forward to controller */
- usbcore.active_controller->stop();
- usbcore.running = false;
-}
-
-/**
- * Gets called by upper layers to indicate that there is
- * an interrupt waiting for the controller.
- */
-void usb_stack_irq(void)
-{
- /* simply notify usb controller */
- if (usbcore.active_controller != NULL &&
- usbcore.active_controller->irq != NULL) {
- usbcore.active_controller->irq();
- }
-}
-
-/**
- * If a host device controller is loaded, we need to have a function
- * to call for maintanence. We need to check if a new device has connected,
- * find suitable drivers for new devices.
- */
-void usb_stack_work(void)
-{
- /* TODO will be used with host device controllers
- * and needs to be called in a loop (thread) */
-}
-
-/**
- * Register an usb controller in the stack. The stack can
- * only have two controllers registered at one time.
- * One device host controller and one host device controller.
- *
- * @param ctrl pointer to controller to register.
- * @return 0 on success else a defined error code.
- */
-int usb_controller_register(struct usb_controller* ctrl)
-{
- if (ctrl == NULL) {
- return EINVAL;
- }
-
- logf("usb_stack: register usb ctrl");
- logf(" -> name: %s", ctrl->name);
- logf(" -> type: %d", ctrl->type);
-
- switch (ctrl->type) {
- case DEVICE:
- if (usbcore.controller[0] == NULL) {
- usbcore.controller[0] = ctrl;
- return 0;
- }
- break;
- case HOST:
- if (usbcore.controller[1] == NULL) {
- usbcore.controller[1] = ctrl;
- return 0;
- }
- break;
- default:
- return EINVAL;
- }
-
- return ENOFREESLOT;
-}
-
-/**
- * Unregister an usb controller from the stack.
- *
- * @param ctrl pointer to controller to unregister.
- * @return 0 on success else a defined error code.
- */
-int usb_controller_unregister(struct usb_controller* ctrl)
-{
-
- if (ctrl == NULL) {
- return EINVAL;
- }
-
- switch (ctrl->type) {
- case DEVICE:
- if (usbcore.controller[0] == ctrl) {
- usbcore.controller[0] = NULL;
- return 0;
- }
- break;
- case HOST:
- if (usbcore.controller[1] == ctrl) {
- usbcore.controller[1] = NULL;
- return 0;
- }
- break;
- default:
- return EINVAL;
- }
-
- return 0; /* never reached */
-}
-
-/**
- * Select an usb controller and active it.
- *
- * @param type of controller to activate.
- */
-void usb_controller_select(int type)
-{
- struct usb_controller* new = NULL;
-
- /* check if a controller of the wanted type is already loaded */
- if (usbcore.active_controller != NULL &&
- (int)usbcore.active_controller->type == type) {
- logf("controller already set");
- return;
- }
-
- logf("usb_controller_select");
- logf(" -> type: %d", type);
-
- usbcore.mode = type;
-
- switch (type) {
- case DEVICE:
- new = usbcore.controller[0];
- break;
- case HOST:
- new = usbcore.controller[1];
- break;
- }
-
- /* if there is only one controller, stop here */
- if (new == NULL) {
- logf("no suitable cntrl found");
- return;
- }
-
- /* shutdown current used controller */
- if (usbcore.active_controller != NULL) {
- logf("shuting down old one");
- usbcore.active_controller->shutdown();
- }
-
- /* set and init new controller */
- usbcore.active_controller = new;
- logf("init controller");
- usbcore.active_controller->init();
-}
-
-int usb_stack_get_mode(void)
-{
- return usbcore.mode;
-}
-
-/**
- * Register an usb device driver.
- *
- * @param driver pointer to an usb_device_driver struct.
- * @return 0 on success, else a defined error code.
- */
-int usb_device_driver_register(struct usb_device_driver* driver)
-{
- int i;
-
- if (driver == NULL) {
- return EINVAL;
- }
-
- /* add to linked list */
- logf("usb_stack: register usb driver");
- for (i = 0; i < NUM_DRIVERS; i++) {
- if (usbcore.device_drivers[i] == NULL) {
- usbcore.device_drivers[i] = driver;
- update_driver_names(device_driver_names);
- return 0;
- }
- }
-
- update_driver_names(device_driver_names);
-
- return 0;
-}
-
-int usb_device_driver_bind(const char* name)
-{
- int i;
- struct usb_device_driver *tmp = NULL;
- struct usb_device_driver *driver = NULL;
-
- if (name == NULL) {
- return EINVAL;
- }
-
- /* look for driver */
- logf("looking for driver %s", name);
- for (i = 0; i < NUM_DRIVERS; i++) {
- tmp = usbcore.device_drivers[i];
- if (tmp != NULL && strcmp(name, tmp->name) == 0) {
- driver = tmp;
- }
- }
-
- if (driver == NULL) {
- logf("no driver found");
- return ENODRIVERFOUND;
- }
-
- /* look if there is an usb controller loaded */
- if (usbcore.active_controller == NULL) {
- /* safe choosen driver and set it when controller starts */
- usbcore.device_driver = driver;
-
- } else {
-
- /* we need to have an active dcd controller */
- if (usbcore.active_controller->type != DEVICE) {
- logf("wrong type");
- return EWRONGCONTROLLERTYPE;
- }
-
- /* bind driver to controller */
- bind_device_driver(driver);
- }
-
- return 0;
-}
-
-void usb_device_driver_unbind(void)
-{
- logf("usb_device_driver_unbind");
- if (usbcore.active_controller->device_driver != NULL) {
- usbcore.active_controller->device_driver->unbind();
- usbcore.active_controller->device_driver = NULL;
- }
-
- usbcore.device_driver = NULL;
-}
-
-static void update_driver_names(unsigned char* result)
-{
- int i;
- int pos = 0;
- unsigned char terminator = ',';
- struct usb_device_driver* dd = NULL;
-
- /* reset buffer, iterate through drivers and add to char array */
- memset(result, 0, USB_STACK_MAX_SETTINGS_NAME);
- for (i = 0; i < NUM_DRIVERS; i++) {
- int len;
- dd = usbcore.device_drivers[i];
-
- if (dd != NULL) {
- len = strlen(dd->name);
- if (pos > 0) {
- memcpy(result + pos, &terminator, 1);
- pos++;
- }
- memcpy(result + pos, dd->name, len);
- pos += len;
- }
- }
-}
-
-static void bind_device_driver(struct usb_device_driver* driver)
-{
- int ret = 0;
-
- /* look if there is an old driver */
- if (usbcore.active_controller->device_driver != NULL) {
- usbcore.active_controller->device_driver->unbind();
- }
-
- /* bind driver to controller */
- usbcore.active_controller->device_driver = driver;
-
- /* init dirver */
- ret = driver->bind(usbcore.active_controller->controller_ops);
-
- if (ret != 0) {
- logf("binding of %s failed", driver->name);
- usbcore.active_controller->device_driver = NULL;
- usbcore.device_driver = NULL;
- }
-}
diff --git a/firmware/usbstack/core/epsetup.c b/firmware/usbstack/core/epsetup.c
deleted file mode 100644
index ef98935fe3..0000000000
--- a/firmware/usbstack/core/epsetup.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include <string.h>
-#include <ctype.h>
-#include "usbstack/core.h"
-
-/**
- *
- * Naming Convention for Endpoint Names
- *
- * - ep1, ep2, ... address is fixed, not direction or type
- * - ep1in, ep2out, ... address and direction are fixed, not type
- * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
- * - ep1in-bulk, ep2out-iso, ... all three are fixed
- * - ep-* ... no functionality restrictions
- *
- * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
- *
- */
-static int ep_matches(struct usb_ep* ep, struct usb_endpoint_descriptor* desc);
-
-void usb_ep_autoconfig_reset(void)
-{
- struct usb_ep* ep = NULL;
- if (usbcore.active_controller == NULL) {
- return;
- }
-
- logf("resetting endpoints");
- list_for_each_entry(ep, &usbcore.active_controller->endpoints.list, list) {
- logf("reset %s", ep->name);
- ep->claimed = false;
- }
-}
-
-/**
- * Find a suitable endpoint for the requested endpoint descriptor.
- * @param desc usb descritpro to use for seraching.
- * @return NULL or a valid endpoint.
- */
-struct usb_ep* usb_ep_autoconfig(struct usb_endpoint_descriptor* desc)
-{
- struct usb_ep* ep = NULL;
- if (usbcore.active_controller == NULL) {
- logf("active controller NULL");
- return NULL;
- }
-
- list_for_each_entry(ep, &usbcore.active_controller->endpoints.list, list) {
- if (ep_matches (ep, desc)) {
- return ep;
- }
- }
-
- return NULL;
-}
-
-static int ep_matches(struct usb_ep* ep, struct usb_endpoint_descriptor* desc)
-{
- uint8_t type;
- const char* tmp;
- uint16_t max;
-
- /* endpoint already claimed? */
- if (ep->claimed) {
- logf("!! claimed !!");
- return 0;
- }
-
- /* only support ep0 for portable CONTROL traffic */
- type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
- if (type == USB_ENDPOINT_XFER_CONTROL) {
- logf("type == control");
- return 0;
- }
-
- /* some other naming convention */
- if (ep->name[0] != 'e') {
- logf("wrong name");
- return 0;
- }
-
- /* type-restriction: "-iso", "-bulk", or "-int".
- * direction-restriction: "in", "out".
- */
- if (ep->name[2] != '-' ) {
- tmp = strrchr (ep->name, '-');
- if (tmp) {
- switch (type) {
- case USB_ENDPOINT_XFER_INT:
- /* bulk endpoints handle interrupt transfers,
- * except the toggle-quirky iso-synch kind
- */
- if (tmp[2] == 's') { // == "-iso"
- return 0;
- }
- break;
- case USB_ENDPOINT_XFER_BULK:
- if (tmp[1] != 'b') { // != "-bulk"
- return 0;
- }
- break;
- case USB_ENDPOINT_XFER_ISOC:
- if (tmp[2] != 's') { // != "-iso"
- return 0;
- }
- }
- } else {
- tmp = ep->name + strlen (ep->name);
- }
-
- /* direction-restriction: "..in-..", "out-.." */
- tmp--;
- if (!isdigit(*tmp)) {
- if (desc->bEndpointAddress & USB_DIR_IN) {
- if ('n' != *tmp) {
- return 0;
- }
- } else {
- if ('t' != *tmp) {
- return 0;
- }
- }
- }
- }
-
-
- /* endpoint maxpacket size is an input parameter, except for bulk
- * where it's an output parameter representing the full speed limit.
- * the usb spec fixes high speed bulk maxpacket at 512 bytes.
- */
- max = 0x7ff & desc->wMaxPacketSize;
-
- switch (type) {
- case USB_ENDPOINT_XFER_INT:
- /* INT: limit 64 bytes full speed, 1024 high speed */
- if ((usbcore.active_controller->speed != USB_SPEED_HIGH) &&
- (max > 64)) {
- return 0;
- }
- /* FALLTHROUGH */
-
- case USB_ENDPOINT_XFER_ISOC:
- if ((usbcore.active_controller->speed != USB_SPEED_HIGH) &&
- (max > 1023)) {
- return 0;
- }
- break;
- }
-
- /* MATCH!! */
-
- /* set address of used ep in desc */
- desc->bEndpointAddress |= ep->ep_num;
- ep->desc = desc;
-
- return 1;
-}
diff --git a/firmware/usbstack/core/utils.c b/firmware/usbstack/core/utils.c
deleted file mode 100644
index d43bd9290f..0000000000
--- a/firmware/usbstack/core/utils.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * Based on linux/drivers/usb/gadget/usbstring.c
- * Copyright (C) 2003 David Brownell
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include <string.h>
-#include "usbstack/core.h"
-
-void into_usb_ctrlrequest(struct usb_ctrlrequest* request)
-{
- char* type = "";
- char* req = "";
- char* extra = 0;
-
- logf("-usb request-");
- /* check if packet is okay */
- if (request->bRequestType == 0 &&
- request->bRequest == 0 &&
- request->wValue == 0 &&
- request->wIndex == 0 &&
- request->wLength == 0) {
- logf(" -> INVALID <-");
- return;
- }
-
- switch (request->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- type = "standard";
-
- switch (request->bRequest) {
- case USB_REQ_GET_STATUS:
- req = "get status";
- break;
- case USB_REQ_CLEAR_FEATURE:
- req = "clear feature";
- break;
- case USB_REQ_SET_FEATURE:
- req = "set feature";
- break;
- case USB_REQ_SET_ADDRESS:
- req = "set address";
- break;
- case USB_REQ_GET_DESCRIPTOR:
- req = "get descriptor";
-
- switch (request->wValue >> 8) {
- case USB_DT_DEVICE:
- extra = "get device descriptor";
- break;
- case USB_DT_DEVICE_QUALIFIER:
- extra = "get device qualifier";
- break;
- case USB_DT_OTHER_SPEED_CONFIG:
- extra = "get other-speed config descriptor";
- case USB_DT_CONFIG:
- extra = "get configuration descriptor";
- break;
- case USB_DT_STRING:
- extra = "get string descriptor";
- break;
- case USB_DT_DEBUG:
- extra = "debug";
- break;
- }
- break;
-
- break;
- case USB_REQ_SET_DESCRIPTOR:
- req = "set descriptor";
- break;
- case USB_REQ_GET_CONFIGURATION:
- req = "get configuration";
- break;
- case USB_REQ_SET_CONFIGURATION:
- req = "set configuration";
- break;
- case USB_REQ_GET_INTERFACE:
- req = "get interface";
- break;
- case USB_REQ_SET_INTERFACE:
- req = "set interface";
- break;
- case USB_REQ_SYNCH_FRAME:
- req = "sync frame";
- break;
- default:
- req = "unkown";
- break;
- }
-
- break;
- case USB_TYPE_CLASS:
- type = "class";
- break;
-
- case USB_TYPE_VENDOR:
- type = "vendor";
- break;
- }
-
- logf(" -b 0x%x", request->bRequestType);
- logf(" -b 0x%x", request->bRequest);
- logf(" -b 0x%x", request->wValue);
- logf(" -b 0x%x", request->wIndex);
- logf(" -b 0x%x", request->wLength);
- logf(" -> t: %s", type);
- logf(" -> r: %s", req);
- if (extra != 0) {
- logf(" -> e: %s", extra);
- }
-}
-
-int usb_stack_get_string(struct usb_string* strings, int id, uint8_t* buf)
-{
- struct usb_string* tmp;
- char* sp, *dp;
- int len;
-
- /* if id is 0, then we need to send back all supported
- * languages. In our case we only support one
- * language: en-us (0x0409) */
- if (id == 0) {
- buf [0] = 4;
- buf [1] = USB_DT_STRING;
- buf [2] = (uint8_t) 0x0409;
- buf [3] = (uint8_t) (0x0409 >> 8);
- return 4;
- }
-
- /* look for string */
- for (tmp = strings; tmp && tmp->s; tmp++) {
- if (tmp->id == id) {
- break;
- }
- }
-
- /* did we found it? */
- if (!tmp || !tmp->s) {
- return -EINVAL;
- }
-
- len = MIN ((size_t) 126, strlen (tmp->s));
- memset(buf + 2, 0, 2 * len);
-
- /* convert to utf-16le */
- sp = (char*)tmp->s;
- dp = (char*)&buf[2];
-
- while (*sp) {
- *dp++ = *sp++;
- *dp++ = 0;
- }
-
- /* write len and tag */
- buf [0] = (len + 1) * 2;
- buf [1] = USB_DT_STRING;
-
- return buf[0];
-}
diff --git a/firmware/usbstack/device.h b/firmware/usbstack/device.h
deleted file mode 100644
index f1052ff9ab..0000000000
--- a/firmware/usbstack/device.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#ifndef _USBSTACK_DEVICE_H_
-#define _USBSTACK_DEVICE_H_
-
-/*
- * usb device driver
- */
-struct usb_device_driver {
- const char* name;
- int (*bind)(void* controller_ops);
- void (*unbind)(void);
- int (*request)(struct usb_ctrlrequest* req);
- void (*suspend)(void);
- void (*resume)(void);
- void (*speed)(enum usb_device_speed speed);
- void* data; /* used to store controller specific ops struct */
-};
-
-int usb_device_driver_register(struct usb_device_driver* driver);
-
-/* forward declaration */
-struct usb_config_descriptor;
-struct usb_descriptor_header;
-
-int usb_stack_configdesc(const struct usb_config_descriptor* config,
- void* buf, unsigned length,
- struct usb_descriptor_header** desc);
-
-#endif /*_USBSTACK_DEVICE_H_*/
diff --git a/firmware/usbstack/drivers/device/usb_serial.c b/firmware/usbstack/drivers/device/usb_serial.c
deleted file mode 100644
index 51def1c3b6..0000000000
--- a/firmware/usbstack/drivers/device/usb_serial.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include <string.h>
-#include "usb_serial.h"
-#include "usbstack/utils.h"
-
-static struct usb_dcd_controller_ops* ops;
-
-struct usb_device_driver usb_serial_driver = {
- .name = "serial",
- .bind = usb_serial_driver_bind,
- .unbind = usb_serial_driver_unbind,
- .request = usb_serial_driver_request,
- .suspend = NULL,
- .resume = NULL,
- .speed = usb_serial_driver_speed,
-};
-
-/*-------------------------------------------------------------------------*/
-/* usb descriptors */
-
-#define MANUFACTURER_STR_ID 1
-#define PRODUCT_STR_ID 2
-#define SERIAL_STR_ID 3
-#define BULK_CONFIG_STR_ID 4
-#define DATA_STR_ID 5
-
-/* static strings, in UTF-8 */
-static struct usb_string strings[] = {
- { MANUFACTURER_STR_ID, "RockBox" },
- { PRODUCT_STR_ID, "RockBox Serial Driver" },
- { SERIAL_STR_ID, "0" },
- { BULK_CONFIG_STR_ID, "Serial Bulk" },
- { DATA_STR_ID, "Serial Data" },
-};
-
-#define BULK_CONFIG_ID 1
-
-static struct usb_device_descriptor serial_device_desc = {
- .bLength = USB_DT_DEVICE_SIZE,
- .bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = 0x0200,
- .bDeviceClass = USB_CLASS_COMM,
- .bDeviceSubClass = 0,
- .bDeviceProtocol = 0,
- .idVendor = 0x0525,
- .idProduct = 0xa4a6,
- .iManufacturer = MANUFACTURER_STR_ID,
- .iProduct = PRODUCT_STR_ID,
- .iSerialNumber = SERIAL_STR_ID,
- .bNumConfigurations = 1,
-};
-
-static struct usb_config_descriptor serial_bulk_config_desc = {
- .bLength = USB_DT_CONFIG_SIZE,
- .bDescriptorType = USB_DT_CONFIG,
-
- .bNumInterfaces = 1,
- .bConfigurationValue = BULK_CONFIG_ID,
- .iConfiguration = BULK_CONFIG_STR_ID,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1,
-};
-
-static struct usb_interface_descriptor serial_bulk_interface_desc = {
- .bLength = USB_DT_INTERFACE_SIZE,
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_CDC_DATA,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
- .iInterface = DATA_STR_ID,
-};
-
-static struct usb_endpoint_descriptor serial_fs_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 8,
-};
-
-static struct usb_endpoint_descriptor serial_fs_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 8,
-};
-
-static struct usb_debug_descriptor serial_debug_desc = {
- .bLength = sizeof(struct usb_debug_descriptor),
- .bDescriptorType = USB_DT_DEBUG,
-};
-
-static struct usb_qualifier_descriptor serial_qualifier_desc = {
- .bLength = sizeof(struct usb_qualifier_descriptor),
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
- .bcdUSB = 0x0200,
- .bDeviceClass = USB_CLASS_COMM,
- .bNumConfigurations = 1,
-};
-
-struct usb_descriptor_header *serial_fs_function[] = {
- (struct usb_descriptor_header *) &serial_bulk_interface_desc,
- (struct usb_descriptor_header *) &serial_fs_in_desc,
- (struct usb_descriptor_header *) &serial_fs_out_desc,
- NULL,
-};
-
-/* USB 2.0 */
-static struct usb_endpoint_descriptor serial_hs_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 512,
-};
-
-static struct usb_endpoint_descriptor serial_hs_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 512,
-};
-
-struct usb_descriptor_header *serial_hs_function[] = {
- (struct usb_descriptor_header *) &serial_bulk_interface_desc,
- (struct usb_descriptor_header *) &serial_hs_in_desc,
- (struct usb_descriptor_header *) &serial_hs_out_desc,
- NULL,
-};
-
-#define BUFFER_SIZE 100
-uint8_t buf[BUFFER_SIZE];
-
-struct usb_response res;
-
-/* helper functions */
-static int config_buf(uint8_t *buf, uint8_t type, unsigned index);
-static int set_config(int config);
-
-struct device {
- struct usb_ep* in;
- struct usb_ep* out;
- uint32_t used_config;
- struct usb_descriptor_header** descriptors;
-};
-
-static struct device dev;
-
-/*-------------------------------------------------------------------------*/
-
-void usb_serial_driver_init(void)
-{
- logf("usb serial: register");
- usb_device_driver_register(&usb_serial_driver);
-}
-
-/*-------------------------------------------------------------------------*/
-
-int usb_serial_driver_bind(void* controler_ops)
-{
- logf("usb serial: bind");
- ops = controler_ops;
-
- /* serach and asign endpoints */
- usb_ep_autoconfig_reset();
-
- dev.in = usb_ep_autoconfig(&serial_fs_in_desc);
- if (!dev.in) {
- goto autoconf_fail;
- }
- dev.in->claimed = true;
- logf("usb serial: in: %s", dev.in->name);
-
- dev.out = usb_ep_autoconfig(&serial_fs_out_desc);
- if (!dev.out) {
- goto autoconf_fail;
- }
- dev.out->claimed = true;
- logf("usb serial: out: %s", dev.out->name);
-
- /* update device decsriptor */
- serial_device_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
-
- /* update qualifie descriptor */
- serial_qualifier_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
-
- /* update debug descriptor */
- serial_debug_desc.bDebugInEndpoint = dev.in->ep_num;
- serial_debug_desc.bDebugOutEndpoint = dev.out->ep_num;
-
- /* update hs descriptors as we asume that endpoints
- are the same for fs and hs */
- serial_hs_in_desc.bEndpointAddress = serial_fs_in_desc.bEndpointAddress;
- serial_hs_out_desc.bEndpointAddress = serial_fs_out_desc.bEndpointAddress;
-
- return 0;
-
-autoconf_fail:
- logf("failed to find endpoints");
- return -EOPNOTSUPP;
-}
-
-void usb_serial_driver_unbind(void) {
-
- /* disable endpoints... */
-}
-
-int usb_serial_driver_request(struct usb_ctrlrequest* request)
-{
- int ret = -EOPNOTSUPP;
- logf("usb serial: request");
-
- res.length = 0;
- res.buf = NULL;
-
- switch (request->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
-
- switch (request->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
-
- switch (request->wValue >> 8) {
- case USB_DT_DEVICE:
- logf("usb serial: sending device desc");
- ret = MIN(sizeof(struct usb_device_descriptor),
- request->wLength);
- res.buf = &serial_device_desc;
- break;
-
- case USB_DT_DEVICE_QUALIFIER:
- logf("usb serial: sending qualifier dec");
- ret = MIN(sizeof(struct usb_qualifier_descriptor),
- request->wLength);
- res.buf = &serial_qualifier_desc;
- break;
-
- case USB_DT_OTHER_SPEED_CONFIG:
- case USB_DT_CONFIG:
- logf("usb serial: sending config desc");
-
- ret = config_buf(buf, request->wValue >> 8,
- request->wValue & 0xff);
- if (ret >= 0) {
- logf("%d, vs %d", request->wLength, ret);
- ret = MIN(request->wLength, (uint16_t)ret);
- }
- res.buf = buf;
- break;
-
- case USB_DT_DEBUG:
- logf("usb serial: sending debug desc");
- ret = MIN(sizeof(struct usb_debug_descriptor),
- request->wLength);
- res.buf = &serial_debug_desc;
- break;
-
- case USB_DT_STRING:
- logf("usb serial: sending string desc");
- ret = usb_stack_get_string(strings, request->wValue & 0xff,
- buf);
- ret = MIN(ret, request->wLength);
- res.buf = buf;
- break;
- }
- break;
-
- case USB_REQ_SET_CONFIGURATION:
- logf("usb serial: set configuration %d", request->wValue);
- ret = set_config(request->wValue);
- break;
-
- case USB_REQ_GET_CONFIGURATION:
- logf("usb serial: get configuration");
- ret = 1;
- res.buf = &dev.used_config;
- break;
- }
- }
-
- if (ret >= 0) {
- res.length = ret;
- ret = ops->send(NULL, &res);
- }
-
- return ret;
-}
-
-void usb_serial_driver_speed(enum usb_device_speed speed)
-{
- switch (speed) {
- case USB_SPEED_HIGH:
- logf("usb serial: using highspeed");
- dev.descriptors = serial_hs_function;
- break;
- default:
- logf("usb serial: using fullspeed");
- dev.descriptors = serial_fs_function;
- break;
- }
-}
-
-/*-------------------------------------------------------------------------*/
-/* helper functions */
-
-static int config_buf(uint8_t *buf, uint8_t type, unsigned index)
-{
- int len;
-
- /* TODO check index*/
- (void)index;
-
- len = usb_stack_configdesc(&serial_bulk_config_desc, buf, BUFFER_SIZE,
- dev.descriptors);
- if (len < 0) {
- return len;
- }
- ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
- return len;
-}
-
-static int set_config(int config)
-{
- /* TODO check config*/
-
- /* enable endpoints */
- logf("setup %s", dev.in->name);
- ops->enable(dev.in, (struct usb_endpoint_descriptor*)dev.descriptors[1]);
- logf("setup %s", dev.out->name);
- ops->enable(dev.out, (struct usb_endpoint_descriptor*)dev.descriptors[2]);
-
- /* store config */
- logf("using config %d", config);
- dev.used_config = config;
-
- return 0;
-}
diff --git a/firmware/usbstack/drivers/device/usb_storage.c b/firmware/usbstack/drivers/device/usb_storage.c
deleted file mode 100644
index 01419da778..0000000000
--- a/firmware/usbstack/drivers/device/usb_storage.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Christian Gmeiner
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include <string.h>
-#include "usb_storage.h"
-#include "usbstack/utils.h"
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_dcd_controller_ops* ops;
-
-struct usb_device_driver usb_storage_driver = {
- .name = "storage",
- .bind = usb_storage_driver_bind,
- .unbind = usb_storage_driver_unbind,
- .request = usb_storage_driver_request,
- .suspend = NULL,
- .resume = NULL,
- .speed = usb_storage_driver_speed,
-};
-
-/*-------------------------------------------------------------------------*/
-
-#define PROTO_BULK 0x50 // Bulk only
-#define SUBCL_SCSI 0x06 // Transparent SCSI
-
-/* Bulk-only class specific requests */
-#define USB_BULK_RESET_REQUEST 0xff
-#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe
-
-/*-------------------------------------------------------------------------*/
-/* usb descriptors */
-
-#define MANUFACTURER_STR_ID 1
-#define PRODUCT_STR_ID 2
-#define SERIAL_STR_ID 3
-#define CONFIG_STR_ID 4
-#define DATA_STR_ID 5
-
-/* static strings, in UTF-8 */
-static struct usb_string strings[] = {
- { MANUFACTURER_STR_ID, "RockBox" },
- { PRODUCT_STR_ID, "RockBox Storage Driver" },
- { SERIAL_STR_ID, "0" },
- { CONFIG_STR_ID, "Storage Bulk" },
- { DATA_STR_ID, "Storage Data" },
-};
-
-static struct usb_device_descriptor storage_device_desc = {
- .bLength = USB_DT_DEVICE_SIZE,
- .bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = 0x0200,
- .bDeviceClass = 0,
- .bDeviceSubClass = 0,
- .bDeviceProtocol = 0,
- .idVendor = 0xffff,
- .idProduct = 0x0001,
- .iManufacturer = MANUFACTURER_STR_ID,
- .iProduct = PRODUCT_STR_ID,
- .iSerialNumber = SERIAL_STR_ID,
- .bNumConfigurations = 1,
-};
-
-static struct usb_config_descriptor storage_config_desc = {
- .bLength = USB_DT_CONFIG_SIZE,
- .bDescriptorType = USB_DT_CONFIG,
-
- .bNumInterfaces = 1,
- .bConfigurationValue = 1,
- .iConfiguration = CONFIG_STR_ID,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 250, /* 500mA in 2mA units */
-};
-
-static struct usb_interface_descriptor storage_interface_desc = {
- .bLength = USB_DT_INTERFACE_SIZE,
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_MASS_STORAGE,
- .bInterfaceSubClass = SUBCL_SCSI,
- .bInterfaceProtocol = PROTO_BULK,
- .iInterface = DATA_STR_ID,
-};
-
-static struct usb_endpoint_descriptor storage_fs_bulk_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 64,
-};
-
-static struct usb_endpoint_descriptor storage_fs_bulk_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 64,
-};
-
-static struct usb_qualifier_descriptor storage_qualifier_desc = {
- .bLength = sizeof(struct usb_qualifier_descriptor),
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
- .bcdUSB = 0x0200,
- .bDeviceClass = 0,
- .bNumConfigurations = 1,
-};
-
-struct usb_descriptor_header *storage_fs_function[] = {
- (struct usb_descriptor_header *) &storage_interface_desc,
- (struct usb_descriptor_header *) &storage_fs_bulk_in_desc,
- (struct usb_descriptor_header *) &storage_fs_bulk_out_desc,
- NULL,
-};
-
-/* USB 2.0 */
-static struct usb_endpoint_descriptor storage_hs_bulk_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 512,
-};
-
-static struct usb_endpoint_descriptor storage_hs_bulk_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = 512,
-};
-
-struct usb_descriptor_header *storage_hs_function[] = {
- (struct usb_descriptor_header *) &storage_interface_desc,
- (struct usb_descriptor_header *) &storage_hs_bulk_in_desc,
- (struct usb_descriptor_header *) &storage_hs_bulk_out_desc,
- NULL,
-};
-
-#define BUFFER_SIZE 100
-uint8_t buf[BUFFER_SIZE];
-
-struct usb_response res;
-
-/* helper functions */
-static int config_buf(uint8_t *buf, uint8_t type, unsigned index);
-static int set_config(int config);
-static int set_interface_alt_setting(int interface_alt_setting);
-
-struct device {
- struct usb_ep* in;
- struct usb_ep* out;
- struct usb_ep* intr;
- uint32_t used_config;
- uint32_t used_interface_alt_setting;
- struct usb_descriptor_header** descriptors;
-};
-
-static struct device dev;
-
-/*-------------------------------------------------------------------------*/
-
-void usb_storage_driver_init(void)
-{
- logf("usb storage: register");
- usb_device_driver_register(&usb_storage_driver);
-}
-
-/*-------------------------------------------------------------------------*/
-/* device driver ops */
-
-int usb_storage_driver_bind(void* controler_ops)
-{
- ops = controler_ops;
-
- /* serach and asign endpoints */
- usb_ep_autoconfig_reset();
-
- dev.in = usb_ep_autoconfig(&storage_fs_bulk_in_desc);
- if (!dev.in) {
- goto autoconf_fail;
- }
- dev.in->claimed = true;
- logf("usb storage: in: %s", dev.in->name);
-
- dev.out = usb_ep_autoconfig(&storage_fs_bulk_out_desc);
- if (!dev.out) {
- goto autoconf_fail;
- }
- dev.out->claimed = true;
- logf("usb storage: out: %s", dev.out->name);
-
- /* update device decsriptor */
- storage_device_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
-
- /* update hs descriptors as we asume that endpoints
- are the same for fs and hs */
- storage_hs_bulk_in_desc.bEndpointAddress =
- storage_fs_bulk_in_desc.bEndpointAddress;
- storage_hs_bulk_out_desc.bEndpointAddress =
- storage_fs_bulk_out_desc.bEndpointAddress;
-
- return 0;
-
-autoconf_fail:
- logf("failed to find endpoints");
- return -EOPNOTSUPP;
-}
-
-void usb_storage_driver_unbind(void)
-{
-
- /* disable endpoints... */
-}
-
-int usb_storage_driver_request(struct usb_ctrlrequest* request)
-{
- int ret = -EOPNOTSUPP;
- logf("usb storage: request");
-
- res.length = 0;
- res.buf = NULL;
-
- switch (request->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
-
- switch (request->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
-
- switch (request->wValue >> 8) {
- case USB_DT_DEVICE:
- logf("usb storage: sending device desc");
- ret = MIN(sizeof(struct usb_device_descriptor),
- request->wLength);
- res.buf = &storage_device_desc;
- break;
-
- case USB_DT_DEVICE_QUALIFIER:
- logf("usb storage: sending qualifier dec");
- ret = MIN(sizeof(struct usb_qualifier_descriptor),
- request->wLength);
- res.buf = &storage_qualifier_desc;
- break;
-
- case USB_DT_OTHER_SPEED_CONFIG:
- case USB_DT_CONFIG:
- logf("usb storage: sending config desc");
-
- ret = config_buf(buf, request->wValue >> 8,
- request->wValue & 0xff);
- if (ret >= 0) {
- logf("%d, vs %d", request->wLength, ret);
- ret = MIN(request->wLength, (uint16_t)ret);
- }
- res.buf = buf;
- break;
-
- case USB_DT_STRING:
- logf("usb storage: sending string desc");
- ret = usb_stack_get_string(strings, request->wValue & 0xff,
- buf);
- ret = MIN(ret, request->wLength);
- res.buf = buf;
- break;
- }
- break;
-
- case USB_REQ_SET_CONFIGURATION:
- logf("usb storage: set configuration %d", request->wValue);
- ret = set_config(request->wValue);
- break;
-
- case USB_REQ_GET_CONFIGURATION:
- logf("usb storage: get configuration");
- ret = 1;
- res.buf = &dev.used_config;
- break;
-
- case USB_REQ_GET_INTERFACE:
- logf("usb storage: get interface");
- ret = 1;
- res.buf = &dev.used_interface_alt_setting;
- break;
-
- case USB_REQ_SET_INTERFACE:
- logf("usb storage: set interface");
- ret = set_interface_alt_setting(request->wValue);
- break;
- }
-
- case USB_TYPE_CLASS:
-
- switch (request->bRequest) {
- case USB_BULK_RESET_REQUEST:
- logf("usb storage: bulk reset");
- break;
-
- case USB_BULK_GET_MAX_LUN_REQUEST:
- logf("usb storage: get max lun");
- /* we support no LUNs (Logical Unit Number) */
- buf[0] = 0;
- ret = 1;
- break;
- }
- break;
- }
-
- if (ret >= 0) {
- res.length = ret;
- ret = ops->send(NULL, &res);
- }
-
- return ret;
-}
-
-void usb_storage_driver_speed(enum usb_device_speed speed)
-{
- switch (speed) {
- case USB_SPEED_HIGH:
- logf("usb storage: using highspeed");
- dev.descriptors = storage_hs_function;
- break;
- default:
- logf("usb storage: using fullspeed");
- dev.descriptors = storage_fs_function;
- break;
- }
-}
-
-/*-------------------------------------------------------------------------*/
-/* S/GET CONFIGURATION helpers */
-
-static int config_buf(uint8_t *buf, uint8_t type, unsigned index)
-{
- int len;
-
- (void)index;
-
- len = usb_stack_configdesc(&storage_config_desc, buf, BUFFER_SIZE,
- dev.descriptors);
- logf("result %d", len);
- if (len < 0) {
- return len;
- }
- ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
- return len;
-}
-
-static int set_config(int config)
-{
- /* enable endpoints */
- logf("setup %s", dev.in->name);
- ops->enable(dev.in, (struct usb_endpoint_descriptor*)dev.descriptors[1]);
- logf("setup %s", dev.out->name);
- ops->enable(dev.out, (struct usb_endpoint_descriptor*)dev.descriptors[2]);
-
- dev.used_config = config;
-
- /* setup buffers */
-
- return 0;
-}
-
-static int set_interface_alt_setting(int interface_alt_setting)
-{
- dev.used_interface_alt_setting = interface_alt_setting;
-
- return 0;
-}
-
diff --git a/firmware/usbstack/usb_benchmark.c b/firmware/usbstack/usb_benchmark.c
new file mode 100644
index 0000000000..a6e0e2d3e7
--- /dev/null
+++ b/firmware/usbstack/usb_benchmark.c
@@ -0,0 +1,125 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: $
+ *
+ * Copyright (C) 2007 by Bjrn Stenberg
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "system.h"
+#include "usb_core.h"
+#include "usb_drv.h"
+//#define LOGF_ENABLE
+#include "logf.h"
+
+static int current_length;
+
+static unsigned char _input_buffer[16384];
+static unsigned char* input_buffer = USB_IRAM_ORIGIN + 1024;
+
+static void ack_control(struct usb_ctrlrequest* req);
+
+static enum {
+ IDLE,
+ SENDING,
+ RECEIVING
+} state = IDLE;
+
+
+void usb_benchmark_init(void)
+{
+ int i;
+ for (i=0; i<128; i++)
+ input_buffer[i] = i;
+}
+
+void usb_benchmark_control_request(struct usb_ctrlrequest* req)
+{
+ int todo;
+ //usb_max_pkt_size = sizeof _input_buffer;
+ usb_max_pkt_size = 64;
+
+ switch (req->bRequest) {
+ case 1: /* read */
+ ack_control(req);
+ current_length = req->wValue * req->wIndex;
+ logf("bench: read %d", current_length);
+ todo = MIN(usb_max_pkt_size, current_length);
+ state = SENDING;
+ usb_drv_reset_endpoint(EP_TX, true);
+ usb_drv_send(EP_TX, &input_buffer, todo);
+ current_length -= todo;
+ break;
+
+ case 2: /* write */
+ ack_control(req);
+ current_length = req->wValue * req->wIndex;
+ logf("bench: write %d", current_length);
+ state = RECEIVING;
+ usb_drv_reset_endpoint(EP_RX, false);
+ usb_drv_recv(EP_RX, &input_buffer, sizeof _input_buffer);
+ break;
+ }
+}
+
+void usb_benchmark_transfer_complete(int endpoint, bool in)
+{
+ (void)in;
+
+ /* see what remains to transfer */
+ if (current_length == 0) {
+ logf("we're done");
+ state = IDLE;
+ return; /* we're done */
+ }
+
+ switch (state)
+ {
+ case SENDING: {
+ int todo = MIN(usb_max_pkt_size, current_length);
+ if (endpoint == EP_RX) {
+ logf("unexpected ep_rx");
+ break;
+ }
+
+ logf("bench: %d more tx", current_length);
+ usb_drv_send(EP_TX, &input_buffer, todo);
+ current_length -= todo;
+ input_buffer[0]++;
+ break;
+ }
+
+ case RECEIVING:
+ if (endpoint == EP_TX) {
+ logf("unexpected ep_tx");
+ break;
+ }
+
+ /* re-prime endpoint */
+ usb_drv_recv(EP_RX, &input_buffer, sizeof _input_buffer);
+ input_buffer[0]++;
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+static void ack_control(struct usb_ctrlrequest* req)
+{
+ if (req->bRequestType & 0x80)
+ usb_drv_recv(EP_CONTROL, NULL, 0);
+ else
+ usb_drv_send(EP_CONTROL, NULL, 0);
+}
diff --git a/firmware/usbstack/utils.h b/firmware/usbstack/usb_benchmark.h
index 4b368a9126..84853a1656 100644
--- a/firmware/usbstack/utils.h
+++ b/firmware/usbstack/usb_benchmark.h
@@ -5,9 +5,9 @@
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
- * $Id$
+ * $Id: $
*
- * Copyright (C) 2007 by Peter D'Hoye
+ * Copyright (C) 2007 by Bjrn Stenberg
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
@@ -16,10 +16,11 @@
* KIND, either express or implied.
*
****************************************************************************/
+#ifndef USB_BENCHMARK_H
+#define USB_BENCHMARK_H
-#ifndef _USBSTACK_UTILS_H_
-#define _USBSTACK_UTILS_H_
+void usb_benchmark_init(void);
+void usb_benchmark_control_request(struct usb_ctrlrequest* req);
+void usb_benchmark_transfer_complete(int endpoint, bool in);
-int usb_stack_get_string(struct usb_string* strings, int id, uint8_t* buf);
-
-#endif /*_USBSTACK_UTILS_H_*/
+#endif
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
new file mode 100644
index 0000000000..e0c4d91338
--- /dev/null
+++ b/firmware/usbstack/usb_core.c
@@ -0,0 +1,537 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: $
+ *
+ * Copyright (C) 2007 by Bjrn Stenberg
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "system.h"
+#include "thread.h"
+#include "kernel.h"
+#include "string.h"
+//#define LOGF_ENABLE
+#include "logf.h"
+
+//#define USB_STORAGE
+//#define USB_BENCHMARK
+#define USB_CHARGING_ONLY
+
+#include "usb_ch9.h"
+#include "usb_drv.h"
+#include "usb_core.h"
+
+#if defined(USB_STORAGE)
+#include "usb_storage.h"
+#elif defined(USB_BENCHMARK)
+#include "usb_benchmark.h"
+#endif
+
+/*-------------------------------------------------------------------------*/
+/* USB protocol descriptors: */
+
+#define USB_SC_SCSI 0x06 /* Transparent */
+#define USB_PROT_BULK 0x50 /* bulk only */
+
+int usb_max_pkt_size = 512;
+
+static const struct usb_device_descriptor device_descriptor = {
+ .bLength = sizeof(struct usb_device_descriptor),
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = 0x0200, /* USB version 2.0 */
+ .bDeviceClass = USB_CLASS_PER_INTERFACE,
+ .bDeviceSubClass = 0,
+ .bDeviceProtocol = 0,
+ .bMaxPacketSize0 = 64,
+ .idVendor = USB_VENDOR_ID,
+ .idProduct = USB_PRODUCT_ID,
+ .bcdDevice = 0x0100,
+ .iManufacturer = 1,
+ .iProduct = 2,
+ .iSerialNumber = 0,
+ .bNumConfigurations = 1
+};
+
+static const struct {
+ struct usb_config_descriptor config_descriptor;
+ struct usb_interface_descriptor interface_descriptor;
+ struct usb_endpoint_descriptor ep1_hs_in_descriptor;
+ struct usb_endpoint_descriptor ep1_hs_out_descriptor;
+} config_data =
+{
+ {
+ .bLength = sizeof(struct usb_config_descriptor),
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength = sizeof config_data,
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .iConfiguration = 0,
+ .bmAttributes = USB_CONFIG_ATT_ONE,
+ .bMaxPower = 250, /* 500mA in 2mA units */
+ },
+
+#ifdef USB_CHARGING_ONLY
+ /* dummy interface for charging-only */
+ {
+ .bLength = sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = 4
+ },
+
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_TX | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 0
+ },
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_RX | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 0
+ }
+#endif
+
+#ifdef USB_STORAGE
+ /* storage interface */
+ {
+ .bLength = sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_MASS_STORAGE,
+ .bInterfaceSubClass = USB_SC_SCSI,
+ .bInterfaceProtocol = USB_PROT_BULK,
+ .iInterface = 0
+ },
+
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_TX | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 512,
+ .bInterval = 0
+ },
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_RX | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 512,
+ .bInterval = 0
+ }
+#endif
+
+#ifdef USB_SERIAL
+ /* serial interface */
+ {
+ .bLength = sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = 0
+ },
+
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_TX | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 512,
+ .bInterval = 0
+ },
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_RX | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 512,
+ .bInterval = 0
+ }
+#endif
+
+#ifdef USB_BENCHMARK
+ /* bulk test interface */
+ {
+ .bLength = sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ .bInterfaceSubClass = 255,
+ .bInterfaceProtocol = 255,
+ .iInterface = 3
+ },
+
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_RX | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+// .wMaxPacketSize = 64,
+ .wMaxPacketSize = 512,
+ .bInterval = 0
+ },
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = EP_TX | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+// .wMaxPacketSize = 64,
+ .wMaxPacketSize = 512,
+ .bInterval = 0
+ }
+#endif
+};
+
+static const struct usb_qualifier_descriptor qualifier_descriptor =
+{
+ .bLength = sizeof(struct usb_qualifier_descriptor),
+ .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
+ .bcdUSB = 0x0200,
+ .bDeviceClass = 0,
+ .bDeviceSubClass = 0,
+ .bDeviceProtocol = 0,
+ .bMaxPacketSize0 = 64,
+ .bNumConfigurations = 1
+};
+
+/* full speed = 12 Mbit */
+static const struct usb_endpoint_descriptor ep1_fs_in_descriptor =
+{
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 0
+};
+
+static const struct usb_endpoint_descriptor ep1_fs_out_descriptor =
+{
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 0
+};
+
+static const struct usb_endpoint_descriptor* ep_descriptors[4] =
+{
+ &config_data.ep1_hs_in_descriptor,
+ &config_data.ep1_hs_out_descriptor,
+ &ep1_fs_in_descriptor,
+ &ep1_fs_out_descriptor
+};
+
+/* this is stringid #0: languages supported */
+static const struct usb_string_descriptor lang_descriptor =
+{
+ sizeof(struct usb_string_descriptor),
+ USB_DT_STRING,
+ {0x0409} /* LANGID US English */
+};
+
+/* this is stringid #1 and up: the actual strings */
+static const struct {
+ unsigned char size;
+ unsigned char type;
+ unsigned short string[32];
+} usb_strings[] =
+{
+ {
+ 16,
+ USB_DT_STRING,
+ {'R','o','c','k','b','o','x'}
+ },
+ {
+ 42,
+ USB_DT_STRING,
+ {'D','i','g','i','t','a','l',' ','a','u','d','i','o',' ','p','l','a','y','e','r'}
+ },
+ {
+ 40,
+ USB_DT_STRING,
+ {'B','u','l','k',' ','t','e','s','t',' ','i','n','t','e','r','f','a','c','e'}
+ },
+ {
+ 28,
+ USB_DT_STRING,
+ {'C','h','a','r','g','i','n','g',' ','o','n','l','y'}
+ }
+};
+
+
+static int usb_address = 0;
+static bool initialized = false;
+static struct event_queue usbcore_queue;
+
+#ifdef USB_STORAGE
+static const char usbcore_thread_name[] = "usb_core";
+static struct thread_entry* usbcore_thread;
+static long usbcore_stack[DEFAULT_STACK_SIZE];
+static void usb_core_thread(void);
+#endif
+
+static void ack_control(struct usb_ctrlrequest* req);
+
+void usb_core_init(void)
+{
+ queue_init(&usbcore_queue, false);
+ usb_drv_init();
+#ifdef USB_STORAGE
+ usb_storage_init();
+ usbcore_thread =
+ create_thread(usb_core_thread, usbcore_stack, sizeof(usbcore_stack), 0,
+ usbcore_thread_name
+ IF_PRIO(, PRIORITY_SYSTEM)
+ IF_COP(, CPU));
+#endif
+
+#ifdef USB_BENCHMARK
+ usb_benchmark_init();
+#endif
+ initialized = true;
+ logf("usb_core_init() finished");
+}
+
+void usb_core_exit(void)
+{
+ if (initialized) {
+ usb_drv_exit();
+ queue_delete(&usbcore_queue);
+#ifdef USB_STORAGE
+ remove_thread(usbcore_thread);
+#endif
+ }
+ logf("usb_core_exit() finished");
+}
+
+#ifdef USB_STORAGE
+void usb_core_thread(void)
+{
+ while (1) {
+ struct queue_event ev;
+
+ queue_wait(&usbcore_queue, &ev);
+
+ usb_storage_transfer_complete(ev.id, ev.data);
+ }
+}
+#endif
+
+/* called by usb_drv_int() */
+void usb_core_control_request(struct usb_ctrlrequest* req)
+{
+ /* note: interrupt context */
+
+#ifdef USB_BENCHMARK
+ if ((req->bRequestType & 0x60) == USB_TYPE_VENDOR) {
+ usb_benchmark_control_request(req);
+ return;
+ }
+#endif
+
+ switch (req->bRequest) {
+ case USB_REQ_SET_CONFIGURATION:
+ logf("usb_core: SET_CONFIG");
+#ifdef USB_STORAGE
+ usb_storage_control_request(req);
+#endif
+ ack_control(req);
+ break;
+
+ case USB_REQ_SET_INTERFACE:
+ logf("usb_core: SET_INTERFACE");
+ ack_control(req);
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+ logf("usb_core: CLEAR_FEATURE");
+ if (req->wValue)
+ usb_drv_stall(req->wIndex, true);
+ else
+ usb_drv_stall(req->wIndex, false);
+ ack_control(req);
+ break;
+
+ case USB_REQ_SET_ADDRESS:
+ usb_address = req->wValue;
+ logf("usb_core: SET_ADR %d", usb_address);
+ ack_control(req);
+ usb_drv_set_address(usb_address);
+ break;
+
+ case USB_REQ_GET_STATUS: {
+ static char tmp[2] = {0,0};
+ tmp[0] = 0;
+ tmp[1] = 0;
+ logf("usb_core: GET_STATUS");
+ usb_drv_send(EP_CONTROL, UNCACHED_ADDR(&tmp), 2);
+ ack_control(req);
+ break;
+ }
+
+ case USB_REQ_GET_DESCRIPTOR: {
+ int index = req->wValue & 0xff;
+ int length = req->wLength;
+ int size;
+ const void* ptr = NULL;
+ logf("usb_core: GET_DESC %d", req->wValue >> 8);
+
+ switch (req->wValue >> 8) { /* type */
+ case USB_DT_DEVICE:
+ ptr = &device_descriptor;
+ size = sizeof device_descriptor;
+ break;
+
+ case USB_DT_CONFIG:
+ ptr = &config_data;
+ size = sizeof config_data;
+ break;
+
+ case USB_DT_STRING:
+ switch (index) {
+ case 0: /* lang descriptor */
+ ptr = &lang_descriptor;
+ size = sizeof lang_descriptor;
+ break;
+
+ default:
+ if ((unsigned)index <= (sizeof(usb_strings)/sizeof(usb_strings[0]))) {
+ index -= 1;
+ ptr = &usb_strings[index];
+ size = usb_strings[index].size;
+ }
+ else {
+ logf("bad string id %d", index);
+ usb_drv_stall(EP_CONTROL, true);
+ }
+ break;
+ }
+ break;
+
+ case USB_DT_INTERFACE:
+ ptr = &config_data.interface_descriptor;
+ size = sizeof config_data.interface_descriptor;
+ break;
+
+ case USB_DT_ENDPOINT:
+ if (index <= NUM_ENDPOINTS) {
+ ptr = &ep_descriptors[index];
+ size = sizeof ep_descriptors[index];
+ }
+ else {
+ logf("bad endpoint %d", index);
+ usb_drv_stall(EP_CONTROL, true);
+ }
+ break;
+
+ case USB_DT_DEVICE_QUALIFIER:
+ ptr = &qualifier_descriptor;
+ size = sizeof qualifier_descriptor;
+ break;
+
+/*
+ case USB_DT_OTHER_SPEED_CONFIG:
+ ptr = &other_speed_descriptor;
+ size = sizeof other_speed_descriptor;
+ break;
+*/
+ default:
+ logf("bad desc %d", req->wValue >> 8);
+ usb_drv_stall(EP_CONTROL, true);
+ break;
+ }
+
+ if (ptr) {
+ length = MIN(size, length);
+ usb_drv_send(EP_CONTROL, (void*)UNCACHED_ADDR(ptr), length);
+ }
+ ack_control(req);
+ break;
+ } /* USB_REQ_GET_DESCRIPTOR */
+
+ default:
+#ifdef USB_STORAGE
+ /* does usb_storage know this request? */
+ if (!usb_storage_control_request(req))
+#endif
+ {
+ /* nope. flag error */
+ logf("usb bad req %d", req->bRequest);
+ usb_drv_stall(EP_CONTROL, true);
+ ack_control(req);
+ }
+ break;
+ }
+}
+
+/* called by usb_drv_int() */
+void usb_core_bus_reset(void)
+{
+ usb_address = 0;
+}
+
+/* called by usb_drv_transfer_completed() */
+void usb_core_transfer_complete(int endpoint, bool in)
+{
+#ifdef USB_CHARGING_ONLY
+ (void)in;
+#endif
+
+ switch (endpoint) {
+ case EP_CONTROL:
+ /* already handled */
+ break;
+
+ case EP_RX:
+ case EP_TX:
+#if defined(USB_BENCHMARK)
+ usb_benchmark_transfer_complete(endpoint, in);
+#elif defined(USB_STORAGE)
+ queue_post(&usbcore_queue, endpoint);
+#endif
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void ack_control(struct usb_ctrlrequest* req)
+{
+ if (req->bRequestType & 0x80)
+ usb_drv_recv(EP_CONTROL, NULL, 0);
+ else
+ usb_drv_send(EP_CONTROL, NULL, 0);
+}
+
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
new file mode 100644
index 0000000000..2c02284dea
--- /dev/null
+++ b/firmware/usbstack/usb_storage.c
@@ -0,0 +1,331 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: $
+ *
+ * Copyright (C) 2007 by Bjrn Stenberg
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "string.h"
+#include "system.h"
+#include "usb_core.h"
+#include "usb_drv.h"
+//#define LOGF_ENABLE
+#include "logf.h"
+#include "ata.h"
+#include "hotswap.h"
+
+#define SECTOR_SIZE 512
+
+/* bulk-only class specific requests */
+#define USB_BULK_RESET_REQUEST 0xff
+#define USB_BULK_GET_MAX_LUN 0xfe
+
+#define DIRECT_ACCESS_DEVICE 0x00 /* disks */
+#define DEVICE_REMOVABLE 0x80
+
+#define CBW_SIGNATURE 0x43425355
+#define CSW_SIGNATURE 0x53425355
+
+#define SCSI_TEST_UNIT_READY 0x00
+#define SCSI_INQUIRY 0x12
+#define SCSI_MODE_SENSE 0x1a
+#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e
+#define SCSI_READ_CAPACITY 0x25
+#define SCSI_READ_10 0x28
+#define SCSI_WRITE_10 0x2a
+
+#define SCSI_STATUS_GOOD 0x00
+#define SCSI_STATUS_CHECK_CONDITION 0x02
+
+
+struct inquiry_data {
+ unsigned char DeviceType;
+ unsigned char DeviceTypeModifier;
+ unsigned char Versions;
+ unsigned char Format;
+ unsigned char AdditionalLength;
+ unsigned char Reserved[2];
+ unsigned char Capability;
+ unsigned char VendorId[8];
+ unsigned char ProductId[16];
+ unsigned char ProductRevisionLevel[4];
+} __attribute__ ((packed));
+
+struct command_block_wrapper {
+ unsigned int signature;
+ unsigned int tag;
+ unsigned int data_transfer_length;
+ unsigned char flags;
+ unsigned char lun;
+ unsigned char command_length;
+ unsigned char command_block[16];
+} __attribute__ ((packed));
+
+struct command_status_wrapper {
+ unsigned int signature;
+ unsigned int tag;
+ unsigned int data_residue;
+ unsigned char status;
+} __attribute__ ((packed));
+
+struct capacity {
+ unsigned int block_count;
+ unsigned int block_size;
+} __attribute__ ((packed));
+
+/* the ARC USB controller can at most buffer 16KB unaligned data */
+static unsigned char _transfer_buffer[16384];
+static unsigned char* transfer_buffer;
+static struct inquiry_data _inquiry;
+static struct inquiry_data* inquiry;
+static struct capacity _capacity_data;
+static struct capacity* capacity_data;
+
+//static unsigned char partial_sector[SECTOR_SIZE];
+
+static struct {
+ unsigned int sector;
+ unsigned int offset; /* if partial sector */
+ unsigned int count;
+ unsigned int tag;
+} current_cmd;
+
+ void handle_scsi(struct command_block_wrapper* cbw);
+ void send_csw(unsigned int tag, int status);
+static void identify2inquiry(void);
+
+static enum {
+ IDLE,
+ SENDING,
+ RECEIVING
+} state = IDLE;
+
+/* called by usb_code_init() */
+void usb_storage_init(void)
+{
+ inquiry = (void*)UNCACHED_ADDR(&_inquiry);
+ transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer);
+ capacity_data = (void*)UNCACHED_ADDR(&_capacity_data);
+ identify2inquiry();
+}
+
+/* called by usb_core_transfer_complete() */
+void usb_storage_transfer_complete(int endpoint)
+{
+ struct command_block_wrapper* cbw = (void*)transfer_buffer;
+
+ switch (endpoint) {
+ case EP_RX:
+ //logf("ums: %d bytes in", length);
+ switch (state) {
+ case IDLE:
+ handle_scsi(cbw);
+ break;
+
+ default:
+ break;
+ }
+
+ /* re-prime endpoint */
+ usb_drv_recv(EP_RX, transfer_buffer, sizeof _transfer_buffer);
+ break;
+
+ case EP_TX:
+ //logf("ums: %d bytes out", length);
+ break;
+ }
+}
+
+/* called by usb_core_control_request() */
+bool usb_storage_control_request(struct usb_ctrlrequest* req)
+{
+ /* note: interrupt context */
+
+ bool handled = false;
+
+ switch (req->bRequest) {
+ case USB_BULK_GET_MAX_LUN: {
+ static char maxlun = 0;
+ logf("ums: getmaxlun");
+ usb_drv_send(EP_CONTROL, UNCACHED_ADDR(&maxlun), 1);
+ usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */
+ handled = true;
+ break;
+ }
+
+ case USB_BULK_RESET_REQUEST:
+ logf("ums: bulk reset");
+ usb_drv_reset_endpoint(EP_RX, false);
+ usb_drv_reset_endpoint(EP_TX, true);
+ usb_drv_send(EP_CONTROL, NULL, 0); /* ack */
+ handled = true;
+ break;
+
+ case USB_REQ_SET_CONFIGURATION:
+ logf("ums: set config");
+ /* prime rx endpoint */
+ usb_drv_recv(EP_RX, transfer_buffer, sizeof _transfer_buffer);
+ handled = true;
+ break;
+ }
+
+ return handled;
+}
+
+/****************************************************************************/
+
+void handle_scsi(struct command_block_wrapper* cbw)
+{
+ /* USB Mass Storage assumes LBA capability.
+ TODO: support 48-bit LBA */
+
+ unsigned int length = cbw->data_transfer_length;
+
+ switch (cbw->command_block[0]) {
+ case SCSI_TEST_UNIT_READY:
+ logf("scsi test_unit_ready");
+ send_csw(cbw->tag, SCSI_STATUS_GOOD);
+ break;
+
+ case SCSI_INQUIRY:
+ logf("scsi inquiry");
+ length = MIN(length, cbw->command_block[4]);
+ usb_drv_send(EP_TX, inquiry, MIN(sizeof _inquiry, length));
+ send_csw(cbw->tag, SCSI_STATUS_GOOD);
+ break;
+
+ case SCSI_MODE_SENSE: {
+ static unsigned char sense_data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ logf("scsi mode_sense");
+ usb_drv_send(EP_TX, UNCACHED_ADDR(&sense_data),
+ MIN(sizeof sense_data, length));
+ send_csw(cbw->tag, SCSI_STATUS_GOOD);
+ break;
+ }
+
+ case SCSI_ALLOW_MEDIUM_REMOVAL:
+ logf("scsi allow_medium_removal");
+ send_csw(cbw->tag, SCSI_STATUS_GOOD);
+ break;
+
+ case SCSI_READ_CAPACITY: {
+ logf("scsi read_capacity");
+#ifdef HAVE_FLASH_STORAGE
+ tCardInfo* cinfo = card_get_info(0);
+ capacity_data->block_count = htobe32(cinfo->numblocks);
+ capacity_data->block_size = htobe32(cinfo->blocksize);
+#else
+ unsigned short* identify = ata_get_identify();
+ capacity_data->block_count = htobe32(identify[60] << 16 | identify[61]);
+ capacity_data->block_size = htobe32(SECTOR_SIZE);
+#endif
+ usb_drv_send(EP_TX, capacity_data,
+ MIN(sizeof _capacity_data, length));
+ send_csw(cbw->tag, SCSI_STATUS_GOOD);
+ break;
+ }
+
+ case SCSI_READ_10:
+ current_cmd.sector =
+ cbw->command_block[2] << 24 |
+ cbw->command_block[3] << 16 |
+ cbw->command_block[4] << 8 |
+ cbw->command_block[5] ;
+ current_cmd.count =
+ cbw->command_block[7] << 16 |
+ cbw->command_block[8];
+ current_cmd.offset = 0;
+ current_cmd.tag = cbw->tag;
+
+ logf("scsi read %d %d", current_cmd.sector, current_cmd.count);
+
+ /* too much? */
+ if (current_cmd.count > (sizeof _transfer_buffer / SECTOR_SIZE)) {
+ send_csw(current_cmd.tag, SCSI_STATUS_CHECK_CONDITION);
+ break;
+ }
+
+ ata_read_sectors(IF_MV2(0,) current_cmd.sector, current_cmd.count,
+ &transfer_buffer);
+ state = SENDING;
+ usb_drv_send(EP_TX, transfer_buffer,
+ MIN(current_cmd.count * SECTOR_SIZE, length));
+ break;
+
+ case SCSI_WRITE_10:
+ logf("scsi write10");
+ break;
+
+ default:
+ logf("scsi unknown cmd %x", cbw->command_block[0]);
+ break;
+ }
+}
+
+void send_csw(unsigned int tag, int status)
+{
+ static struct command_status_wrapper _csw;
+ struct command_status_wrapper* csw = UNCACHED_ADDR(&_csw);
+ csw->signature = CSW_SIGNATURE;
+ csw->tag = tag;
+ csw->data_residue = 0;
+ csw->status = status;
+
+ //logf("csw %x %x", csw->tag, csw->signature);
+ usb_drv_send(EP_TX, csw, sizeof _csw);
+}
+
+/* convert ATA IDENTIFY to SCSI INQUIRY */
+static void identify2inquiry(void)
+{
+ unsigned int i;
+#ifdef HAVE_FLASH_STORAGE
+ for (i=0; i<8; i++)
+ inquiry->VendorId[i] = i + 'A';
+
+ for (i=0; i<8; i++)
+ inquiry->ProductId[i] = i + 'm';
+#else
+ unsigned short* dest;
+ unsigned short* src;
+ unsigned short* identify = ata_get_identify();
+ memset(inquiry, 0, sizeof _inquiry);
+
+ if (identify[82] & 4)
+ inquiry->DeviceTypeModifier = DEVICE_REMOVABLE;
+
+ /* ATA only has a 'model' field, so we copy the
+ first 8 bytes to 'vendor' and the rest to 'product' */
+ src = (unsigned short*)&identify[27];
+ dest = (unsigned short*)&inquiry->VendorId;
+ for (i=0;i<4;i++)
+ dest[i] = src[i];
+
+ src = (unsigned short*)&identify[27+8];
+ dest = (unsigned short*)&inquiry->ProductId;
+ for (i=0;i<8;i++)
+ dest[i] = src[i];
+
+ src = (unsigned short*)&identify[23];
+ dest = (unsigned short*)&inquiry->ProductRevisionLevel;
+ for (i=0;i<2;i++)
+ dest[i] = src[i];
+#endif
+
+ inquiry->DeviceType = DIRECT_ACCESS_DEVICE;
+ inquiry->AdditionalLength = 0x1f;
+ inquiry->Versions = 3; /* ANSI SCSI level 2 */
+ inquiry->Format = 3; /* ANSI SCSI level 2 INQUIRY format */
+}
+
diff --git a/firmware/usbstack/host.h b/firmware/usbstack/usb_storage.h
index b27449c9a6..9067c92c61 100644
--- a/firmware/usbstack/host.h
+++ b/firmware/usbstack/usb_storage.h
@@ -5,9 +5,9 @@
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
- * $Id$
+ * $Id: $
*
- * Copyright (C) 2007 by Christian Gmeiner
+ * Copyright (C) 2007 by Bjrn Stenberg
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
@@ -16,16 +16,15 @@
* KIND, either express or implied.
*
****************************************************************************/
+#ifndef USB_STORAGE_H
+#define USB_STORAGE_H
-#ifndef _USBSTACK_HOST_H_
-#define _USBSTACK_HOST_H_
+#include "usb_ch9.h"
-/*
- * usb host driver
- */
-struct usb_host_driver {
- const char* name;
- void* data; /* used to store controller specific ops struct */
-};
+void usb_storage_init(void);
+void usb_storage_transfer(void* data);
+void usb_storage_transfer_complete(int endpoint);
+bool usb_storage_control_request(struct usb_ctrlrequest* req);
+
+#endif
-#endif /*_USBSTACK_HOST_H_*/
diff --git a/tools/Makefile b/tools/Makefile
index 5b0ef1ba46..17887b2d48 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -87,6 +87,9 @@ wavtrim: wavtrim.c
voicefont: voicefont.c
$(SILENT)$(CC) -g $+ -o $@
+usb_benchmark: usb_benchmark.c
+ $(SILENT)$(CC) -g -lusb $+ -o $@
+
clean:
@echo "Cleaning tools"
$(SILENT)rm -f $(CLEANALL) $(shell for f in $(CLEANALL) ; do echo $$f.exe $$f.o $$f.obj ; done) *.ajf *~
diff --git a/tools/usb_benchmark.c b/tools/usb_benchmark.c
new file mode 100644
index 0000000000..6d4b27ccbf
--- /dev/null
+++ b/tools/usb_benchmark.c
@@ -0,0 +1,212 @@
+/*
+ LPCUSB, an USB device driver for LPC microcontrollers
+ Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*
+ Simple benchmarking application.
+
+ It talks with the 'custom' device application on the LPC214x through
+ libusb.
+
+ 2007-11-01: Some minor modifications by <bjorn@haxx.se>
+
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/timeb.h>
+
+#include "usb.h"
+
+// types
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+typedef unsigned int U32;
+typedef unsigned char U8;
+
+#define MAX_TIME 3000
+
+static unsigned char abData[16384];
+
+// USB device specific definitions
+#define VENDOR_ID 0x0781
+#define PRODUCT_ID 0x7450
+
+#define BM_REQUEST_TYPE (2<<5)
+#define BULK_IN_EP 0x82
+#define BULK_OUT_EP 0x05
+
+// this structure should match with the expectations of the 'custom' device!
+typedef struct {
+ U32 dwAddress;
+ U32 dwLength;
+} TMemoryCmd;
+
+
+static struct usb_device * find_device(int iVendor, int iProduct)
+{
+ struct usb_bus *usb_bus;
+ struct usb_device *dev;
+
+ for (usb_bus = usb_get_busses(); usb_bus; usb_bus = usb_bus->next) {
+ for (dev = usb_bus->devices; dev; dev = dev->next) {
+ if ((dev->descriptor.idVendor == iVendor) &&
+ (dev->descriptor.idProduct == iProduct)) {
+ return dev;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+static struct timeb start;
+
+static void starttimer(void)
+{
+ ftime(&start);
+}
+
+static int stoptimer(void)
+{
+ struct timeb now;
+
+ ftime(&now);
+ return 1000 * (now.time - start.time) + now.millitm - start.millitm;
+}
+
+
+int main(void)
+{
+ const int blocksize[] = { 128, 512 };
+ struct usb_device *dev;
+ struct usb_dev_handle *hdl;
+ int i, j;
+ U32 dwBlockSize, dwChunk, dwBytes;
+ TMemoryCmd MemCmd;
+ int iTimer;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ for (i=0; i<sizeof abData/4; i++)
+ ((unsigned int*)abData)[i] = i;
+
+ dev = find_device(VENDOR_ID, PRODUCT_ID);
+ if (dev == NULL) {
+ fprintf(stderr, "device not found\n");
+ return -1;
+ }
+
+ hdl = usb_open(dev);
+
+ i = usb_set_configuration(hdl, 1);
+ if (i < 0) {
+ fprintf(stderr, "usb_set_configuration failed\n");
+ }
+
+ i = usb_claim_interface(hdl, 0);
+ if (i < 0) {
+ fprintf(stderr, "usb_claim_interface failed %d\n", i);
+ return -1;
+ }
+
+
+ // read some data
+ for (j = 0; j < 1; j++) {
+ dwBlockSize = blocksize[j];
+ fprintf(stderr, "Testing blocksize %5d\n", dwBlockSize);
+
+#if 1
+ fprintf(stderr, "* write:");
+ // send a vendor request for a write
+ MemCmd.dwAddress = 0;
+ MemCmd.dwLength = 20 * 1024;
+ i = usb_control_msg(hdl, BM_REQUEST_TYPE, 0x02, 20, 1024, NULL, 0, 1000);
+ if (i < 0) {
+ fprintf(stderr, "usb_control_msg failed %d\n", i);
+ break;
+ }
+ dwBytes = 0;
+ starttimer();
+ while (MemCmd.dwLength > 0) {
+ dwChunk = MIN(dwBlockSize, MemCmd.dwLength);
+ i = usb_bulk_write(hdl, 0x01, (char *)abData, dwChunk, 2000);
+ if (i < 1) {
+ fprintf(stderr, "usb_bulk_write failed %d\n", i);
+ break;
+ }
+ MemCmd.dwLength -= dwChunk;
+ dwBytes += dwBlockSize;
+ if (stoptimer() > MAX_TIME) {
+ break;
+ }
+ ((unsigned int*)abData)[0]++;
+ }
+ if (i<0)
+ break;
+ iTimer = stoptimer();
+ if (iTimer)
+ fprintf(stderr, " %7d bytes in %d ms = %d kB/s\n", dwBytes, iTimer, dwBytes / iTimer);
+ // stdout
+ printf("%d,%d,%d\n", dwBlockSize, dwBytes, iTimer);
+#endif
+#if 1
+ fprintf(stderr, "* read :");
+ // send a vendor request for a read
+ MemCmd.dwAddress = 0;
+ MemCmd.dwLength = 20 * 1024;
+ i = usb_control_msg(hdl, BM_REQUEST_TYPE, 0x01, 20, 1024, NULL, 0, 1000);
+ if (i < 0) {
+ fprintf(stderr, "usb_control_msg failed %d\n", i);
+ break;
+ }
+ dwBytes = 0;
+ starttimer();
+ while (MemCmd.dwLength > 0) {
+ dwChunk = MIN(dwBlockSize, MemCmd.dwLength);
+ i = usb_bulk_read(hdl, 0x82, (char *)abData, dwChunk, 2000);
+ if (i < 1) {
+ fprintf(stderr, "usb_bulk_read failed %d\n", i);
+ break;
+ }
+ MemCmd.dwLength -= dwChunk;
+ dwBytes += dwBlockSize;
+ if (stoptimer() > MAX_TIME) {
+ break;
+ }
+ }
+ if (i<0)
+ break;
+ iTimer = stoptimer();
+ if (iTimer)
+ fprintf(stderr, " %7d bytes in %d ms = %d kB/s\n", dwBytes, iTimer, dwBytes / iTimer);
+ // stdout
+ printf("%d,%d,%d\n", dwBlockSize, dwBytes, iTimer);
+#endif
+ }
+
+
+ usb_release_interface(hdl, 0);
+ usb_close(hdl);
+
+ return 0;
+}
+