Index: apps/main.c =================================================================== --- apps/main.c (revision 16422) +++ apps/main.c (working copy) @@ -444,6 +444,7 @@ #endif usb_start_monitoring(); +#ifndef HAVE_USBSTACK while (usb_detect() == USB_INSERTED) { #ifdef HAVE_EEPROM_SETTINGS @@ -464,6 +465,7 @@ break; #endif } +#endif /* HAVE_USBSTACK */ if (!mounted) { Index: firmware/export/usb_core.h =================================================================== --- firmware/export/usb_core.h (revision 16422) +++ firmware/export/usb_core.h (working copy) @@ -20,34 +20,23 @@ #define USB_CORE_H #ifndef BOOTLOADER -#define USB_THREAD -#ifdef USE_ROCKBOX_USB //#define USB_SERIAL //#define USB_BENCHMARK #define USB_STORAGE - -#else #define USB_CHARGING_ONLY - -#endif /* USE_ROCKBOX_USB */ -#else +#else /* BOOTLOADER */ #define USB_CHARGING_ONLY #endif /* BOOTLOADER */ #include "usb_ch9.h" +#include "usb.h" #if defined(CPU_PP) #define USB_IRAM_ORIGIN ((unsigned char *)0x4000c000) #define USB_IRAM_SIZE ((size_t)0xc000) #endif - -enum { - USB_CORE_QUIT, - USB_CORE_TRANSFER_COMPLETION -}; - /* endpoints */ enum { EP_CONTROL = 0, @@ -66,16 +55,6 @@ NUM_ENDPOINTS }; - -/* queue events */ -#define USB_TRANSFER_COMPLETE 1 - -struct queue_msg { - int endpoint; - int length; - void* data; -}; - extern int usb_max_pkt_size; void usb_core_init(void); @@ -83,7 +62,8 @@ void usb_core_control_request(struct usb_ctrlrequest* req); void usb_core_transfer_complete(int endpoint, bool in, int status, int length); void usb_core_bus_reset(void); -bool usb_core_data_connection(void); - +bool usb_core_exclusive_connection(void); +void usb_core_enable_protocol(int driver,bool enabled); +void usb_core_handle_transfer_completion(struct usb_transfer_completion_event_data* event); #endif Index: firmware/export/usb.h =================================================================== --- firmware/export/usb.h (revision 16422) +++ firmware/export/usb.h (working copy) @@ -23,15 +23,16 @@ #include "button.h" /* Messages from usb_tick and thread states */ -#define USB_INSERTED 1 -#define USB_EXTRACTED 2 -#ifdef HAVE_MMC -#define USB_REENABLE 3 -#endif +enum { + USB_INSERTED, + USB_EXTRACTED, + USB_REENABLE, + USB_POWERED, + USB_TRANSFER_COMPLETION +}; + #ifdef HAVE_USB_POWER -#define USB_POWERED 4 - #if CONFIG_KEYPAD == RECORDER_PAD #define USBPOWER_BUTTON BUTTON_F1 #define USBPOWER_BTN_IGNORE BUTTON_ON @@ -70,6 +71,16 @@ USB_DRIVER_COUNT }; #endif +#ifdef HAVE_USBSTACK +struct usb_transfer_completion_event_data +{ + unsigned char endpoint; + bool in; + int status; + int length; + void* data; +}; +#endif void usb_init(void); @@ -87,5 +98,9 @@ bool usb_charging_enabled(void); #endif #endif +#ifdef HAVE_USBSTACK +void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data); +bool usb_driver_enabled(int driver); +#endif #endif Index: firmware/usbstack/usb_core.c =================================================================== --- firmware/usbstack/usb_core.c (revision 16422) +++ firmware/usbstack/usb_core.c (working copy) @@ -28,8 +28,6 @@ #include "usb_drv.h" #include "usb_core.h" -#define USB_THREAD - #if defined(USB_STORAGE) #include "usb_storage.h" #endif @@ -289,46 +287,23 @@ static int usb_address = 0; static bool initialized = false; -static bool data_connection = false; -static struct event_queue usbcore_queue; static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state; -#ifdef USB_THREAD -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 - -#ifdef USE_ROCKBOX_USB +static bool usb_core_storage_enabled = false; +static bool usb_core_serial_enabled = false; static bool usb_core_charging_enabled = false; -static bool usb_core_storage_enabled = true; -static bool usb_core_serial_enabled = true; #if defined(USB_BENCHMARK) static bool usb_core_benchmark_enabled = false; #endif -#else -static bool usb_core_charging_enabled = true; -#endif - static void usb_core_control_request_handler(struct usb_ctrlrequest* req); static int ack_control(struct usb_ctrlrequest* req); static unsigned char *response_data; static unsigned char __response_data[CACHEALIGN_UP(256)] CACHEALIGN_ATTR; -struct usb_core_event -{ - unsigned char endpoint; - bool in; - int status; - int length; - void* data; -}; +static struct usb_transfer_completion_event_data events[NUM_ENDPOINTS]; -static struct usb_core_event events[NUM_ENDPOINTS]; - #ifdef IPOD_ARCH static void set_serial_descriptor(void) { @@ -408,8 +383,11 @@ response_data = (void*)UNCACHED_ADDR(&__response_data); - queue_init(&usbcore_queue, false); usb_drv_init(); + + /* class driver init functions should be safe to call even if the driver + * won't be used. This simplifies other logic (i.e. we don't need to know + * yet which drivers will be enabled */ #ifdef USB_STORAGE usb_storage_init(); #endif @@ -418,14 +396,6 @@ usb_serial_init(); #endif -#ifdef USB_THREAD - 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 @@ -438,71 +408,57 @@ { if (initialized) { usb_drv_exit(); -#ifdef USB_THREAD - queue_post(&usbcore_queue, USB_CORE_QUIT, 0); - thread_wait(usbcore_thread); -#endif - queue_delete(&usbcore_queue); } - data_connection = false; initialized = false; logf("usb_core_exit() finished"); } -bool usb_core_data_connection(void) +void usb_core_handle_transfer_completion(struct usb_transfer_completion_event_data* event) { - return data_connection; -} - -#ifdef USB_THREAD -void usb_core_thread(void) -{ - while (1) { - struct queue_event ev; - - queue_wait(&usbcore_queue, &ev); - if (ev.id == USB_CORE_QUIT) { - cancel_cpu_boost(); - return; - } - - if (ev.id == USB_CORE_TRANSFER_COMPLETION) { - struct usb_core_event* event = (struct usb_core_event*)ev.data; - switch(event->endpoint) { - case EP_CONTROL: - logf("ctrl handled %ld",current_tick); - usb_core_control_request_handler((struct usb_ctrlrequest*)event->data); - break; + switch(event->endpoint) { + case EP_CONTROL: + logf("ctrl handled %ld",current_tick); + usb_core_control_request_handler((struct usb_ctrlrequest*)event->data); + break; #ifdef USB_STORAGE - case EP_MASS_STORAGE: - usb_storage_transfer_complete(event->in,event->status,event->length); - break; + case EP_MASS_STORAGE: + usb_storage_transfer_complete(event->in,event->status,event->length); + break; #endif #ifdef USB_SERIAL - case EP_SERIAL: - usb_serial_transfer_complete(event->in,event->status,event->length); - break; + case EP_SERIAL: + usb_serial_transfer_complete(event->in,event->status,event->length); + break; #endif #ifdef USB_BENCHMARK - case EP_BENCHMARK: - usb_benchmark_transfer_complete(event->in); - break; + case EP_BENCHMARK: + usb_benchmark_transfer_complete(event->in); + break; #endif #ifdef USB_CHARGING_ONLY - case EP_CHARGING_ONLY: - break; + case EP_CHARGING_ONLY: + break; #endif - } - } } } -#endif -static void usb_core_control_request_handler(struct usb_ctrlrequest* req) +void usb_core_enable_protocol(int driver,bool enabled) { - /* note: interrupt context */ - data_connection = true; + switch(driver) { + case USB_DRIVER_MASS_STORAGE: + usb_core_storage_enabled = enabled; + break; + case USB_DRIVER_SERIAL: + usb_core_serial_enabled = enabled; + break; + case USB_DRIVER_CHARGING_ONLY: + usb_core_charging_enabled = enabled; + break; + } +} +static void usb_core_control_request_handler(struct usb_ctrlrequest* req) +{ if(usb_state == DEFAULT) { set_serial_descriptor(); } @@ -753,13 +709,13 @@ } break; } + logf("control handled"); } /* called by usb_drv_int() */ void usb_core_bus_reset(void) { usb_address = 0; - data_connection = false; usb_state = DEFAULT; } @@ -782,7 +738,7 @@ events[endpoint].status=status; events[endpoint].length=length; /* All other endoints. Let the thread deal with it */ - queue_post(&usbcore_queue, USB_CORE_TRANSFER_COMPLETION, (intptr_t)&events[endpoint]); + usb_signal_transfer_completion(&events[endpoint]); break; } } @@ -796,7 +752,7 @@ events[0].status=0; events[0].length=0; logf("ctrl received %ld",current_tick); - queue_post(&usbcore_queue, USB_CORE_TRANSFER_COMPLETION,(intptr_t)&events[0]); + usb_signal_transfer_completion(&events[0]); } static int ack_control(struct usb_ctrlrequest* req) Index: firmware/usbstack/usb_storage.c =================================================================== --- firmware/usbstack/usb_storage.c (revision 16422) +++ firmware/usbstack/usb_storage.c (working copy) @@ -224,7 +224,7 @@ SENDING_CSW } state = WAITING_FOR_COMMAND; -/* called by usb_code_init() */ +/* called by usb_core_init(). Can safely be called multiple times. */ void usb_storage_init(void) { transfer_buffer = (void*)UNCACHED_ADDR(&_transfer_buffer); Index: firmware/target/arm/usb-fw-pp502x.c =================================================================== --- firmware/target/arm/usb-fw-pp502x.c (revision 16422) +++ firmware/target/arm/usb-fw-pp502x.c (working copy) @@ -70,33 +70,25 @@ void usb_enable(bool on) { if (on) { - usb_core_init(); -#if !defined(USE_ROCKBOX_USB) - /* until we have native mass-storage mode, we want to reboot on - usb host connect */ -#if defined(IRIVER_H10) || defined (IRIVER_H10_5GB) - if (button_status()==BUTTON_RIGHT) -#endif /* defined(IRIVER_H10) || defined (IRIVER_H10_5GB) */ - { -#ifndef HAVE_FLASH_STORAGE - ata_sleepnow(); /* Immediately spindown the disk. */ - sleep(HZ*2); -#endif - -#ifdef IPOD_ARCH /* The following code is based on ipodlinux */ + /* if USB is detected, re-enable the USB-devices, otherwise make sure it's disabled */ + DEV_EN |= DEV_USB0; + DEV_RS &=~DEV_USB0; + DEV_EN |= DEV_USB1; + DEV_RS &=~DEV_USB1; #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 /* CONFIG_CPU */ -#endif /* IPOD_ARCH */ - - system_reboot(); /* Reboot */ - } -#endif /* USE_ROCKBOX_USB */ + DEV_INIT2 |= INIT_USB; +#endif + usb_core_init(); } - else + else { usb_core_exit(); + /* Disable USB devices */ + DEV_EN &=~ DEV_USB0; + DEV_EN &=~ DEV_USB1; +#if CONFIG_CPU == PP5020 + DEV_INIT2 &=~ INIT_USB; +#endif + } } static bool usb_pin_detect(void) @@ -136,11 +128,6 @@ /* detect host or charger (INSERTED or POWERED) */ int usb_detect(void) { - static int countdown = 0; - static int status = USB_EXTRACTED; - static bool prev_usbstatus1 = false; - bool usbstatus1, usbstatus2; - #if defined(IPOD_COLOR) || defined(IPOD_4G) \ || defined(IPOD_MINI) || defined(IPOD_MINI2G) /* GPIO C bit 1 is firewire detect */ @@ -149,67 +136,10 @@ return USB_INSERTED; #endif - if (countdown > 0) - { - countdown--; - - usbstatus2 = usb_core_data_connection(); - if ((countdown == 0) || usbstatus2) - { - /* We now know that we have been connected to either a charger - or a computer */ - countdown = 0; - status = usbstatus2 ? USB_INSERTED : USB_POWERED; - } - return status; + if(usb_pin_detect()) { + return USB_INSERTED; } - - usbstatus1 = usb_pin_detect(); - - if (usbstatus1 == prev_usbstatus1) - { - /* Nothing has changed, so just return previous status */ - return status; + else { + return USB_EXTRACTED; } - prev_usbstatus1 = usbstatus1; - - if (!usbstatus1) - { /* We have just been disconnected */ - status = USB_EXTRACTED; - - /* Disable USB devices */ - DEV_EN &=~ DEV_USB0; - DEV_EN &=~ DEV_USB1; -#if CONFIG_CPU == PP5020 - DEV_INIT2 &=~ INIT_USB; -#endif - - return status; - } else { - /* if USB is detected, re-enable the USB-devices, otherwise make sure it's disabled */ - DEV_EN |= DEV_USB0; - DEV_RS &=~DEV_USB0; - DEV_EN |= DEV_USB1; - DEV_RS &=~DEV_USB1; -#if CONFIG_CPU == PP5020 - DEV_INIT2 |= INIT_USB; -#endif - } - - /* Run the USB stack to request full bus power */ - usb_core_init(); - - if((button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON) - { - /* The user wants to charge, so it doesn't matter what we are - connected to. */ - status = USB_POWERED; - return status; - } - - /* Wait up to 100 ticks (1s) before deciding there is no computer - attached. */ - countdown = 100; - - return status; } Index: firmware/target/arm/usb-drv-pp502x.c =================================================================== --- firmware/target/arm/usb-drv-pp502x.c (revision 16422) +++ firmware/target/arm/usb-drv-pp502x.c (working copy) @@ -23,6 +23,7 @@ #include "string.h" #include "usb_ch9.h" #include "usb_core.h" +#include "usb.h" //#define LOGF_ENABLE #include "logf.h" Index: firmware/usb.c =================================================================== --- firmware/usb.c (revision 16422) +++ firmware/usb.c (working copy) @@ -37,6 +37,9 @@ #include "sprintf.h" #include "string.h" #include "usb-target.h" +#ifdef HAVE_USBSTACK +#include "usb_core.h" +#endif #ifdef IRIVER_H300_SERIES #include "pcf50606.h" /* for pcf50606_usb_charging_... */ #endif @@ -72,6 +75,7 @@ #ifndef BOOTLOADER +#ifndef HAVE_USBSTACK static void usb_slave_mode(bool on) { int rc; @@ -88,10 +92,8 @@ { DEBUGF("Leaving USB slave mode\n"); -#ifndef HAVE_USBSTACK /* Let the ISDx00 settle */ sleep(HZ*1); -#endif usb_enable(false); @@ -116,6 +118,7 @@ } } +#endif static void usb_thread(void) { @@ -130,6 +133,11 @@ queue_wait(&usb_queue, &ev); switch(ev.id) { +#ifdef HAVE_USBSTACK + case USB_TRANSFER_COMPLETION: + usb_core_handle_transfer_completion((struct usb_transfer_completion_event_data*)ev.data); + break; +#endif #ifdef HAVE_USB_POWER case USB_POWERED: usb_state = USB_POWERED; @@ -147,6 +155,12 @@ if((button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON) { usb_state = USB_POWERED; +#ifdef HAVE_USBSTACK + usb_core_enable_protocol(USB_DRIVER_MASS_STORAGE,false); + usb_core_enable_protocol(USB_DRIVER_SERIAL,false);/* TODO: add debug setting */ + usb_core_enable_protocol(USB_DRIVER_CHARGING_ONLY,true); + usb_enable(true); +#endif } else #endif @@ -168,9 +182,16 @@ if(num_acks_to_expect == 0) { DEBUGF("All threads have acknowledged the connect.\n"); +#ifdef HAVE_USBSTACK + usb_core_enable_protocol(USB_DRIVER_MASS_STORAGE,true); + usb_core_enable_protocol(USB_DRIVER_SERIAL,false);/* TODO: add debug setting */ + usb_core_enable_protocol(USB_DRIVER_CHARGING_ONLY,false); + usb_enable(true); +#else usb_slave_mode(true); usb_state = USB_INSERTED; cpu_idle_mode(true); +#endif } else { @@ -181,6 +202,9 @@ break; case USB_EXTRACTED: +#ifdef HAVE_USBSTACK + usb_enable(false); +#endif #ifdef HAVE_LCD_BITMAP if(do_screendump_instead_of_usb) break; @@ -192,6 +216,7 @@ break; } #endif +#ifndef HAVE_USBSTACK if(usb_state == USB_INSERTED) { /* Only disable the USB mode if we really have enabled it @@ -200,6 +225,7 @@ usb_slave_mode(false); cpu_idle_mode(false); } +#endif usb_state = USB_EXTRACTED; @@ -248,6 +274,12 @@ } #endif +#ifdef HAVE_USBSTACK +void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data) +{ + queue_post(&usb_queue, USB_TRANSFER_COMPLETION, (intptr_t)event_data); +} +#endif #ifndef BOOTLOADER static void usb_tick(void)