diff options
| author | Björn Stenberg <bjorn@haxx.se> | 2007-11-22 20:51:00 +0000 |
|---|---|---|
| committer | Björn Stenberg <bjorn@haxx.se> | 2007-11-22 20:51:00 +0000 |
| commit | b4e5123e5d78935a3ab961d54ee5902eed37aa32 (patch) | |
| tree | e0818a8c26e4a435188e70820c3aab387b01d842 /firmware/usbstack | |
| parent | 2e2cbfe4acc22c1c69e38b638280da974630ca7f (diff) | |
| download | rockbox-b4e5123e5d78935a3ab961d54ee5902eed37aa32.zip rockbox-b4e5123e5d78935a3ab961d54ee5902eed37aa32.tar.gz rockbox-b4e5123e5d78935a3ab961d54ee5902eed37aa32.tar.bz2 rockbox-b4e5123e5d78935a3ab961d54ee5902eed37aa32.tar.xz | |
New USB stack
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15758 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/usbstack')
| -rw-r--r-- | firmware/usbstack/controller.h | 88 | ||||
| -rw-r--r-- | firmware/usbstack/core.h | 64 | ||||
| -rw-r--r-- | firmware/usbstack/core/config.c | 82 | ||||
| -rw-r--r-- | firmware/usbstack/core/core.c | 402 | ||||
| -rw-r--r-- | firmware/usbstack/core/epsetup.c | 175 | ||||
| -rw-r--r-- | firmware/usbstack/core/utils.c | 176 | ||||
| -rw-r--r-- | firmware/usbstack/device.h | 47 | ||||
| -rw-r--r-- | firmware/usbstack/drivers/device/usb_serial.c | 358 | ||||
| -rw-r--r-- | firmware/usbstack/drivers/device/usb_serial.h | 33 | ||||
| -rw-r--r-- | firmware/usbstack/drivers/device/usb_storage.c | 387 | ||||
| -rw-r--r-- | firmware/usbstack/drivers/device/usb_storage.h | 33 | ||||
| -rw-r--r-- | firmware/usbstack/usb_benchmark.c | 125 | ||||
| -rw-r--r-- | firmware/usbstack/usb_benchmark.h (renamed from firmware/usbstack/utils.h) | 15 | ||||
| -rw-r--r-- | firmware/usbstack/usb_core.c | 537 | ||||
| -rw-r--r-- | firmware/usbstack/usb_storage.c | 331 | ||||
| -rw-r--r-- | firmware/usbstack/usb_storage.h (renamed from firmware/usbstack/host.h) | 23 |
16 files changed, 1012 insertions, 1864 deletions
diff --git a/firmware/usbstack/controller.h b/firmware/usbstack/controller.h deleted file mode 100644 index c91eab7..0000000 --- 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 c47232f..0000000 --- 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 1a9b125..0000000 --- a/firmware/usbstack/core/config.c +++ /dev/null @@ -1,82 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Christian Gmeiner - * - * Based on linux/drivers/usb/gadget/config.c - * Copyright (C) 2003 David Brownell - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include <string.h> -#include "usbstack/core.h" - -static int usb_descriptor_fillbuf(void* buf, unsigned buflen, - struct usb_descriptor_header** src) -{ - uint8_t* dest = buf; - - if (!src) { - return -EINVAL; - } - - /* fill buffer from src[] until null descriptor ptr */ - for (; 0 != *src; src++) { - unsigned len = (*src)->bLength; - - if (len > buflen) - return -EINVAL; - - memcpy(dest, *src, len); - buflen -= len; - dest += len; - } - return dest - (uint8_t *)buf; -} - -int usb_stack_configdesc(const struct usb_config_descriptor* config, void* buf, - unsigned length, struct usb_descriptor_header** desc) -{ - struct usb_config_descriptor* cp = buf; - int len; - - if (length < USB_DT_CONFIG_SIZE || !desc) { - return -EINVAL; - } - - /* config descriptor first */ - *cp = *config; - - /* then interface/endpoint/class/vendor/... */ - len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (uint8_t*)buf, - length - USB_DT_CONFIG_SIZE, desc); - - if (len < 0) { - return len; - } - - len += USB_DT_CONFIG_SIZE; - if (len > 0xffff) { - return -EINVAL; - } - - /* patch up the config descriptor */ - cp->bLength = USB_DT_CONFIG_SIZE; - cp->bDescriptorType = USB_DT_CONFIG; - cp->wTotalLength = len; - cp->bmAttributes |= USB_CONFIG_ATT_ONE; - - return len; -} diff --git a/firmware/usbstack/core/core.c b/firmware/usbstack/core/core.c deleted file mode 100644 index f72b3bb..0000000 --- a/firmware/usbstack/core/core.c +++ /dev/null @@ -1,402 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Christian Gmeiner - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include <errno.h> -#include <string.h> -#include <ctype.h> -#include "config.h" - -#include "usbstack.h" -#include "usbstack/core.h" -#include "usbstack/controller.h" -#include "usbstack/drivers/device/usb_serial.h" -#include "usbstack/drivers/device/usb_storage.h" - -struct usb_core usbcore; - -/* private used functions */ -static void update_driver_names(unsigned char* result); -static void bind_device_driver(struct usb_device_driver* driver); - -/** - * Initialize usb stack. - */ -void usb_stack_init(void) -{ - int i; - logf("usb_stack_init"); - - /* init datastructures */ - usbcore.controller[0] = NULL; - usbcore.controller[1] = NULL; - usbcore.active_controller = NULL; - usbcore.device_driver = NULL; - usbcore.running = false; - - memset(&device_driver_names, 0, USB_STACK_MAX_SETTINGS_NAME); - - /* init arrays */ - for (i = 0; i < NUM_DRIVERS; i++) { - usbcore.device_drivers[i] = NULL; - usbcore.host_drivers[i] = NULL; - } - - /* init controllers */ -#if (USBSTACK_CAPS & CONTROLLER_DEVICE) - usb_dcd_init(); -#endif - -#if (USBSTACK_CAPS & CONTROLLER_HOST) - usb_hcd_init(); -#endif - - /* init drivers */ - usb_serial_driver_init(); - usb_storage_driver_init(); -} - -/** - * Start processing of usb stack. This function init - * active usb controller. - */ -void usb_stack_start(void) -{ - /* are we allready running? */ - if (usbcore.running) { - logf("allready running!"); - return; - } - - if (usbcore.active_controller == NULL) { - logf("no active controller!"); - return; - } - - /* forward to controller */ - logf("starting controller"); - usbcore.active_controller->start(); - usbcore.running = true; - - /* look if started controller is a device controller - * and if it has a device driver bind to it */ - logf("check for auto bind"); - if (usbcore.active_controller->type == DEVICE) { - if (usbcore.active_controller->device_driver == NULL && - usbcore.device_driver != NULL) { - /* bind driver */ - logf("binding..."); - bind_device_driver(usbcore.device_driver); - } - } -} - -/** - * Stop processing of usb stack. This function shutsdown - * active usb controller. - */ -void usb_stack_stop(void) -{ - /* are we allready stopped? */ - if (usbcore.running == false) { - return; - } - - /* forward to controller */ - usbcore.active_controller->stop(); - usbcore.running = false; -} - -/** - * Gets called by upper layers to indicate that there is - * an interrupt waiting for the controller. - */ -void usb_stack_irq(void) -{ - /* simply notify usb controller */ - if (usbcore.active_controller != NULL && - usbcore.active_controller->irq != NULL) { - usbcore.active_controller->irq(); - } -} - -/** - * If a host device controller is loaded, we need to have a function - * to call for maintanence. We need to check if a new device has connected, - * find suitable drivers for new devices. - */ -void usb_stack_work(void) -{ - /* TODO will be used with host device controllers - * and needs to be called in a loop (thread) */ -} - -/** - * Register an usb controller in the stack. The stack can - * only have two controllers registered at one time. - * One device host controller and one host device controller. - * - * @param ctrl pointer to controller to register. - * @return 0 on success else a defined error code. - */ -int usb_controller_register(struct usb_controller* ctrl) -{ - if (ctrl == NULL) { - return EINVAL; - } - - logf("usb_stack: register usb ctrl"); - logf(" -> name: %s", ctrl->name); - logf(" -> type: %d", ctrl->type); - - switch (ctrl->type) { - case DEVICE: - if (usbcore.controller[0] == NULL) { - usbcore.controller[0] = ctrl; - return 0; - } - break; - case HOST: - if (usbcore.controller[1] == NULL) { - usbcore.controller[1] = ctrl; - return 0; - } - break; - default: - return EINVAL; - } - - return ENOFREESLOT; -} - -/** - * Unregister an usb controller from the stack. - * - * @param ctrl pointer to controller to unregister. - * @return 0 on success else a defined error code. - */ -int usb_controller_unregister(struct usb_controller* ctrl) -{ - - if (ctrl == NULL) { - return EINVAL; - } - - switch (ctrl->type) { - case DEVICE: - if (usbcore.controller[0] == ctrl) { - usbcore.controller[0] = NULL; - return 0; - } - break; - case HOST: - if (usbcore.controller[1] == ctrl) { - usbcore.controller[1] = NULL; - return 0; - } - break; - default: - return EINVAL; - } - - return 0; /* never reached */ -} - -/** - * Select an usb controller and active it. - * - * @param type of controller to activate. - */ -void usb_controller_select(int type) -{ - struct usb_controller* new = NULL; - - /* check if a controller of the wanted type is already loaded */ - if (usbcore.active_controller != NULL && - (int)usbcore.active_controller->type == type) { - logf("controller already set"); - return; - } - - logf("usb_controller_select"); - logf(" -> type: %d", type); - - usbcore.mode = type; - - switch (type) { - case DEVICE: - new = usbcore.controller[0]; - break; - case HOST: - new = usbcore.controller[1]; - break; - } - - /* if there is only one controller, stop here */ - if (new == NULL) { - logf("no suitable cntrl found"); - return; - } - - /* shutdown current used controller */ - if (usbcore.active_controller != NULL) { - logf("shuting down old one"); - usbcore.active_controller->shutdown(); - } - - /* set and init new controller */ - usbcore.active_controller = new; - logf("init controller"); - usbcore.active_controller->init(); -} - -int usb_stack_get_mode(void) -{ - return usbcore.mode; -} - -/** - * Register an usb device driver. - * - * @param driver pointer to an usb_device_driver struct. - * @return 0 on success, else a defined error code. - */ -int usb_device_driver_register(struct usb_device_driver* driver) -{ - int i; - - if (driver == NULL) { - return EINVAL; - } - - /* add to linked list */ - logf("usb_stack: register usb driver"); - for (i = 0; i < NUM_DRIVERS; i++) { - if (usbcore.device_drivers[i] == NULL) { - usbcore.device_drivers[i] = driver; - update_driver_names(device_driver_names); - return 0; - } - } - - update_driver_names(device_driver_names); - - return 0; -} - -int usb_device_driver_bind(const char* name) -{ - int i; - struct usb_device_driver *tmp = NULL; - struct usb_device_driver *driver = NULL; - - if (name == NULL) { - return EINVAL; - } - - /* look for driver */ - logf("looking for driver %s", name); - for (i = 0; i < NUM_DRIVERS; i++) { - tmp = usbcore.device_drivers[i]; - if (tmp != NULL && strcmp(name, tmp->name) == 0) { - driver = tmp; - } - } - - if (driver == NULL) { - logf("no driver found"); - return ENODRIVERFOUND; - } - - /* look if there is an usb controller loaded */ - if (usbcore.active_controller == NULL) { - /* safe choosen driver and set it when controller starts */ - usbcore.device_driver = driver; - - } else { - - /* we need to have an active dcd controller */ - if (usbcore.active_controller->type != DEVICE) { - logf("wrong type"); - return EWRONGCONTROLLERTYPE; - } - - /* bind driver to controller */ - bind_device_driver(driver); - } - - return 0; -} - -void usb_device_driver_unbind(void) -{ - logf("usb_device_driver_unbind"); - if (usbcore.active_controller->device_driver != NULL) { - usbcore.active_controller->device_driver->unbind(); - usbcore.active_controller->device_driver = NULL; - } - - usbcore.device_driver = NULL; -} - -static void update_driver_names(unsigned char* result) -{ - int i; - int pos = 0; - unsigned char terminator = ','; - struct usb_device_driver* dd = NULL; - - /* reset buffer, iterate through drivers and add to char array */ - memset(result, 0, USB_STACK_MAX_SETTINGS_NAME); - for (i = 0; i < NUM_DRIVERS; i++) { - int len; - dd = usbcore.device_drivers[i]; - - if (dd != NULL) { - len = strlen(dd->name); - if (pos > 0) { - memcpy(result + pos, &terminator, 1); - pos++; - } - memcpy(result + pos, dd->name, len); - pos += len; - } - } -} - -static void bind_device_driver(struct usb_device_driver* driver) -{ - int ret = 0; - - /* look if there is an old driver */ - if (usbcore.active_controller->device_driver != NULL) { - usbcore.active_controller->device_driver->unbind(); - } - - /* bind driver to controller */ - usbcore.active_controller->device_driver = driver; - - /* init dirver */ - ret = driver->bind(usbcore.active_controller->controller_ops); - - if (ret != 0) { - logf("binding of %s failed", driver->name); - usbcore.active_controller->device_driver = NULL; - usbcore.device_driver = NULL; - } -} diff --git a/firmware/usbstack/core/epsetup.c b/firmware/usbstack/core/epsetup.c deleted file mode 100644 index ef98935..0000000 --- a/firmware/usbstack/core/epsetup.c +++ /dev/null @@ -1,175 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Christian Gmeiner - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include <string.h> -#include <ctype.h> -#include "usbstack/core.h" - -/** - * - * Naming Convention for Endpoint Names - * - * - ep1, ep2, ... address is fixed, not direction or type - * - ep1in, ep2out, ... address and direction are fixed, not type - * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction - * - ep1in-bulk, ep2out-iso, ... all three are fixed - * - ep-* ... no functionality restrictions - * - * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal. - * - */ -static int ep_matches(struct usb_ep* ep, struct usb_endpoint_descriptor* desc); - -void usb_ep_autoconfig_reset(void) -{ - struct usb_ep* ep = NULL; - if (usbcore.active_controller == NULL) { - return; - } - - logf("resetting endpoints"); - list_for_each_entry(ep, &usbcore.active_controller->endpoints.list, list) { - logf("reset %s", ep->name); - ep->claimed = false; - } -} - -/** - * Find a suitable endpoint for the requested endpoint descriptor. - * @param desc usb descritpro to use for seraching. - * @return NULL or a valid endpoint. - */ -struct usb_ep* usb_ep_autoconfig(struct usb_endpoint_descriptor* desc) -{ - struct usb_ep* ep = NULL; - if (usbcore.active_controller == NULL) { - logf("active controller NULL"); - return NULL; - } - - list_for_each_entry(ep, &usbcore.active_controller->endpoints.list, list) { - if (ep_matches (ep, desc)) { - return ep; - } - } - - return NULL; -} - -static int ep_matches(struct usb_ep* ep, struct usb_endpoint_descriptor* desc) -{ - uint8_t type; - const char* tmp; - uint16_t max; - - /* endpoint already claimed? */ - if (ep->claimed) { - logf("!! claimed !!"); - return 0; - } - - /* only support ep0 for portable CONTROL traffic */ - type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (type == USB_ENDPOINT_XFER_CONTROL) { - logf("type == control"); - return 0; - } - - /* some other naming convention */ - if (ep->name[0] != 'e') { - logf("wrong name"); - return 0; - } - - /* type-restriction: "-iso", "-bulk", or "-int". - * direction-restriction: "in", "out". - */ - if (ep->name[2] != '-' ) { - tmp = strrchr (ep->name, '-'); - if (tmp) { - switch (type) { - case USB_ENDPOINT_XFER_INT: - /* bulk endpoints handle interrupt transfers, - * except the toggle-quirky iso-synch kind - */ - if (tmp[2] == 's') { // == "-iso" - return 0; - } - break; - case USB_ENDPOINT_XFER_BULK: - if (tmp[1] != 'b') { // != "-bulk" - return 0; - } - break; - case USB_ENDPOINT_XFER_ISOC: - if (tmp[2] != 's') { // != "-iso" - return 0; - } - } - } else { - tmp = ep->name + strlen (ep->name); - } - - /* direction-restriction: "..in-..", "out-.." */ - tmp--; - if (!isdigit(*tmp)) { - if (desc->bEndpointAddress & USB_DIR_IN) { - if ('n' != *tmp) { - return 0; - } - } else { - if ('t' != *tmp) { - return 0; - } - } - } - } - - - /* endpoint maxpacket size is an input parameter, except for bulk - * where it's an output parameter representing the full speed limit. - * the usb spec fixes high speed bulk maxpacket at 512 bytes. - */ - max = 0x7ff & desc->wMaxPacketSize; - - switch (type) { - case USB_ENDPOINT_XFER_INT: - /* INT: limit 64 bytes full speed, 1024 high speed */ - if ((usbcore.active_controller->speed != USB_SPEED_HIGH) && - (max > 64)) { - return 0; - } - /* FALLTHROUGH */ - - case USB_ENDPOINT_XFER_ISOC: - if ((usbcore.active_controller->speed != USB_SPEED_HIGH) && - (max > 1023)) { - return 0; - } - break; - } - - /* MATCH!! */ - - /* set address of used ep in desc */ - desc->bEndpointAddress |= ep->ep_num; - ep->desc = desc; - - return 1; -} diff --git a/firmware/usbstack/core/utils.c b/firmware/usbstack/core/utils.c deleted file mode 100644 index d43bd92..0000000 --- a/firmware/usbstack/core/utils.c +++ /dev/null @@ -1,176 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Christian Gmeiner - * - * Based on linux/drivers/usb/gadget/usbstring.c - * Copyright (C) 2003 David Brownell - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include <string.h> -#include "usbstack/core.h" - -void into_usb_ctrlrequest(struct usb_ctrlrequest* request) -{ - char* type = ""; - char* req = ""; - char* extra = 0; - - logf("-usb request-"); - /* check if packet is okay */ - if (request->bRequestType == 0 && - request->bRequest == 0 && - request->wValue == 0 && - request->wIndex == 0 && - request->wLength == 0) { - logf(" -> INVALID <-"); - return; - } - - switch (request->bRequestType & USB_TYPE_MASK) { - case USB_TYPE_STANDARD: - type = "standard"; - - switch (request->bRequest) { - case USB_REQ_GET_STATUS: - req = "get status"; - break; - case USB_REQ_CLEAR_FEATURE: - req = "clear feature"; - break; - case USB_REQ_SET_FEATURE: - req = "set feature"; - break; - case USB_REQ_SET_ADDRESS: - req = "set address"; - break; - case USB_REQ_GET_DESCRIPTOR: - req = "get descriptor"; - - switch (request->wValue >> 8) { - case USB_DT_DEVICE: - extra = "get device descriptor"; - break; - case USB_DT_DEVICE_QUALIFIER: - extra = "get device qualifier"; - break; - case USB_DT_OTHER_SPEED_CONFIG: - extra = "get other-speed config descriptor"; - case USB_DT_CONFIG: - extra = "get configuration descriptor"; - break; - case USB_DT_STRING: - extra = "get string descriptor"; - break; - case USB_DT_DEBUG: - extra = "debug"; - break; - } - break; - - break; - case USB_REQ_SET_DESCRIPTOR: - req = "set descriptor"; - break; - case USB_REQ_GET_CONFIGURATION: - req = "get configuration"; - break; - case USB_REQ_SET_CONFIGURATION: - req = "set configuration"; - break; - case USB_REQ_GET_INTERFACE: - req = "get interface"; - break; - case USB_REQ_SET_INTERFACE: - req = "set interface"; - break; - case USB_REQ_SYNCH_FRAME: - req = "sync frame"; - break; - default: - req = "unkown"; - break; - } - - break; - case USB_TYPE_CLASS: - type = "class"; - break; - - case USB_TYPE_VENDOR: - type = "vendor"; - break; - } - - logf(" -b 0x%x", request->bRequestType); - logf(" -b 0x%x", request->bRequest); - logf(" -b 0x%x", request->wValue); - logf(" -b 0x%x", request->wIndex); - logf(" -b 0x%x", request->wLength); - logf(" -> t: %s", type); - logf(" -> r: %s", req); - if (extra != 0) { - logf(" -> e: %s", extra); - } -} - -int usb_stack_get_string(struct usb_string* strings, int id, uint8_t* buf) -{ - struct usb_string* tmp; - char* sp, *dp; - int len; - - /* if id is 0, then we need to send back all supported - * languages. In our case we only support one - * language: en-us (0x0409) */ - if (id == 0) { - buf [0] = 4; - buf [1] = USB_DT_STRING; - buf [2] = (uint8_t) 0x0409; - buf [3] = (uint8_t) (0x0409 >> 8); - return 4; - } - - /* look for string */ - for (tmp = strings; tmp && tmp->s; tmp++) { - if (tmp->id == id) { - break; - } - } - - /* did we found it? */ - if (!tmp || !tmp->s) { - return -EINVAL; - } - - len = MIN ((size_t) 126, strlen (tmp->s)); - memset(buf + 2, 0, 2 * len); - - /* convert to utf-16le */ - sp = (char*)tmp->s; - dp = (char*)&buf[2]; - - while (*sp) { - *dp++ = *sp++; - *dp++ = 0; - } - - /* write len and tag */ - buf [0] = (len + 1) * 2; - buf [1] = USB_DT_STRING; - - return buf[0]; -} diff --git a/firmware/usbstack/device.h b/firmware/usbstack/device.h deleted file mode 100644 index f1052ff..0000000 --- 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 51def1c..0000000 --- a/firmware/usbstack/drivers/device/usb_serial.c +++ /dev/null @@ -1,358 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Christian Gmeiner - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include <string.h> -#include "usb_serial.h" -#include "usbstack/utils.h" - -static struct usb_dcd_controller_ops* ops; - -struct usb_device_driver usb_serial_driver = { - .name = "serial", - .bind = usb_serial_driver_bind, - .unbind = usb_serial_driver_unbind, - .request = usb_serial_driver_request, - .suspend = NULL, - .resume = NULL, - .speed = usb_serial_driver_speed, -}; - -/*-------------------------------------------------------------------------*/ -/* usb descriptors */ - -#define MANUFACTURER_STR_ID 1 -#define PRODUCT_STR_ID 2 -#define SERIAL_STR_ID 3 -#define BULK_CONFIG_STR_ID 4 -#define DATA_STR_ID 5 - -/* static strings, in UTF-8 */ -static struct usb_string strings[] = { - { MANUFACTURER_STR_ID, "RockBox" }, - { PRODUCT_STR_ID, "RockBox Serial Driver" }, - { SERIAL_STR_ID, "0" }, - { BULK_CONFIG_STR_ID, "Serial Bulk" }, - { DATA_STR_ID, "Serial Data" }, -}; - -#define BULK_CONFIG_ID 1 - -static struct usb_device_descriptor serial_device_desc = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = USB_CLASS_COMM, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - .idVendor = 0x0525, - .idProduct = 0xa4a6, - .iManufacturer = MANUFACTURER_STR_ID, - .iProduct = PRODUCT_STR_ID, - .iSerialNumber = SERIAL_STR_ID, - .bNumConfigurations = 1, -}; - -static struct usb_config_descriptor serial_bulk_config_desc = { - .bLength = USB_DT_CONFIG_SIZE, - .bDescriptorType = USB_DT_CONFIG, - - .bNumInterfaces = 1, - .bConfigurationValue = BULK_CONFIG_ID, - .iConfiguration = BULK_CONFIG_STR_ID, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 1, -}; - -static struct usb_interface_descriptor serial_bulk_interface_desc = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = DATA_STR_ID, -}; - -static struct usb_endpoint_descriptor serial_fs_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 8, -}; - -static struct usb_endpoint_descriptor serial_fs_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 8, -}; - -static struct usb_debug_descriptor serial_debug_desc = { - .bLength = sizeof(struct usb_debug_descriptor), - .bDescriptorType = USB_DT_DEBUG, -}; - -static struct usb_qualifier_descriptor serial_qualifier_desc = { - .bLength = sizeof(struct usb_qualifier_descriptor), - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = 0x0200, - .bDeviceClass = USB_CLASS_COMM, - .bNumConfigurations = 1, -}; - -struct usb_descriptor_header *serial_fs_function[] = { - (struct usb_descriptor_header *) &serial_bulk_interface_desc, - (struct usb_descriptor_header *) &serial_fs_in_desc, - (struct usb_descriptor_header *) &serial_fs_out_desc, - NULL, -}; - -/* USB 2.0 */ -static struct usb_endpoint_descriptor serial_hs_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 512, -}; - -static struct usb_endpoint_descriptor serial_hs_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 512, -}; - -struct usb_descriptor_header *serial_hs_function[] = { - (struct usb_descriptor_header *) &serial_bulk_interface_desc, - (struct usb_descriptor_header *) &serial_hs_in_desc, - (struct usb_descriptor_header *) &serial_hs_out_desc, - NULL, -}; - -#define BUFFER_SIZE 100 -uint8_t buf[BUFFER_SIZE]; - -struct usb_response res; - -/* helper functions */ -static int config_buf(uint8_t *buf, uint8_t type, unsigned index); -static int set_config(int config); - -struct device { - struct usb_ep* in; - struct usb_ep* out; - uint32_t used_config; - struct usb_descriptor_header** descriptors; -}; - -static struct device dev; - -/*-------------------------------------------------------------------------*/ - -void usb_serial_driver_init(void) -{ - logf("usb serial: register"); - usb_device_driver_register(&usb_serial_driver); -} - -/*-------------------------------------------------------------------------*/ - -int usb_serial_driver_bind(void* controler_ops) -{ - logf("usb serial: bind"); - ops = controler_ops; - - /* serach and asign endpoints */ - usb_ep_autoconfig_reset(); - - dev.in = usb_ep_autoconfig(&serial_fs_in_desc); - if (!dev.in) { - goto autoconf_fail; - } - dev.in->claimed = true; - logf("usb serial: in: %s", dev.in->name); - - dev.out = usb_ep_autoconfig(&serial_fs_out_desc); - if (!dev.out) { - goto autoconf_fail; - } - dev.out->claimed = true; - logf("usb serial: out: %s", dev.out->name); - - /* update device decsriptor */ - serial_device_desc.bMaxPacketSize0 = ops->ep0->maxpacket; - - /* update qualifie descriptor */ - serial_qualifier_desc.bMaxPacketSize0 = ops->ep0->maxpacket; - - /* update debug descriptor */ - serial_debug_desc.bDebugInEndpoint = dev.in->ep_num; - serial_debug_desc.bDebugOutEndpoint = dev.out->ep_num; - - /* update hs descriptors as we asume that endpoints - are the same for fs and hs */ - serial_hs_in_desc.bEndpointAddress = serial_fs_in_desc.bEndpointAddress; - serial_hs_out_desc.bEndpointAddress = serial_fs_out_desc.bEndpointAddress; - - return 0; - -autoconf_fail: - logf("failed to find endpoints"); - return -EOPNOTSUPP; -} - -void usb_serial_driver_unbind(void) { - - /* disable endpoints... */ -} - -int usb_serial_driver_request(struct usb_ctrlrequest* request) -{ - int ret = -EOPNOTSUPP; - logf("usb serial: request"); - - res.length = 0; - res.buf = NULL; - - switch (request->bRequestType & USB_TYPE_MASK) { - case USB_TYPE_STANDARD: - - switch (request->bRequest) { - case USB_REQ_GET_DESCRIPTOR: - - switch (request->wValue >> 8) { - case USB_DT_DEVICE: - logf("usb serial: sending device desc"); - ret = MIN(sizeof(struct usb_device_descriptor), - request->wLength); - res.buf = &serial_device_desc; - break; - - case USB_DT_DEVICE_QUALIFIER: - logf("usb serial: sending qualifier dec"); - ret = MIN(sizeof(struct usb_qualifier_descriptor), - request->wLength); - res.buf = &serial_qualifier_desc; - break; - - case USB_DT_OTHER_SPEED_CONFIG: - case USB_DT_CONFIG: - logf("usb serial: sending config desc"); - - ret = config_buf(buf, request->wValue >> 8, - request->wValue & 0xff); - if (ret >= 0) { - logf("%d, vs %d", request->wLength, ret); - ret = MIN(request->wLength, (uint16_t)ret); - } - res.buf = buf; - break; - - case USB_DT_DEBUG: - logf("usb serial: sending debug desc"); - ret = MIN(sizeof(struct usb_debug_descriptor), - request->wLength); - res.buf = &serial_debug_desc; - break; - - case USB_DT_STRING: - logf("usb serial: sending string desc"); - ret = usb_stack_get_string(strings, request->wValue & 0xff, - buf); - ret = MIN(ret, request->wLength); - res.buf = buf; - break; - } - break; - - case USB_REQ_SET_CONFIGURATION: - logf("usb serial: set configuration %d", request->wValue); - ret = set_config(request->wValue); - break; - - case USB_REQ_GET_CONFIGURATION: - logf("usb serial: get configuration"); - ret = 1; - res.buf = &dev.used_config; - break; - } - } - - if (ret >= 0) { - res.length = ret; - ret = ops->send(NULL, &res); - } - - return ret; -} - -void usb_serial_driver_speed(enum usb_device_speed speed) -{ - switch (speed) { - case USB_SPEED_HIGH: - logf("usb serial: using highspeed"); - dev.descriptors = serial_hs_function; - break; - default: - logf("usb serial: using fullspeed"); - dev.descriptors = serial_fs_function; - break; - } -} - -/*-------------------------------------------------------------------------*/ -/* helper functions */ - -static int config_buf(uint8_t *buf, uint8_t type, unsigned index) -{ - int len; - - /* TODO check index*/ - (void)index; - - len = usb_stack_configdesc(&serial_bulk_config_desc, buf, BUFFER_SIZE, - dev.descriptors); - if (len < 0) { - return len; - } - ((struct usb_config_descriptor *)buf)->bDescriptorType = type; - return len; -} - -static int set_config(int config) -{ - /* TODO check config*/ - - /* enable endpoints */ - logf("setup %s", dev.in->name); - ops->enable(dev.in, (struct usb_endpoint_descriptor*)dev.descriptors[1]); - logf("setup %s", dev.out->name); - ops->enable(dev.out, (struct usb_endpoint_descriptor*)dev.descriptors[2]); - - /* store config */ - logf("using config %d", config); - dev.used_config = config; - - return 0; -} diff --git a/firmware/usbstack/drivers/device/usb_serial.h b/firmware/usbstack/drivers/device/usb_serial.h deleted file mode 100644 index cc5d9c4..0000000 --- a/firmware/usbstack/drivers/device/usb_serial.h +++ /dev/null @@ -1,33 +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 _SERIAL_H_ -#define _SERIAL_H_ - -#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_*/ diff --git a/firmware/usbstack/drivers/device/usb_storage.c b/firmware/usbstack/drivers/device/usb_storage.c deleted file mode 100644 index 01419da..0000000 --- a/firmware/usbstack/drivers/device/usb_storage.c +++ /dev/null @@ -1,387 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Christian Gmeiner - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include <string.h> -#include "usb_storage.h" -#include "usbstack/utils.h" - -/*-------------------------------------------------------------------------*/ - -static struct usb_dcd_controller_ops* ops; - -struct usb_device_driver usb_storage_driver = { - .name = "storage", - .bind = usb_storage_driver_bind, - .unbind = usb_storage_driver_unbind, - .request = usb_storage_driver_request, - .suspend = NULL, - .resume = NULL, - .speed = usb_storage_driver_speed, -}; - -/*-------------------------------------------------------------------------*/ - -#define PROTO_BULK 0x50 // Bulk only -#define SUBCL_SCSI 0x06 // Transparent SCSI - -/* Bulk-only class specific requests */ -#define USB_BULK_RESET_REQUEST 0xff -#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe - -/*-------------------------------------------------------------------------*/ -/* usb descriptors */ - -#define MANUFACTURER_STR_ID 1 -#define PRODUCT_STR_ID 2 -#define SERIAL_STR_ID 3 -#define CONFIG_STR_ID 4 -#define DATA_STR_ID 5 - -/* static strings, in UTF-8 */ -static struct usb_string strings[] = { - { MANUFACTURER_STR_ID, "RockBox" }, - { PRODUCT_STR_ID, "RockBox Storage Driver" }, - { SERIAL_STR_ID, "0" }, - { CONFIG_STR_ID, "Storage Bulk" }, - { DATA_STR_ID, "Storage Data" }, -}; - -static struct usb_device_descriptor storage_device_desc = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - .idVendor = 0xffff, - .idProduct = 0x0001, - .iManufacturer = MANUFACTURER_STR_ID, - .iProduct = PRODUCT_STR_ID, - .iSerialNumber = SERIAL_STR_ID, - .bNumConfigurations = 1, -}; - -static struct usb_config_descriptor storage_config_desc = { - .bLength = USB_DT_CONFIG_SIZE, - .bDescriptorType = USB_DT_CONFIG, - - .bNumInterfaces = 1, - .bConfigurationValue = 1, - .iConfiguration = CONFIG_STR_ID, - .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, - .bMaxPower = 250, /* 500mA in 2mA units */ -}; - -static struct usb_interface_descriptor storage_interface_desc = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_MASS_STORAGE, - .bInterfaceSubClass = SUBCL_SCSI, - .bInterfaceProtocol = PROTO_BULK, - .iInterface = DATA_STR_ID, -}; - -static struct usb_endpoint_descriptor storage_fs_bulk_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 64, -}; - -static struct usb_endpoint_descriptor storage_fs_bulk_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 64, -}; - -static struct usb_qualifier_descriptor storage_qualifier_desc = { - .bLength = sizeof(struct usb_qualifier_descriptor), - .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = 0x0200, - .bDeviceClass = 0, - .bNumConfigurations = 1, -}; - -struct usb_descriptor_header *storage_fs_function[] = { - (struct usb_descriptor_header *) &storage_interface_desc, - (struct usb_descriptor_header *) &storage_fs_bulk_in_desc, - (struct usb_descriptor_header *) &storage_fs_bulk_out_desc, - NULL, -}; - -/* USB 2.0 */ -static struct usb_endpoint_descriptor storage_hs_bulk_in_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 512, -}; - -static struct usb_endpoint_descriptor storage_hs_bulk_out_desc = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = 512, -}; - -struct usb_descriptor_header *storage_hs_function[] = { - (struct usb_descriptor_header *) &storage_interface_desc, - (struct usb_descriptor_header *) &storage_hs_bulk_in_desc, - (struct usb_descriptor_header *) &storage_hs_bulk_out_desc, - NULL, -}; - -#define BUFFER_SIZE 100 -uint8_t buf[BUFFER_SIZE]; - -struct usb_response res; - -/* helper functions */ -static int config_buf(uint8_t *buf, uint8_t type, unsigned index); -static int set_config(int config); -static int set_interface_alt_setting(int interface_alt_setting); - -struct device { - struct usb_ep* in; - struct usb_ep* out; - struct usb_ep* intr; - uint32_t used_config; - uint32_t used_interface_alt_setting; - struct usb_descriptor_header** descriptors; -}; - -static struct device dev; - -/*-------------------------------------------------------------------------*/ - -void usb_storage_driver_init(void) -{ - logf("usb storage: register"); - usb_device_driver_register(&usb_storage_driver); -} - -/*-------------------------------------------------------------------------*/ -/* device driver ops */ - -int usb_storage_driver_bind(void* controler_ops) -{ - ops = controler_ops; - - /* serach and asign endpoints */ - usb_ep_autoconfig_reset(); - - dev.in = usb_ep_autoconfig(&storage_fs_bulk_in_desc); - if (!dev.in) { - goto autoconf_fail; - } - dev.in->claimed = true; - logf("usb storage: in: %s", dev.in->name); - - dev.out = usb_ep_autoconfig(&storage_fs_bulk_out_desc); - if (!dev.out) { - goto autoconf_fail; - } - dev.out->claimed = true; - logf("usb storage: out: %s", dev.out->name); - - /* update device decsriptor */ - storage_device_desc.bMaxPacketSize0 = ops->ep0->maxpacket; - - /* update hs descriptors as we asume that endpoints - are the same for fs and hs */ - storage_hs_bulk_in_desc.bEndpointAddress = - storage_fs_bulk_in_desc.bEndpointAddress; - storage_hs_bulk_out_desc.bEndpointAddress = - storage_fs_bulk_out_desc.bEndpointAddress; - - return 0; - -autoconf_fail: - logf("failed to find endpoints"); - return -EOPNOTSUPP; -} - -void usb_storage_driver_unbind(void) -{ - - /* disable endpoints... */ -} - -int usb_storage_driver_request(struct usb_ctrlrequest* request) -{ - int ret = -EOPNOTSUPP; - logf("usb storage: request"); - - res.length = 0; - res.buf = NULL; - - switch (request->bRequestType & USB_TYPE_MASK) { - case USB_TYPE_STANDARD: - - switch (request->bRequest) { - case USB_REQ_GET_DESCRIPTOR: - - switch (request->wValue >> 8) { - case USB_DT_DEVICE: - logf("usb storage: sending device desc"); - ret = MIN(sizeof(struct usb_device_descriptor), - request->wLength); - res.buf = &storage_device_desc; - break; - - case USB_DT_DEVICE_QUALIFIER: - logf("usb storage: sending qualifier dec"); - ret = MIN(sizeof(struct usb_qualifier_descriptor), - request->wLength); - res.buf = &storage_qualifier_desc; - break; - - case USB_DT_OTHER_SPEED_CONFIG: - case USB_DT_CONFIG: - logf("usb storage: sending config desc"); - - ret = config_buf(buf, request->wValue >> 8, - request->wValue & 0xff); - if (ret >= 0) { - logf("%d, vs %d", request->wLength, ret); - ret = MIN(request->wLength, (uint16_t)ret); - } - res.buf = buf; - break; - - case USB_DT_STRING: - logf("usb storage: sending string desc"); - ret = usb_stack_get_string(strings, request->wValue & 0xff, - buf); - ret = MIN(ret, request->wLength); - res.buf = buf; - break; - } - break; - - case USB_REQ_SET_CONFIGURATION: - logf("usb storage: set configuration %d", request->wValue); - ret = set_config(request->wValue); - break; - - case USB_REQ_GET_CONFIGURATION: - logf("usb storage: get configuration"); - ret = 1; - res.buf = &dev.used_config; - break; - - case USB_REQ_GET_INTERFACE: - logf("usb storage: get interface"); - ret = 1; - res.buf = &dev.used_interface_alt_setting; - break; - - case USB_REQ_SET_INTERFACE: - logf("usb storage: set interface"); - ret = set_interface_alt_setting(request->wValue); - break; - } - - case USB_TYPE_CLASS: - - switch (request->bRequest) { - case USB_BULK_RESET_REQUEST: - logf("usb storage: bulk reset"); - break; - - case USB_BULK_GET_MAX_LUN_REQUEST: - logf("usb storage: get max lun"); - /* we support no LUNs (Logical Unit Number) */ - buf[0] = 0; - ret = 1; - break; - } - break; - } - - if (ret >= 0) { - res.length = ret; - ret = ops->send(NULL, &res); - } - - return ret; -} - -void usb_storage_driver_speed(enum usb_device_speed speed) -{ - switch (speed) { - case USB_SPEED_HIGH: - logf("usb storage: using highspeed"); - dev.descriptors = storage_hs_function; - break; - default: - logf("usb storage: using fullspeed"); - dev.descriptors = storage_fs_function; - break; - } -} - -/*-------------------------------------------------------------------------*/ -/* S/GET CONFIGURATION helpers */ - -static int config_buf(uint8_t *buf, uint8_t type, unsigned index) -{ - int len; - - (void)index; - - len = usb_stack_configdesc(&storage_config_desc, buf, BUFFER_SIZE, - dev.descriptors); - logf("result %d", len); - if (len < 0) { - return len; - } - ((struct usb_config_descriptor *)buf)->bDescriptorType = type; - return len; -} - -static int set_config(int config) -{ - /* enable endpoints */ - logf("setup %s", dev.in->name); - ops->enable(dev.in, (struct usb_endpoint_descriptor*)dev.descriptors[1]); - logf("setup %s", dev.out->name); - ops->enable(dev.out, (struct usb_endpoint_descriptor*)dev.descriptors[2]); - - dev.used_config = config; - - /* setup buffers */ - - return 0; -} - -static int set_interface_alt_setting(int interface_alt_setting) -{ - dev.used_interface_alt_setting = interface_alt_setting; - - return 0; -} - diff --git a/firmware/usbstack/drivers/device/usb_storage.h b/firmware/usbstack/drivers/device/usb_storage.h deleted file mode 100644 index de53a06..0000000 --- a/firmware/usbstack/drivers/device/usb_storage.h +++ /dev/null @@ -1,33 +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 _STORGAGE_H_ -#define _STORGAGE_H_ - -#include "usbstack/core.h" - -/* register storage driver in usb stack */ -void usb_storage_driver_init(void); - -int usb_storage_driver_bind(void* controller_ops); -void usb_storage_driver_unbind(void); -int usb_storage_driver_request(struct usb_ctrlrequest* req); -void usb_storage_driver_speed(enum usb_device_speed speed); - -#endif /*_STORGAGE_H_*/ diff --git a/firmware/usbstack/usb_benchmark.c b/firmware/usbstack/usb_benchmark.c new file mode 100644 index 0000000..a6e0e2d --- /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 index 4b368a9..84853a1 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 0000000..e0c4d91 --- /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 0000000..2c02284 --- /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 index b27449c..9067c92 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_*/ |