From fb4eb9bb68f52f5773cc03a4fed9314c29918cb4 Mon Sep 17 00:00:00 2001 From: zagor Date: Thu, 22 Nov 2007 20:51:00 +0000 Subject: [PATCH] New USB stack git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15758 a1c6a512-1295-4272-9138-f99709370657 --- apps/main.c | 7 - apps/menus/settings_menu.c | 92 -- apps/settings.c | 16 - apps/settings_list.c | 12 - firmware/FILES | 4 +- firmware/SOURCES | 28 +- firmware/drivers/usb/arcotg_dcd.c | 1032 -------------------- firmware/drivers/usb/arcotg_dcd.h | 179 ---- firmware/drivers/usb/arcotg_udc.c | 136 --- firmware/export/arcotg_udc.h | 318 ------ firmware/export/config-c200.h | 6 +- firmware/export/config-e200.h | 7 +- firmware/export/config-h10.h | 6 +- firmware/export/config-h10_5gb.h | 6 +- firmware/export/linkedlist.h | 355 ------- firmware/export/pp5020.h | 2 +- firmware/export/usb.h | 2 +- .../device/usb_storage.h => export/usb_core.h} | 46 +- .../device/usb_serial.h => export/usb_drv.h} | 32 +- firmware/export/usbstack.h | 63 -- firmware/target/arm/system-pp502x.c | 15 +- firmware/target/arm/usb-drv-pp502x.c | 624 ++++++++++++ firmware/target/arm/usb-fw-pp502x.c | 132 +-- firmware/usb.c | 6 +- firmware/usbstack/controller.h | 88 -- firmware/usbstack/core.h | 64 -- firmware/usbstack/core/config.c | 82 -- firmware/usbstack/core/core.c | 402 -------- firmware/usbstack/core/epsetup.c | 175 ---- firmware/usbstack/core/utils.c | 176 ---- firmware/usbstack/device.h | 47 - firmware/usbstack/drivers/device/usb_serial.c | 358 ------- firmware/usbstack/drivers/device/usb_storage.c | 387 -------- firmware/usbstack/usb_benchmark.c | 125 +++ firmware/usbstack/{utils.h => usb_benchmark.h} | 15 +- firmware/usbstack/usb_core.c | 537 ++++++++++ firmware/usbstack/usb_storage.c | 331 +++++++ firmware/usbstack/{host.h => usb_storage.h} | 23 +- tools/Makefile | 3 + tools/usb_benchmark.c | 212 ++++ 40 files changed, 1953 insertions(+), 4198 deletions(-) delete mode 100644 firmware/drivers/usb/arcotg_dcd.c delete mode 100644 firmware/drivers/usb/arcotg_dcd.h delete mode 100644 firmware/drivers/usb/arcotg_udc.c delete mode 100644 firmware/export/arcotg_udc.h delete mode 100644 firmware/export/linkedlist.h rename firmware/{usbstack/drivers/device/usb_storage.h => export/usb_core.h} (54%) rename firmware/{usbstack/drivers/device/usb_serial.h => export/usb_drv.h} (59%) delete mode 100644 firmware/export/usbstack.h create mode 100644 firmware/target/arm/usb-drv-pp502x.c delete mode 100644 firmware/usbstack/controller.h delete mode 100644 firmware/usbstack/core.h delete mode 100644 firmware/usbstack/core/config.c delete mode 100644 firmware/usbstack/core/core.c delete mode 100644 firmware/usbstack/core/epsetup.c delete mode 100644 firmware/usbstack/core/utils.c delete mode 100644 firmware/usbstack/device.h delete mode 100644 firmware/usbstack/drivers/device/usb_serial.c delete mode 100644 firmware/usbstack/drivers/device/usb_storage.c create mode 100644 firmware/usbstack/usb_benchmark.c rename firmware/usbstack/{utils.h => usb_benchmark.h} (75%) create mode 100644 firmware/usbstack/usb_core.c create mode 100644 firmware/usbstack/usb_storage.c rename firmware/usbstack/{host.h => usb_storage.h} (72%) create mode 100644 tools/usb_benchmark.c diff --git a/apps/main.c b/apps/main.c index d75bb726c..0ce8bcc7a 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 d1ca4a8d5..bcb8976a0 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 ) \___| < | \_\ ( <_> > < < - * 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 -#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 79f03f1bc..000000000 --- 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 c4ae6f8d6..000000000 --- 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 e016321b3..000000000 --- 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 8a1d6a37f..53ff97326 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 f5ba8f0c4..c49ee2384 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 aa60b106d..c69b43350 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 e8f7d7562..efb62c03f 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 bea41eeca..000000000 --- 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: /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 /* 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 b559aa366..845c89c61 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 17dbafa10..0977ff4d7 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_storage.h b/firmware/export/usb_core.h similarity index 54% rename from firmware/usbstack/drivers/device/usb_storage.h rename to firmware/export/usb_core.h index de53a0609..be3e4789d 100644 --- a/firmware/usbstack/drivers/device/usb_storage.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 Björn 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 _STORGAGE_H_ -#define _STORGAGE_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 storage driver in usb stack */ -void usb_storage_driver_init(void); +/* endpoints */ +enum { + EP_CONTROL = 0, + EP_RX, + EP_TX, + NUM_ENDPOINTS +}; -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); +/* 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 /*_STORGAGE_H_*/ diff --git a/firmware/usbstack/drivers/device/usb_serial.h b/firmware/export/usb_drv.h similarity index 59% rename from firmware/usbstack/drivers/device/usb_serial.h rename to firmware/export/usb_drv.h index cc5d9c488..a30f2ec49 100644 --- a/firmware/usbstack/drivers/device/usb_serial.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 Björn 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 _SERIAL_H_ -#define _SERIAL_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 serial driver in usb stack */ -void usb_serial_driver_init(void); - -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); - -#endif /*_SERIAL_H_*/ +#endif diff --git a/firmware/export/usbstack.h b/firmware/export/usbstack.h deleted file mode 100644 index 4ad477ec9..000000000 --- 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 - -#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 4d7e603a1..5dfcfa9ea 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 000000000..a837728a4 --- /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 Björn 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 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 f4b92f07d..75ee4759c 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 c91eab785..000000000 --- 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 c47232f12..000000000 --- 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 1a9b12508..000000000 --- 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 -#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 f72b3bbed..000000000 --- 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 -#include -#include -#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 ef98935fe..000000000 --- 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 -#include -#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 d43bd9290..000000000 --- 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 -#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 f1052ff9a..000000000 --- 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 51def1c3b..000000000 --- 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 -#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 01419da77..000000000 --- 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 -#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 000000000..a6e0e2d3e --- /dev/null +++ b/firmware/usbstack/usb_benchmark.c @@ -0,0 +1,125 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 by Björn 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 similarity index 75% rename from firmware/usbstack/utils.h rename to firmware/usbstack/usb_benchmark.h index 4b368a912..84853a165 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 Björn 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 000000000..e0c4d9133 --- /dev/null +++ b/firmware/usbstack/usb_core.c @@ -0,0 +1,537 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 by Björn 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 000000000..2c02284de --- /dev/null +++ b/firmware/usbstack/usb_storage.c @@ -0,0 +1,331 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 by Björn 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 similarity index 72% rename from firmware/usbstack/host.h rename to firmware/usbstack/usb_storage.h index b27449c9a..9067c92c6 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 Björn 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 5b0ef1ba4..17887b2d4 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 000000000..6d4b27ccb --- /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 + +*/ + +#include +#include +#include + +#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 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; +} + -- 2.11.4.GIT