Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 14252)
+++ apps/lang/english.lang (working copy)
@@ -11018,3 +11018,73 @@
*: ""
+
+ id: LANG_USBSTACK
+ desc: in settings_menu
+ user:
+
+ *: "USB Stack"
+
+
+ *: "USB Stack"
+
+
+ *: "USB Stack"
+
+
+
+ id: LANG_USBSTACK_MODE
+ desc: in usbstack settings
+ user:
+
+ *: "USB Stack Mode"
+
+
+ *: "USB Stack Mode"
+
+
+ *: "USB Stack Mode"
+
+
+
+ id: LANG_USBSTACK_AUTOMATIC
+ desc: in usbstack settings
+ user:
+
+ *: "Automatic"
+
+
+ *: "Automatic"
+
+
+ *: "Automatic"
+
+
+
+ id: LANG_USBSTACK_DEVICE
+ desc: in usbstack settings
+ user:
+
+ *: "Device"
+
+
+ *: "Device"
+
+
+ *: "Device"
+
+
+
+ id: LANG_USBSTACK_HOST
+ desc: in usbstack settings
+ user:
+
+ *: "Host"
+
+
+ *: "Host"
+
+
+ *: "Host"
+
+
\ No newline at end of file
Index: apps/settings.c
===================================================================
--- apps/settings.c (revision 14252)
+++ apps/settings.c (working copy)
@@ -98,6 +98,10 @@
#include "lcd-remote.h"
#endif
+#ifdef USE_USBSTACK
+#include "usbstack.h"
+#endif
+
long lasttime = 0;
/** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/
@@ -867,7 +871,10 @@
if (global_settings.colors_file)
read_color_theme_file();
#endif
-
+
+#ifdef USE_USBSTACK
+ usb_controller_select(global_settings.usb_stack_mode);
+#endif
}
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 14252)
+++ apps/settings.h (working copy)
@@ -743,6 +743,9 @@
int list_accel_start_delay; /* ms before we start increaseing step size */
int list_accel_wait; /* ms between increases */
#endif
+#ifdef USE_USBSTACK
+ int usb_stack_mode; /* automatic, device or host */
+#endif
};
/** global variables **/
Index: apps/menus/settings_menu.c
===================================================================
--- apps/menus/settings_menu.c (revision 14252)
+++ apps/menus/settings_menu.c (working copy)
@@ -442,7 +442,18 @@
/* VOICE MENU */
/***********************************/
+#ifdef USE_USBSTACK
/***********************************/
+/* USB STACK MENU */
+MENUITEM_SETTING(usbstack_mode, &global_settings.usb_stack_mode, NULL);
+
+MAKE_MENU(usbstack_menu, ID2P(LANG_USBSTACK), 0, Icon_file_view_menu,
+ &usbstack_mode);
+/* USB STACK MENU */
+/***********************************/
+#endif
+
+/***********************************/
/* SETTINGS MENU */
static int language_browse(void)
{
@@ -458,6 +469,11 @@
&tagcache_menu,
#endif
&display_menu, &system_menu,
- &bookmark_settings_menu, &browse_langs, &voice_settings_menu );
+ &bookmark_settings_menu, &browse_langs, &voice_settings_menu
+
+#ifdef USE_USBSTACK
+ , &usbstack_menu
+#endif
+ );
/* SETTINGS MENU */
/***********************************/
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c (revision 14252)
+++ apps/settings_list.c (working copy)
@@ -47,6 +47,9 @@
#include "radio.h"
#endif
+#ifdef USE_USBSTACK
+#include "usbstack.h"
+#endif
#define NVRAM(bytes) (bytes< ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: adc.h 13174 2007-04-15 23:35:56Z amiconn $
+ *
+ * Copyright (C) by Linux Kernel Developers
+ *
+ * Original source can be found in linux kernel: /include/list.h
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _LINKED_LIST_H_
+#define _LINKED_LIST_H_
+
+static inline void prefetch(const void *x) {(void)x;}
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+/* TODO move this macro? */
+/* more about this macro: http://www.kroah.com/log/linux/container_of.html */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1 ((void *) 0x00100100)
+#define LIST_POISON2 ((void *) 0x00200200)
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+ struct list_head *new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+ struct list_head *new)
+{
+ list_replace(old, new);
+ INIT_LIST_HEAD(old);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ }
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; prefetch(pos->next), pos != (head); \
+ pos = pos->next)
+
+/**
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
+ pos = pos->prev)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
+ */
+#define list_prepare_entry(pos, head, member) \
+ ((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member) \
+ for (; prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+#endif /*_LINKED_LIST_H_*/
Index: firmware/export/config.h
===================================================================
--- firmware/export/config.h (revision 14252)
+++ firmware/export/config.h (working copy)
@@ -334,7 +334,7 @@
#define ICODE_ATTR __attribute__ ((section(".icode")))
#define ICONST_ATTR __attribute__ ((section(".irodata")))
#define IDATA_ATTR __attribute__ ((section(".idata")))
-#define IBSS_ATTR __attribute__ ((section(".ibss")))
+#define IBSS_ATTR
#define USE_IRAM
#if CONFIG_CPU != SH7034
#define IRAM_STEAL
Index: firmware/export/usbstack.h
===================================================================
--- firmware/export/usbstack.h (revision 0)
+++ firmware/export/usbstack.h (revision 0)
@@ -0,0 +1,138 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: $
+ *
+ * Copyright (C) 2007 by Christian Gmeiner
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _USBSTACK_H_
+#define _USBSTACK_H_
+
+#include "linkedlist.h"
+#include "usb_ch9.h"
+#include "logf.h"
+
+/*
+ * error codes
+ */
+#define ENOFREESLOT 1
+#define ENOCONTROLLERACTIVE 2
+#define EWRONGCONTROLLERTYPE 3
+
+/*
+ * stack routines
+ */
+void usb_stack_init(void);
+void usb_stack_shutdown(void);
+void usb_stack_start(void);
+void usb_stack_stop(void);
+void usb_stack_irq(void);
+void usb_stack_work(void);
+
+/*
+ * usb controller
+ */
+
+enum usb_controller_type {
+ AUTOMATIC = 0, /* only used for autodetection, do not use in controllers */
+ DEVICE,
+ HOST,
+};
+
+struct usb_device_driver;
+struct usb_host_driver;
+
+struct usb_controller {
+ const char* name;
+ enum usb_controller_type type;
+ int (*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;
+};
+
+int usb_controller_register(struct usb_controller* ctrl);
+int usb_controller_unregister(struct usb_controller* ctrl);
+void usb_controller_select(int type);
+
+/*
+ * usb device driver
+ */
+struct usb_device_driver {
+ const char* name;
+ void (*bind)(void* controller_ops);
+ void (*unbind)(void);
+ void (*request)(struct usb_ctrlrequest* req);
+ void* data; /* used to store controller specific ops struct */
+ struct list_head list;
+};
+
+int usb_device_driver_register(struct usb_device_driver* driver);
+int usb_device_driver_unregister(struct usb_device_driver* driver);
+int usb_device_driver_bind(struct usb_device_driver* driver);
+void ubs_device_driver_unbind(struct usb_device_driver* driver);
+
+/*
+ * usb host driver
+ */
+struct usb_host_driver {
+ void* data; /* used to store controller specific ops struct */
+ struct list_head list;
+};
+
+/*
+ * dcd - device controller driver
+ */
+void usb_dcd_init(void);
+void usb_dcd_shutdown(void);
+
+struct usb_dcd_controller_ops {
+ /* endpoint management */
+ /* transfer */
+ /* reciving */
+};
+
+/*
+ * hcd - host controller driver
+ */
+void usb_hcd_init(void);
+void usb_hcd_shutdown(void);
+
+struct usb_hcd_controller_ops {
+ /* TODO */
+};
+
+/*
+ * 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;
+ struct usb_host_driver host_drivers;
+ struct usb_device_driver device_drivers;
+ enum usb_controller_type mode;
+ bool running;
+};
+
+/* use a global variable to make usb_core accessable in other places */
+struct usb_core usbcore;
+
+#endif /*_USBSTACK_H_*/
Index: firmware/export/config-e200.h
===================================================================
--- firmware/export/config-e200.h (revision 14252)
+++ firmware/export/config-e200.h (working copy)
@@ -145,6 +145,7 @@
/* USB On-the-go */
#define CONFIG_USBOTG USBOTG_ARC
+#define USE_USBSTACK
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
Index: firmware/export/config-ipodvideo.h
===================================================================
--- firmware/export/config-ipodvideo.h (revision 14252)
+++ firmware/export/config-ipodvideo.h (working copy)
@@ -38,6 +38,8 @@
/* define this if you would like tagcache to build on this target */
#define HAVE_TAGCACHE
+#define USE_USBSTACK
+
/* LCD dimensions */
#define LCD_WIDTH 320
#define LCD_HEIGHT 240
Index: firmware/export/usbstack/dummy_driver.h
===================================================================
--- firmware/export/usbstack/dummy_driver.h (revision 0)
+++ firmware/export/usbstack/dummy_driver.h (revision 0)
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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 _DUMMY_DRIVER_H_
+#define _DUMMY_DRIVER_H_
+
+void usb_dummy_init(void);
+
+#endif /*_DUMMY_DRIVER_H_*/
Index: firmware/usbstack/core/core.c
===================================================================
--- firmware/usbstack/core/core.c (revision 0)
+++ firmware/usbstack/core/core.c (revision 0)
@@ -0,0 +1,310 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: $
+ *
+ * Copyright (C) 2007 by Christian Gmeiner
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include
+#include
+#include "usbstack.h"
+
+/**
+ * Initialize usb stack.
+ */
+void usb_stack_init(void) {
+
+ /* init datastructures */
+ usbcore.controller[0] = NULL;
+ usbcore.controller[1] = NULL;
+ usbcore.active_controller = NULL;
+
+ /* init linked lists */
+ INIT_LIST_HEAD(&usbcore.device_drivers.list);
+ INIT_LIST_HEAD(&usbcore.host_drivers.list);
+
+ /* idea: all drivers should be something like rockbox plugins... rockbox usb drivers.
+ * the app code scans for usb drivers and register them automaticly in the stack.
+ * We only need one *.c file for a driver and we dont need any *.h files with one
+ * method in it: usb__init(void);
+ */
+}
+
+/**
+ * Shutdown usb stack.
+ */
+void usb_stack_shutdown(void) {
+
+ /* free current used device driver */
+ if (usbcore.active_controller->device_driver != NULL) {
+
+ /* call unbind if supported */
+ if (usbcore.active_controller->device_driver->unbind != NULL) {
+ usbcore.active_controller->device_driver->unbind();
+ }
+ usbcore.active_controller->device_driver = NULL;
+ }
+
+ /* stop stack */
+ usb_stack_stop();
+
+ /* TODO delete linked lists */
+}
+
+/**
+ * Start processing of usb stack. This function init
+ * active usb controller.
+ */
+void usb_stack_start(void) {
+
+ /* are we allready running? */
+ if (usbcore.running) {
+ return;
+ }
+
+ /* forward to controller */
+ if (usbcore.active_controller != NULL && usbcore.active_controller->start != NULL) {
+ usbcore.active_controller->start();
+ usbcore.running = true;
+ }
+}
+
+/**
+ * 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 */
+ if (usbcore.active_controller != NULL && usbcore.active_controller->stop != NULL) {
+ 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;
+}
+
+/**
+ * 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 AUTOMATIC:
+ /* we want autodetection, so shutdown current controller */
+ if (usbcore.active_controller != NULL) {
+ usbcore.active_controller->shutdown();
+ usbcore.active_controller = NULL;
+ }
+ return;
+ break;
+ 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) {
+ usbcore.active_controller->shutdown();
+ }
+
+ /* set and init new controller */
+ usbcore.active_controller = new;
+ usbcore.active_controller->init();
+}
+
+/**
+ * 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) {
+
+ if (driver == NULL) {
+ return EINVAL;
+ }
+
+ logf("usb_stack: register usb driver");
+ /* add to linked list */
+ list_add(&driver->list, &usbcore.device_drivers.list);
+
+ return 0;
+}
+
+/**
+ * Unregister an usb device driver.
+ *
+ * @param driver to unregister
+ * @return 0 or defined error code.
+ */
+int usb_device_driver_unregister(struct usb_device_driver* driver) {
+
+ if (driver == NULL) {
+ return EINVAL;
+ }
+
+ /* delete from linked list */
+ list_del(&driver->list);
+ return 0;
+}
+
+int usb_device_driver_bind(struct usb_device_driver* driver) {
+
+ if (driver == NULL) {
+ return EINVAL;
+ }
+
+ /* look if there is an usb controller loaded */
+ if (usbcore.active_controller == NULL) {
+ return ENOCONTROLLERACTIVE;
+ }
+
+ /* we need to have an active dcd controller */
+ if (usbcore.active_controller->type != DEVICE) {
+ return EWRONGCONTROLLERTYPE;
+ }
+
+ /* bind driver to controller */
+ usbcore.active_controller->device_driver = driver;
+
+ /* init dirver */
+ driver->bind(usbcore.active_controller->controller_ops);
+
+ return 0;
+}
+
+void usb_device_driver_unbind(struct usb_device_driver* driver) {
+ (void)driver;
+}
Index: firmware/SOURCES
===================================================================
--- firmware/SOURCES (revision 14252)
+++ firmware/SOURCES (working copy)
@@ -226,6 +226,10 @@
/* USBOTG */
#if !defined(SIMULATOR)
+#if defined(USE_USBSTACK)
+usbstack/core/core.c
+usbstack/drivers/dummy.c
+#endif
#if CONFIG_USBOTG == USBOTG_ISP1362
drivers/isp1362.c
#endif
@@ -233,7 +237,7 @@
#if CONFIG_USBOTG == USBOTG_M5636
drivers/m5636.c
#elif CONFIG_USBOTG == USBOTG_ARC
-drivers/arcotg_udc.c
+drivers/usb/arcotg_dcd.c
#endif /* CONFIG_USBOTG */
#endif /* !defined(BOOTLOADER) */
#endif /* !defined(SIMULATOR) */
Index: firmware/target/arm/usb-fw-pp502x.c
===================================================================
--- firmware/target/arm/usb-fw-pp502x.c (revision 14252)
+++ firmware/target/arm/usb-fw-pp502x.c (working copy)
@@ -8,6 +8,7 @@
* $Id$
*
* Copyright (C) 2002 by Linus Nielsen Feltzing
+ * Copyright (C) 2007 by Christian Gmeiner
*
* iPod driver based on code from the ipodlinux project - http://ipodlinux.org
* Adapted for Rockbox in January 2006
@@ -21,32 +22,16 @@
* KIND, either express or implied.
*
****************************************************************************/
-#include "config.h"
-#include "cpu.h"
-#include "kernel.h"
-#include "thread.h"
+
#include "system.h"
-#include "debug.h"
-#include "ata.h"
-#include "fat.h"
-#include "disk.h"
-#include "panic.h"
-#include "lcd.h"
-#include "adc.h"
#include "usb.h"
-#include "button.h"
-#include "sprintf.h"
-#include "string.h"
-#include "hwcompat.h"
-
#include "usb-target.h"
+#include "usbstack.h"
#include "arcotg_udc.h"
-void usb_init_device(void)
-{
- int r0;
- outl(inl(0x70000084) | 0x200, 0x70000084);
+void usb_init_device(void) {
+ outl(inl(0x70000084) | 0x200, 0x70000084);
outl(inl(0x7000002C) | 0x3000000, 0x7000002C);
DEV_EN |= DEV_USB;
@@ -56,89 +41,32 @@
DEV_INIT |= INIT_USB;
while ((inl(0x70000028) & 0x80) == 0);
+ /* reset port */
UDC_PORTSC1 |= PORTSCX_PORT_RESET;
while ((UDC_PORTSC1 & PORTSCX_PORT_RESET) != 0);
-
- UDC_OTGSC |= 0x5F000000;
- if( (UDC_OTGSC & 0x100) == 0) {
- UDC_USBMODE &=~ USB_MODE_CTRL_MODE_HOST;
- UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
- outl(inl(0x70000028) | 0x4000, 0x70000028);
- outl(inl(0x70000028) | 0x2, 0x70000028);
- } else {
- UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
- outl(inl(0x70000028) &~0x4000, 0x70000028);
- outl(inl(0x70000028) | 0x2, 0x70000028);
- }
-
+ /* reset device */
UDC_USBCMD |= USB_CMD_CTRL_RESET;
while((UDC_USBCMD & USB_CMD_CTRL_RESET) != 0);
- r0 = UDC_PORTSC1;
-
- /* Note from IPL source (referring to next 5 lines of code:
- THIS NEEDS TO BE CHANGED ONCE THERE IS KERNEL USB */
- DEV_INIT |= INIT_USB;
- DEV_EN |= DEV_USB;
- while ((inl(0x70000028) & 0x80) == 0);
- outl(inl(0x70000028) | 0x2, 0x70000028);
-
udelay(0x186A0);
-
- dr_controller_setup();
-
-#if defined(IPOD_COLOR) || defined(IPOD_4G) \
- || defined(IPOD_MINI) || defined(IPOD_MINI2G)
- /* GPIO C bit 1 is firewire detect */
- GPIOC_ENABLE |= 0x02;
- GPIOC_OUTPUT_EN &= ~0x02;
-#endif
}
-void usb_enable(bool on)
-{
- /* This device specific code will eventually give way to proper USB
- handling, which should be the same for all PP502x targets. */
- if (on)
- {
-#if defined(IPOD_ARCH) || defined(IRIVER_H10) || defined (IRIVER_H10_5GB)
- /* For the H10 and iPod, we can only do one thing with USB mode - reboot
- into the flash-based disk-mode. This does not return. */
+void usb_enable(bool on) {
-#if defined(IRIVER_H10) || defined (IRIVER_H10_5GB)
- if(button_status()==BUTTON_RIGHT)
-#endif
- {
- ata_sleepnow(); /* Immediately spindown the disk. */
- sleep(HZ*2);
-
-#ifdef IPOD_ARCH /* The following code is based on ipodlinux */
-#if CONFIG_CPU == PP5020
- memcpy((void *)0x40017f00, "diskmode\0\0hotstuff\0\0\1", 21);
-#elif CONFIG_CPU == PP5022
- memcpy((void *)0x4001ff00, "diskmode\0\0hotstuff\0\0\1", 21);
-#endif
-#endif
-
- system_reboot(); /* Reboot */
- }
-#endif
+ if (on) {
+ logf("enabling usb");
+ usb_stack_start();
+ } else {
+ logf("disabling usb");
+ usb_stack_stop();
}
}
-bool usb_detect(void)
-{
- static bool prev_usbstatus1 = false;
- bool usbstatus1,usbstatus2;
+bool usb_detect(void) {
-#if defined(IPOD_COLOR) || defined(IPOD_4G) \
- || defined(IPOD_MINI) || defined(IPOD_MINI2G)
- /* GPIO C bit 1 is firewire detect */
- if (!(GPIOC_INPUT_VAL & 0x02))
- return true;
-#endif
-
+ bool connected = false;
+
/* UDC_ID should have the bit format:
[31:24] = 0x0
[23:16] = 0x22 (Revision number)
@@ -150,19 +78,28 @@
return false;
}
- usbstatus1 = (UDC_OTGSC & 0x800) ? true : false;
- if ((usbstatus1 == true) && (prev_usbstatus1 == false)) {
- dr_controller_run();
- } else if ((usbstatus1 == false) && (prev_usbstatus1 == true)) {
- dr_controller_stop();
+ connected = (UDC_OTGSC & 0x800) ? true : false;
+
+ if (connected == false) {
+ usb_stack_stop();
+ return false;
}
+
+ /* do we want autodetection? */
+ if (usbcore.mode == AUTOMATIC) {
- prev_usbstatus1 = usbstatus1;
- usbstatus2 = (UDC_PORTSC1 & PORTSCX_CURRENT_CONNECT_STATUS) ? true : false;
-
- if (usbstatus1 && usbstatus2) {
- return true;
- } else {
- return false;
+ logf("automatic mode");
+ UDC_OTGSC |= 0x5F000000;
+ if ((UDC_OTGSC & 0x100) == 0) {
+ usb_controller_select(HOST);
+ } else {
+ usb_controller_select(DEVICE);
+ }
}
+
+ /* TODO correct place? */
+ usb_stack_start();
+
+ return true;
}
+
Index: firmware/target/arm/system-pp502x.c
===================================================================
--- firmware/target/arm/system-pp502x.c (revision 14252)
+++ firmware/target/arm/system-pp502x.c (working copy)
@@ -20,6 +20,10 @@
#include "thread.h"
#include "i2s.h"
+#if defined(USE_USBSTACK)
+#include "usbstack.h"
+#endif
+
#if NUM_CORES > 1
struct mutex boostctrl_mtx NOCACHEBSS_ATTR;
#endif
@@ -39,8 +43,12 @@
{
if(CURRENT_CORE == CPU)
{
- if (CPU_INT_STAT & TIMER1_MASK)
+ if (CPU_INT_STAT & TIMER1_MASK) {
TIMER1();
+#if defined(USE_USBSTACK)
+ usb_stack_irq();
+#endif
+ }
else if (CPU_INT_STAT & TIMER2_MASK)
TIMER2();
#if defined(IPOD_MINI) /* Mini 1st gen only, mini 2nd gen uses iPod 4G code */
Index: firmware/drivers/arcotg_udc.c
===================================================================
--- firmware/drivers/arcotg_udc.c (revision 14252)
+++ firmware/drivers/arcotg_udc.c (working copy)
@@ -1,135 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 by Barry Wardell
- *
- * Based on code from the Linux Target Image Builder from Freescale
- * available at http://www.bitshrine.org/ and
- * http://www.bitshrine.org/gpp/linux-2.6.16-mx31-usb-2.patch
- * Adapted for Rockbox in January 2007
- * Original file: drivers/usb/gadget/arcotg_udc.c
- *
- * USB Device Controller Driver
- * Driver for ARC OTG USB module in the i.MX31 platform, etc.
- *
- * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Based on mpc-udc.h
- * Author: Li Yang (leoli@freescale.com)
- * Jiang Bo (Tanya.jiang@freescale.com)
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-#include "arcotg_udc.h"
-#include "logf.h"
-
-static int timeout;
-
-/* @qh_addr is the aligned virt addr of ep QH addr
- * it is used to set endpointlistaddr Reg */
-/* was static int dr_controller_setup(void *qh_addr) */
-int dr_controller_setup(void)
-{
-#if 0
- struct arc_usb_config *config;
-
- config = udc_controller->config;
-
- /* before here, make sure usb_slave_regs has been initialized */
- if (!qh_addr)
- return -EINVAL;
-#endif
-
- /* Stop and reset the usb controller */
- UDC_USBCMD &= ~USB_CMD_RUN_STOP;
-
- UDC_USBCMD |= USB_CMD_CTRL_RESET;
-
- /* Wait for reset to complete */
- timeout = 10000000;
- while ((UDC_USBCMD & USB_CMD_CTRL_RESET) &&
- --timeout) {
- continue;
- }
- if (timeout == 0) {
- logf("%s: TIMEOUT", __FUNCTION__);
- return -ETIMEDOUT;
- }
-
- /* Set the controller as device mode and disable setup lockout */
- UDC_USBMODE |= (USB_MODE_CTRL_MODE_DEVICE | USB_MODE_SETUP_LOCK_OFF);
-
- /* Clear the setup status */
- UDC_USBSTS = 0;
-#if 0
- UDC_ENDPOINTLISTADDR = (unsigned int)qh_addr & USB_EP_LIST_ADDRESS_MASK;
-
- VDBG("qh_addr=0x%x epla_reg=0x%8x", qh_addr, UOG_ASYNCLISTADDR);
-#endif
- UDC_PORTSC1 = (UDC_PORTSC1 & ~PORTSCX_PHY_TYPE_SEL) | PORTSCX_PTS_UTMI;
-#if 0
- if (config->set_vbus_power)
- config->set_vbus_power(0);
-#endif
-
- return 0;
-}
-
-/* just Enable DR irq reg and Set Dr controller Run */
-/* was static void dr_controller_run(struct arcotg_udc *udc) */
-void dr_controller_run(void)
-{
- /*Enable DR irq reg */
- UDC_USBINTR = USB_INTR_INT_EN | USB_INTR_ERR_INT_EN |
- USB_INTR_PTC_DETECT_EN | USB_INTR_RESET_EN |
- USB_INTR_DEVICE_SUSPEND | USB_INTR_SYS_ERR_EN;
-#if 0
- /* Clear stopped bit */
- udc->stopped = 0;
-#endif
- /* Set the controller as device mode */
- UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
-
- /* Set controller to Run */
- UDC_USBCMD |= USB_CMD_RUN_STOP;
-
- return;
-}
-
-/* just Enable DR irq reg and Set Dr controller Run */
-/* was static void dr_controller_stop(struct arcotg_udc *udc) */
-void dr_controller_stop(void)
-{
-#if 0
- /* if we're in OTG mode, and the Host is currently using the port,
- * stop now and don't rip the controller out from under the
- * ehci driver
- */
- if (udc->gadget.is_otg) {
- if (!(UDC_OTGSC & OTGSC_STS_USB_ID)) {
- logf("Leaving early");
- return;
- }
- }
-#endif
-
- /* disable all INTR */
- UDC_USBINTR = 0;
-#if 0
- /* Set stopped bit */
- udc->stopped = 1;
-#endif
- /* Set controller to Stop */
- UDC_USBCMD &= ~USB_CMD_RUN_STOP;
-}
Index: firmware/drivers/usb/arcotg_dcd.c
===================================================================
--- firmware/drivers/usb/arcotg_dcd.c (revision 0)
+++ firmware/drivers/usb/arcotg_dcd.c (revision 0)
@@ -0,0 +1,249 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: arcotg_udc.c 12340 2007-02-16 22:13:21Z barrywardell $
+ *
+ * Copyright (C) 2007 by Christian Gmeiner
+ *
+ * Based on code from the Linux Target Image Builder from Freescale
+ * available at http://www.bitshrine.org/ and
+ * http://www.bitshrine.org/gpp/linux-2.6.16-mx31-usb-2.patch
+ * Adapted for Rockbox in January 2007
+ * Original file: drivers/usb/gadget/arcotg_udc.c
+ *
+ * USB Device Controller Driver
+ * Driver for ARC OTG USB module in the i.MX31 platform, etc.
+ *
+ * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Based on mpc-udc.h
+ * Author: Li Yang (leoli@freescale.com)
+ * Jiang Bo (Tanya.jiang@freescale.com)
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include
+#include "usbstack.h"
+#include "arcotg_dcd.h"
+
+/* description of our usb controller driver */
+struct usb_controller arcotg_dcd = {
+ .name = "arcotg_dcd",
+ .type = DEVICE,
+ .init = usb_arcotg_dcd_init,
+ .shutdown = usb_arcotg_dcd_shutdown,
+ .irq = usb_arcotg_dcd_irq,
+ .start = usb_arcotg_dcd_start,
+ .stop = usb_arcotg_dcd_stop,
+};
+
+static unsigned int timeout;
+static struct arcotg_udc udc_controller;
+static struct eqh qh[USB_MAX_PIPES] IBSS_ATTR;
+
+void usb_dcd_init() {
+
+ logf("arcotg_dcd: registering us");
+ /* register us in the usb stack */
+ usb_controller_register(&arcotg_dcd);
+}
+
+void usb_arcotg_dcd_start(void) {
+
+ logf("arcotg_dcd: start");
+
+ /* enable interrupt sources */
+ UDC_USBINTR = USB_INTR_INT_EN | USB_INTR_ERR_INT_EN |
+ USB_INTR_PTC_DETECT_EN | USB_INTR_RESET_EN |
+ USB_INTR_DEVICE_SUSPEND | USB_INTR_SYS_ERR_EN;
+
+ /* clear stopped bit */
+ udc_controller.stopped = false;
+
+ /* set the controller as device mode */
+ UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
+
+ /* set controller to Run */
+ UDC_USBCMD |= USB_CMD_RUN_STOP;
+}
+
+void usb_arcotg_dcd_stop(void) {
+
+ logf("arcotg_dcd: stop");
+
+ /* disable all interrupts */
+ UDC_USBINTR = 0;
+
+ /* set stopped bit */
+ udc_controller.stopped = true;
+
+ /* set controller to Stop */
+ UDC_USBCMD &= ~USB_CMD_RUN_STOP;
+}
+
+int usb_arcotg_dcd_init(void) {
+
+ logf("arcotg_dcd: init");
+
+ /* do some mysical stuff */
+ outl(inl(0x70000028) &~0x4000, 0x70000028);
+ outl(inl(0x70000028) | 0x2, 0x70000028);
+
+ /* setup data structues */
+ memset(&udc_controller, 0, sizeof(struct arcotg_udc));
+ spinlock_init(&udc_controller.lock);
+
+ /* stop and reset the usb controller */
+ UDC_USBCMD &= ~USB_CMD_RUN_STOP;
+ UDC_USBCMD |= USB_CMD_CTRL_RESET;
+
+ /* wait for reset to complete */
+ timeout = 10000000;
+ while ((UDC_USBCMD & USB_CMD_CTRL_RESET) && -timeout) {
+ continue;
+ }
+
+ if (timeout == 0) {
+ logf("%s: TIMEOUT", __FUNCTION__);
+ return -ETIMEDOUT;
+ }
+
+ /* set the controller as device mode */
+ UDC_USBMODE |= USB_MODE_CTRL_MODE_DEVICE;
+
+ /* init queue heads for ep0 */
+ qh_init(0, USB_RECV, USB_ENDPOINT_XFER_CONTROL, USB_MAX_CTRL_PAYLOAD, 0, 0);
+ qh_init(0, USB_SEND, USB_ENDPOINT_XFER_CONTROL, USB_MAX_CTRL_PAYLOAD, 0, 0);
+
+ /* set address of queue heads */
+ UDC_ENDPOINTLISTADDR = (unsigned int)qh;
+ return 0;
+}
+
+void usb_arcotg_dcd_shutdown(void) {
+
+ logf("arcotg_dcd: shutdown");
+}
+
+void usb_arcotg_dcd_irq(void) {
+
+ unsigned int irq_src = 0;
+
+ spinlock_lock(&udc_controller.lock);
+
+ /* read source of irq */
+ irq_src = UDC_USBSTS & UDC_USBINTR;
+
+ /* TODO */
+ if (irq_src == 0x0) {
+ spinlock_unlock(&udc_controller.lock);
+ return;
+ }
+
+ /* clear notification bits */
+ UDC_USBSTS &= irq_src;
+ logf("irq_src [0x%08x]", irq_src);
+
+ /* USB Interrupt */
+ switch (irq_src) {
+ case USB_STS_INT:
+
+ /* setup packet, we only support ep0 as control ep */
+ if (UDC_ENDPTSETUPSTAT & EP_SETUP_STATUS_EP0) {
+ /* copy data from queue head to local buffer */
+ memcpy(&udc_controller.local_setup_buff, (uint8_t *) &qh[0].setup_buffer, 8);
+ setup_received_int(&udc_controller.local_setup_buff);
+ }
+ break;
+ }
+
+ spinlock_unlock(&udc_controller.lock);
+}
+
+/*
+ * Interrupt handlers
+ */
+void setup_received_int(struct usb_ctrlrequest* request) {
+
+ int handled = 0; /* set to zero if we do not handle the message, */
+ /* and should pass it to the driver */
+
+ /* look what kind of request */
+ if ((request->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+
+ /* what shall we do? */
+ switch (request->bRequest) {
+ case USB_REQ_SET_ADDRESS:
+ /* set recived address */
+ break;
+ }
+ }
+
+ if (handled == 0) {
+ logf("pass it to driver...");
+ /* pass it to device driver */
+ if (arcotg_dcd.device_driver != NULL && arcotg_dcd.device_driver->request != NULL) {
+ arcotg_dcd.device_driver->request(request);
+ }
+ }
+}
+
+
+/*
+ * Lifecycle
+ */
+
+/**
+ * Used to initialise queue head for one endpoint.
+ */
+static void qh_init(unsigned char ep_num, unsigned char dir, unsigned char ep_type,
+ unsigned int max_pkt_len, unsigned int zlt, unsigned char mult) {
+
+ struct eqh *p_QH = &qh[2 * ep_num + dir];
+ uint32_t tmp = 0;
+
+ /* set the Endpoint Capabilites Reg of QH */
+ switch (ep_type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ /* Interrupt On Setup (IOS). for control ep */
+ tmp = (max_pkt_len << LENGTH_BIT_POS) | INTERRUPT_ON_COMPLETE;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ tmp = (max_pkt_len << LENGTH_BIT_POS) | (mult << EP_QUEUE_HEAD_MULT_POS);
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+ tmp = max_pkt_len << LENGTH_BIT_POS;
+ if (zlt) {
+ tmp |= EP_QUEUE_HEAD_ZLT_SEL;
+ }
+ break;
+ default:
+ logf("error ep type is %d", ep_type);
+ return;
+ }
+
+ /* see 32.14.4.1 Queue Head Initialization */
+
+ /* write the wMaxPacketSize field as required by the USB Chapter9 or application specific portocol */
+ p_QH->max_pkt_length = tmp;
+
+ /* write the next dTD Terminate bit fild to 1 */
+ p_QH->td.next_td_ptr = 1;
+
+ /* write the Active bit in the status field to 0 */
+ p_QH->td.caps &= ~STATUS_ACTIVE;
+
+ /* write the Hald bit in the status field to 0 */
+ p_QH->td.caps &= ~STATUS_HALTED;
+}
Index: firmware/drivers/usb/ehcid.c
===================================================================
--- firmware/drivers/usb/ehcid.c (revision 0)
+++ firmware/drivers/usb/ehcid.c (revision 0)
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: arcotg_udc.c 12340 2007-02-16 22:13:21Z barrywardell $
+ *
+ * Copyright (C) 2007 by Christian Gmeiner
+ *
+ * Based on code from the Linux Target Image Builder from Freescale
+ * available at http://www.bitshrine.org/ and
+ * http://www.bitshrine.org/gpp/linux-2.6.16-mx31-usb-2.patch
+ * Adapted for Rockbox in January 2007
+ * Original file: drivers/usb/gadget/arcotg_udc.c
+ *
+ * USB Device Controller Driver
+ * Driver for ARC OTG USB module in the i.MX31 platform, etc.
+ *
+ * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Based on mpc-udc.h
+ * Author: Li Yang (leoli@freescale.com)
+ * Jiang Bo (Tanya.jiang@freescale.com)
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+