Index: apps/main.c =================================================================== --- apps/main.c (revision 16371) +++ apps/main.c (working copy) @@ -444,6 +444,7 @@ #endif usb_start_monitoring(); +#ifndef HAVE_SOFTWARE_USB while (usb_detect() == USB_INSERTED) { #ifdef HAVE_EEPROM_SETTINGS @@ -464,6 +465,7 @@ break; #endif } +#endif /* HAVE_SOFTWARE_USB */ if (!mounted) { Index: firmware/export/usb_core.h =================================================================== --- firmware/export/usb_core.h (revision 16371) +++ 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 16371) +++ firmware/export/usb.h (working copy) @@ -23,15 +23,24 @@ #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 +enum { + USB_INSERTED, + USB_EXTRACTED, + USB_REENABLE, + USB_POWERED, + USB_TRANSFER_COMPLETION +}; + +#ifdef HAVE_USBSTACK +enum { + USB_DRIVER_MASS_STORAGE, + USB_DRIVER_SERIAL, + USB_DRIVER_CHARGING_ONLY, + USB_DRIVER_COUNT +}; #endif #ifdef HAVE_USB_POWER -#define USB_POWERED 4 - #if CONFIG_KEYPAD == RECORDER_PAD #define USBPOWER_BUTTON BUTTON_F1 #define USBPOWER_BTN_IGNORE BUTTON_ON @@ -61,6 +70,17 @@ #endif #endif /* HAVE_USB_POWER */ +#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); void usb_enable(bool on); void usb_start_monitoring(void); @@ -76,5 +96,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 16371) +++ firmware/usbstack/usb_core.c (working copy) @@ -23,12 +23,11 @@ //#define LOGF_ENABLE #include "logf.h" +#include "usb.h" #include "usb_ch9.h" #include "usb_drv.h" #include "usb_core.h" -#define USB_THREAD - #if defined(USB_STORAGE) #include "usb_storage.h" #endif @@ -275,15 +274,13 @@ 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); +static bool usb_core_storage_enabled = false; +static bool usb_core_serial_enabled = false; +static bool usb_core_charging_enabled = false; +#if defined(USB_BENCHMARK) +static bool usb_core_benchmark_enabled = false; #endif static void usb_core_control_request_handler(struct usb_ctrlrequest* req); @@ -292,17 +289,8 @@ 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) { @@ -357,8 +345,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 @@ -367,14 +358,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 @@ -387,74 +370,58 @@ { 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) -{ -#if defined(IPOD_ARCH) || defined(HAVE_AS3514) - set_serial_descriptor(); -#endif - - 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 +void usb_core_enable_protocol(int driver,bool enabled) +{ + 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) { - /* note: interrupt context */ - data_connection = true; #if defined(IPOD_ARCH) || defined(HAVE_AS3514) if(usb_state == DEFAULT) { @@ -476,11 +443,13 @@ if (req->wValue){ usb_state = CONFIGURED; #ifdef USB_STORAGE - usb_storage_control_request(req); + if(usb_core_storage_enabled) + usb_storage_control_request(req); #endif #ifdef USB_SERIAL - usb_serial_control_request(req); + if(usb_core_serial_enabled) + usb_serial_control_request(req); #endif } else { @@ -597,48 +566,56 @@ size = sizeof(config_descriptor); #ifdef USB_CHARGING_ONLY - charging_interface_descriptor.bInterfaceNumber=interface_number; - interface_number++; - memcpy(&response_data[size],&charging_interface_descriptor,sizeof(struct usb_interface_descriptor)); - size += sizeof(struct usb_interface_descriptor); + if(usb_core_charging_enabled){ + charging_interface_descriptor.bInterfaceNumber=interface_number; + interface_number++; + memcpy(&response_data[size],&charging_interface_descriptor,sizeof(struct usb_interface_descriptor)); + size += sizeof(struct usb_interface_descriptor); + } #endif #ifdef USB_STORAGE - mass_storage_ep_in_descriptor.wMaxPacketSize=max_packet_size; - mass_storage_ep_out_descriptor.wMaxPacketSize=max_packet_size; - mass_storage_interface_descriptor.bInterfaceNumber=interface_number; - interface_number++; + if(usb_core_storage_enabled){ + mass_storage_ep_in_descriptor.wMaxPacketSize=max_packet_size; + mass_storage_ep_out_descriptor.wMaxPacketSize=max_packet_size; + mass_storage_interface_descriptor.bInterfaceNumber=interface_number; + interface_number++; - memcpy(&response_data[size],&mass_storage_interface_descriptor,sizeof(struct usb_interface_descriptor)); - size += sizeof(struct usb_interface_descriptor); - memcpy(&response_data[size],&mass_storage_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); - size += sizeof(struct usb_endpoint_descriptor); - memcpy(&response_data[size],&mass_storage_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); - size += sizeof(struct usb_endpoint_descriptor); + memcpy(&response_data[size],&mass_storage_interface_descriptor,sizeof(struct usb_interface_descriptor)); + size += sizeof(struct usb_interface_descriptor); + memcpy(&response_data[size],&mass_storage_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); + size += sizeof(struct usb_endpoint_descriptor); + memcpy(&response_data[size],&mass_storage_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); + size += sizeof(struct usb_endpoint_descriptor); + } #endif #ifdef USB_SERIAL - serial_ep_in_descriptor.wMaxPacketSize=max_packet_size; - serial_ep_out_descriptor.wMaxPacketSize=max_packet_size; - serial_interface_descriptor.bInterfaceNumber=interface_number; - interface_number++; + if(usb_core_serial_enabled){ + serial_ep_in_descriptor.wMaxPacketSize=max_packet_size; + serial_ep_out_descriptor.wMaxPacketSize=max_packet_size; + serial_interface_descriptor.bInterfaceNumber=interface_number; + interface_number++; - memcpy(&response_data[size],&serial_interface_descriptor,sizeof(struct usb_interface_descriptor)); - size += sizeof(struct usb_interface_descriptor); - memcpy(&response_data[size],&serial_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); - size += sizeof(struct usb_endpoint_descriptor); - memcpy(&response_data[size],&serial_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); - size += sizeof(struct usb_endpoint_descriptor); + memcpy(&response_data[size],&serial_interface_descriptor,sizeof(struct usb_interface_descriptor)); + size += sizeof(struct usb_interface_descriptor); + memcpy(&response_data[size],&serial_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); + size += sizeof(struct usb_endpoint_descriptor); + memcpy(&response_data[size],&serial_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); + size += sizeof(struct usb_endpoint_descriptor); + } #endif #ifdef USB_BENCHMARK - benchmark_ep_in_descriptor.wMaxPacketSize=max_packet_size; - benchmark_ep_out_descriptor.wMaxPacketSize=max_packet_size; - config_descriptor.bNumInterfaces=interface_number; + if(usb_core_benchmark_enabled){ + benchmark_ep_in_descriptor.wMaxPacketSize=max_packet_size; + benchmark_ep_out_descriptor.wMaxPacketSize=max_packet_size; + config_descriptor.bNumInterfaces=interface_number; - memcpy(&response_data[size],&benchmark_interface_descriptor,sizeof(struct usb_interface_descriptor)); - size += sizeof(struct usb_interface_descriptor); - memcpy(&response_data[size],&benchmark_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); - size += sizeof(struct usb_endpoint_descriptor); - memcpy(&response_data[size],&benchmark_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); - size += sizeof(struct usb_endpoint_descriptor); + memcpy(&response_data[size],&benchmark_interface_descriptor,sizeof(struct usb_interface_descriptor)); + size += sizeof(struct usb_interface_descriptor); + memcpy(&response_data[size],&benchmark_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); + size += sizeof(struct usb_endpoint_descriptor); + memcpy(&response_data[size],&benchmark_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); + size += sizeof(struct usb_endpoint_descriptor); + } #endif config_descriptor.wTotalLength = size; memcpy(&response_data[0],&config_descriptor,sizeof(struct usb_config_descriptor)); @@ -698,13 +675,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; } @@ -727,7 +704,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; } } @@ -741,7 +718,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 16371) +++ 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 16371) +++ 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 16371) +++ 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" @@ -448,6 +449,7 @@ /* port change */ if (status & USBSTS_PORT_CHANGE) { REG_USBSTS |= USBSTS_PORT_CHANGE; + logf("PC INT : %d",REG_PORTSC1&PORTSCX_CURRENT_CONNECT_STATUS); } } Index: firmware/usb.c =================================================================== --- firmware/usb.c (revision 16371) +++ 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)