summaryrefslogtreecommitdiff
path: root/firmware/usbstack
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2007-11-22 20:51:00 +0000
committerBjörn Stenberg <bjorn@haxx.se>2007-11-22 20:51:00 +0000
commitb4e5123e5d78935a3ab961d54ee5902eed37aa32 (patch)
treee0818a8c26e4a435188e70820c3aab387b01d842 /firmware/usbstack
parent2e2cbfe4acc22c1c69e38b638280da974630ca7f (diff)
downloadrockbox-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.h88
-rw-r--r--firmware/usbstack/core.h64
-rw-r--r--firmware/usbstack/core/config.c82
-rw-r--r--firmware/usbstack/core/core.c402
-rw-r--r--firmware/usbstack/core/epsetup.c175
-rw-r--r--firmware/usbstack/core/utils.c176
-rw-r--r--firmware/usbstack/device.h47
-rw-r--r--firmware/usbstack/drivers/device/usb_serial.c358
-rw-r--r--firmware/usbstack/drivers/device/usb_serial.h33
-rw-r--r--firmware/usbstack/drivers/device/usb_storage.c387
-rw-r--r--firmware/usbstack/drivers/device/usb_storage.h33
-rw-r--r--firmware/usbstack/usb_benchmark.c125
-rw-r--r--firmware/usbstack/usb_benchmark.h (renamed from firmware/usbstack/utils.h)15
-rw-r--r--firmware/usbstack/usb_core.c537
-rw-r--r--firmware/usbstack/usb_storage.c331
-rw-r--r--firmware/usbstack/usb_storage.h (renamed from firmware/usbstack/host.h)23
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_*/