USB retweaking: Take out the USB_REQUEST/RELEASE_DISK scheme and simply ask the USB core whether or not any drivers require exclusive access at the moment of connect. Doing anthing else just produces nasty effects on Windows because it expects some communication just for enabling the PHY and not allowing it to mount volumes if a thread doesn't ack causes annoying error message boxes. Make behavior of each USB type identical from the system perspective. Some miscellaneous changes (simplify, ata->storage naming, define only used USB_* enums values were possible).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19762 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
30414d56c9
commit
6da8b4eb49
9 changed files with 267 additions and 267 deletions
|
@ -2575,7 +2575,7 @@ static bool logf_usb_serial(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_USBSTACK) && defined(USB_STORAGE)
|
||||
#if 0 && defined(HAVE_USBSTACK) && defined(USB_STORAGE)
|
||||
static bool usb_reconnect(void)
|
||||
{
|
||||
splash(HZ, "Reconnect mass storage");
|
||||
|
@ -2720,7 +2720,7 @@ static const struct the_menu_item menuitems[] = {
|
|||
#if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) && defined(USB_SERIAL)
|
||||
{"logf over usb",logf_usb_serial },
|
||||
#endif
|
||||
#if defined(HAVE_USBSTACK) && defined(USB_STORAGE)
|
||||
#if 0 && defined(HAVE_USBSTACK) && defined(USB_STORAGE)
|
||||
{"reconnect usb storage",usb_reconnect},
|
||||
#endif
|
||||
#ifdef CPU_BOOST_LOGGING
|
||||
|
|
|
@ -61,8 +61,9 @@
|
|||
#define CMD_SET_FEATURES 0xEF
|
||||
#define CMD_SECURITY_FREEZE_LOCK 0xF5
|
||||
|
||||
#define Q_SLEEP 0
|
||||
#define Q_CLOSE 1
|
||||
/* Should all be < 0x100 (which are reserved for control messages) */
|
||||
#define Q_SLEEP 0
|
||||
#define Q_CLOSE 1
|
||||
|
||||
#define READ_TIMEOUT 5*HZ
|
||||
|
||||
|
@ -143,7 +144,7 @@ static void ata_lock_unlock(struct ata_lock *l)
|
|||
#define mutex_unlock ata_lock_unlock
|
||||
#endif /* MAX_PHYS_SECTOR_SIZE */
|
||||
|
||||
#if defined(HAVE_USBSTACK) && defined(USE_ROCKBOX_USB) && !defined(BOOTLOADER)
|
||||
#if defined(HAVE_USBSTACK) && defined(USE_ROCKBOX_USB)
|
||||
#define ALLOW_USB_SPINDOWN
|
||||
#endif
|
||||
|
||||
|
@ -164,7 +165,7 @@ static bool lba48 = false; /* set for 48 bit addressing */
|
|||
#endif
|
||||
static long ata_stack[(DEFAULT_STACK_SIZE*3)/sizeof(long)];
|
||||
static const char ata_thread_name[] = "ata";
|
||||
static struct event_queue ata_queue;
|
||||
static struct event_queue ata_queue SHAREDBSS_ATTR;
|
||||
static bool initialized = false;
|
||||
|
||||
static long last_user_activity = -1;
|
||||
|
@ -910,7 +911,9 @@ static void ata_thread(void)
|
|||
#ifdef ALLOW_USB_SPINDOWN
|
||||
if(!usb_mode)
|
||||
#endif
|
||||
{
|
||||
call_storage_idle_notifys(false);
|
||||
}
|
||||
last_seen_mtx_unlock = 0;
|
||||
}
|
||||
}
|
||||
|
@ -923,7 +926,9 @@ static void ata_thread(void)
|
|||
#ifdef ALLOW_USB_SPINDOWN
|
||||
if(!usb_mode)
|
||||
#endif
|
||||
{
|
||||
call_storage_idle_notifys(true);
|
||||
}
|
||||
ata_perform_sleep();
|
||||
last_sleep = current_tick;
|
||||
}
|
||||
|
@ -935,14 +940,21 @@ static void ata_thread(void)
|
|||
{
|
||||
mutex_lock(&ata_mtx);
|
||||
ide_power_enable(false);
|
||||
mutex_unlock(&ata_mtx);
|
||||
poweroff = true;
|
||||
mutex_unlock(&ata_mtx);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifndef USB_NONE
|
||||
case SYS_USB_CONNECTED:
|
||||
/* Tell the USB thread that we are safe */
|
||||
DEBUGF("ata_thread got SYS_USB_CONNECTED\n");
|
||||
#ifdef ALLOW_USB_SPINDOWN
|
||||
usb_mode = true;
|
||||
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
||||
/* There is no need to force ATA power on */
|
||||
#else
|
||||
if (poweroff) {
|
||||
mutex_lock(&ata_mtx);
|
||||
ata_led(true);
|
||||
|
@ -951,14 +963,8 @@ static void ata_thread(void)
|
|||
mutex_unlock(&ata_mtx);
|
||||
}
|
||||
|
||||
/* Tell the USB thread that we are safe */
|
||||
DEBUGF("ata_thread got SYS_USB_CONNECTED\n");
|
||||
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
||||
|
||||
#ifdef ALLOW_USB_SPINDOWN
|
||||
usb_mode = true;
|
||||
#else
|
||||
/* Wait until the USB cable is extracted again */
|
||||
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
||||
usb_wait_for_disconnect(&ata_queue);
|
||||
#endif
|
||||
break;
|
||||
|
@ -971,12 +977,15 @@ static void ata_thread(void)
|
|||
usb_mode = false;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#endif /* USB_NONE */
|
||||
|
||||
case Q_SLEEP:
|
||||
#ifdef ALLOW_USB_SPINDOWN
|
||||
if(!usb_mode)
|
||||
#endif
|
||||
{
|
||||
call_storage_idle_notifys(false);
|
||||
}
|
||||
last_disk_activity = current_tick - sleep_timeout + (HZ/2);
|
||||
break;
|
||||
|
||||
|
|
|
@ -24,20 +24,33 @@
|
|||
#include "kernel.h"
|
||||
#include "button.h"
|
||||
|
||||
#if defined(IPOD_COLOR) || defined(IPOD_4G) \
|
||||
|| defined(IPOD_MINI) || defined(IPOD_MINI2G)
|
||||
#define USB_FIREWIRE_HANDLING
|
||||
#endif
|
||||
|
||||
/* Messages from usb_tick and thread states */
|
||||
enum {
|
||||
USB_INSERTED,
|
||||
USB_EXTRACTED,
|
||||
USB_REENABLE,
|
||||
USB_POWERED,
|
||||
USB_TRANSFER_COMPLETION,
|
||||
USB_REQUEST_DISK,
|
||||
USB_RELEASE_DISK,
|
||||
USB_REQUEST_REBOOT,
|
||||
USB_QUIT,
|
||||
USB_INSERTED, /* Event+State */
|
||||
USB_EXTRACTED, /* Event+State */
|
||||
#ifdef HAVE_USB_POWER
|
||||
USB_POWERED, /* State */
|
||||
#endif
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
USB_SCREENDUMP, /* State */
|
||||
#endif
|
||||
#if (CONFIG_STORAGE & STORAGE_MMC)
|
||||
USB_REENABLE, /* Event */
|
||||
#endif
|
||||
#ifdef HAVE_USBSTACK
|
||||
USB_TRANSFER_COMPLETION, /* Event */
|
||||
#endif
|
||||
#ifdef USB_FIREWIRE_HANDLING
|
||||
USB_REQUEST_REBOOT, /* Event */
|
||||
#endif
|
||||
USB_QUIT, /* Event */
|
||||
};
|
||||
|
||||
|
||||
#ifdef HAVE_USB_POWER
|
||||
#if CONFIG_KEYPAD == RECORDER_PAD
|
||||
#define USBPOWER_BUTTON BUTTON_F1
|
||||
|
@ -111,13 +124,10 @@ bool usb_charging_enabled(void);
|
|||
#ifdef HAVE_USBSTACK
|
||||
void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data);
|
||||
bool usb_driver_enabled(int driver);
|
||||
bool usb_exclusive_ata(void); /* ata is available for usb */
|
||||
void usb_request_exclusive_ata(void);
|
||||
void usb_release_exclusive_ata(void);
|
||||
bool usb_exclusive_storage(void); /* storage is available for usb */
|
||||
#endif
|
||||
|
||||
#if defined(IPOD_COLOR) || defined(IPOD_4G) \
|
||||
|| defined(IPOD_MINI) || defined(IPOD_MINI2G)
|
||||
#ifdef USB_FIREWIRE_HANDLING
|
||||
bool firewire_detect(void);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ void usb_core_exit(void);
|
|||
void usb_core_control_request(struct usb_ctrlrequest* req);
|
||||
void usb_core_transfer_complete(int endpoint, int dir, int status, int length);
|
||||
void usb_core_bus_reset(void);
|
||||
bool usb_core_exclusive_connection(void);
|
||||
bool usb_core_any_exclusive_storage(void);
|
||||
void usb_core_enable_driver(int driver,bool enabled);
|
||||
bool usb_core_driver_enabled (int driver);
|
||||
void usb_core_handle_transfer_completion(
|
||||
|
|
401
firmware/usb.c
401
firmware/usb.c
|
@ -79,7 +79,7 @@ static int usb_mmc_countdown = 0;
|
|||
static long usb_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)];
|
||||
static const char usb_thread_name[] = "usb";
|
||||
static unsigned int usb_thread_entry = 0;
|
||||
#endif
|
||||
#endif /* USB_FULL_INIT */
|
||||
static struct event_queue usb_queue;
|
||||
static int last_usb_status;
|
||||
static bool usb_monitor_enabled;
|
||||
|
@ -87,47 +87,15 @@ static bool usb_monitor_enabled;
|
|||
static bool exclusive_storage_access;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(IPOD_COLOR) || defined(IPOD_4G) \
|
||||
|| defined(IPOD_MINI) || defined(IPOD_MINI2G)
|
||||
#ifdef USB_FIREWIRE_HANDLING
|
||||
static int firewire_countdown;
|
||||
static bool last_firewire_status;
|
||||
#endif
|
||||
|
||||
#ifdef USB_FULL_INIT
|
||||
#ifndef HAVE_USBSTACK
|
||||
static void usb_slave_mode(bool on)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if(on)
|
||||
{
|
||||
DEBUGF("Entering USB slave mode\n");
|
||||
storage_soft_reset();
|
||||
storage_init();
|
||||
storage_enable(false);
|
||||
usb_enable(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGF("Leaving USB slave mode\n");
|
||||
|
||||
/* Let the ISDx00 settle */
|
||||
sleep(HZ*1);
|
||||
|
||||
usb_enable(false);
|
||||
|
||||
rc = storage_init();
|
||||
if(rc)
|
||||
panicf("storage: %d",rc);
|
||||
|
||||
rc = disk_mount_all();
|
||||
if (rc <= 0) /* no partition */
|
||||
panicf("mount: %d",rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USB_FIREWIRE_HANDLING) \
|
||||
|| (defined(HAVE_USBSTACK) && !defined(USE_ROCKBOX_USB))
|
||||
static void try_reboot(void)
|
||||
{
|
||||
#ifdef HAVE_DISK_STORAGE
|
||||
|
@ -145,15 +113,111 @@ static void try_reboot(void)
|
|||
|
||||
system_reboot(); /* Reboot */
|
||||
}
|
||||
#endif /* USB_FIRWIRE_HANDLING || (HAVE_USBSTACK && !USE_ROCKBOX_USB) */
|
||||
|
||||
#ifdef HAVE_USBSTACK
|
||||
/* inline since branch is chosen at compile time */
|
||||
static inline void usb_slave_mode(bool on)
|
||||
{
|
||||
#ifdef USE_ROCKBOX_USB
|
||||
int rc;
|
||||
|
||||
if (on)
|
||||
{
|
||||
trigger_cpu_boost();
|
||||
#ifdef HAVE_PRIORITY_SCHEDULING
|
||||
thread_set_priority(THREAD_ID_CURRENT, PRIORITY_REALTIME);
|
||||
#endif
|
||||
usb_enable(true);
|
||||
}
|
||||
else /* usb_state == USB_INSERTED (only!) */
|
||||
{
|
||||
usb_enable(false);
|
||||
#ifdef HAVE_PRIORITY_SCHEDULING
|
||||
thread_set_priority(THREAD_ID_CURRENT, PRIORITY_SYSTEM);
|
||||
#endif
|
||||
/* Entered exclusive mode */
|
||||
rc = disk_mount_all();
|
||||
if (rc <= 0) /* no partition */
|
||||
panicf("mount: %d",rc);
|
||||
|
||||
cancel_cpu_boost();
|
||||
}
|
||||
#else /* !USB_ROCKBOX_USB */
|
||||
if (on)
|
||||
{
|
||||
/* until we have native mass-storage mode, we want to reboot on
|
||||
usb host connect */
|
||||
try_reboot();
|
||||
}
|
||||
#endif /* USE_ROCKBOX_USB */
|
||||
}
|
||||
|
||||
void usb_signal_transfer_completion(
|
||||
struct usb_transfer_completion_event_data* event_data)
|
||||
{
|
||||
queue_post(&usb_queue, USB_TRANSFER_COMPLETION, (intptr_t)event_data);
|
||||
}
|
||||
#else /* !HAVE_USBSTACK */
|
||||
/* inline since branch is chosen at compile time */
|
||||
static inline void usb_slave_mode(bool on)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if(on)
|
||||
{
|
||||
DEBUGF("Entering USB slave mode\n");
|
||||
storage_soft_reset();
|
||||
storage_init();
|
||||
storage_enable(false);
|
||||
usb_enable(true);
|
||||
cpu_idle_mode(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGF("Leaving USB slave mode\n");
|
||||
|
||||
cpu_idle_mode(false);
|
||||
|
||||
/* Let the ISDx00 settle */
|
||||
sleep(HZ*1);
|
||||
|
||||
usb_enable(false);
|
||||
|
||||
rc = storage_init();
|
||||
if(rc)
|
||||
panicf("storage: %d",rc);
|
||||
|
||||
rc = disk_mount_all();
|
||||
if (rc <= 0) /* no partition */
|
||||
panicf("mount: %d",rc);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_USBSTACK */
|
||||
|
||||
#ifdef HAVE_USB_POWER
|
||||
static inline bool usb_power_button(void)
|
||||
{
|
||||
#if defined(IRIVER_H10) || defined (IRIVER_H10_5GB)
|
||||
return (button_status() & ~USBPOWER_BTN_IGNORE) != USBPOWER_BUTTON;
|
||||
#else
|
||||
return (button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USB_FIREWIRE_HANDLING
|
||||
static inline bool usb_reboot_button(void)
|
||||
{
|
||||
return (button_status() & ~USBPOWER_BTN_IGNORE) != USBPOWER_BUTTON;
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_USB_POWER */
|
||||
|
||||
static void usb_thread(void)
|
||||
{
|
||||
int num_acks_to_expect = -1;
|
||||
bool waiting_for_ack;
|
||||
int num_acks_to_expect = 0;
|
||||
struct queue_event ev;
|
||||
|
||||
waiting_for_ack = false;
|
||||
|
||||
while(1)
|
||||
{
|
||||
queue_wait(&usb_queue, &ev);
|
||||
|
@ -165,180 +229,116 @@ static void usb_thread(void)
|
|||
#endif
|
||||
#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;
|
||||
usb_core_handle_transfer_completion(
|
||||
(struct usb_transfer_completion_event_data*)ev.data);
|
||||
break;
|
||||
#endif
|
||||
case USB_INSERTED:
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
if(do_screendump_instead_of_usb)
|
||||
{
|
||||
usb_state = USB_SCREENDUMP;
|
||||
screen_dump();
|
||||
break;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_USB_POWER
|
||||
#if defined(IRIVER_H10) || defined (IRIVER_H10_5GB)
|
||||
if((button_status() & ~USBPOWER_BTN_IGNORE) != USBPOWER_BUTTON)
|
||||
#else
|
||||
if((button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON)
|
||||
#endif
|
||||
if (usb_power_button())
|
||||
{
|
||||
/* Only charging is desired */
|
||||
usb_state = USB_POWERED;
|
||||
#ifdef HAVE_USBSTACK
|
||||
usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,false);
|
||||
usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,true);
|
||||
usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, false);
|
||||
usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, true);
|
||||
usb_enable(true);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif /* HAVE_USB_POWER */
|
||||
#ifdef HAVE_USBSTACK
|
||||
/* Set the state to USB_POWERED for now. If permission to connect
|
||||
* by threads and storage is granted it will be changed to
|
||||
* USB_CONNECTED. */
|
||||
usb_state = USB_POWERED;
|
||||
usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, true);
|
||||
usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, false);
|
||||
|
||||
/* Check any drivers enabled at this point for exclusive storage
|
||||
* access requirements. */
|
||||
exclusive_storage_access = usb_core_any_exclusive_storage();
|
||||
|
||||
if (exclusive_storage_access)
|
||||
#endif /* HAVE_USBSTACK */
|
||||
{
|
||||
/* Tell all threads that they have to back off the storage.
|
||||
We subtract one for our own thread. */
|
||||
num_acks_to_expect = queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
|
||||
DEBUGF("USB inserted. Waiting for ack from %d threads...\n",
|
||||
num_acks_for_connect);
|
||||
}
|
||||
break;
|
||||
|
||||
case SYS_USB_CONNECTED_ACK:
|
||||
if(num_acks_to_expect > 0 && --num_acks_to_expect == 0)
|
||||
{
|
||||
DEBUGF("All threads have acknowledged the connect.\n");
|
||||
usb_slave_mode(true);
|
||||
usb_state = USB_INSERTED;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_USBSTACK
|
||||
/* Set the state to USB_POWERED for now. if a real
|
||||
connection is detected it will switch to USB_INSERTED */
|
||||
usb_state = USB_POWERED;
|
||||
usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,true);
|
||||
usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,false);
|
||||
usb_enable(true);
|
||||
#else
|
||||
/* Tell all threads that they have to back off the ATA.
|
||||
We subtract one for our own thread. */
|
||||
num_acks_to_expect =
|
||||
queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
|
||||
waiting_for_ack = true;
|
||||
DEBUGF("USB inserted. Waiting for ack from %d threads...\n",
|
||||
DEBUGF("usb: got ack, %d to go...\n",
|
||||
num_acks_to_expect);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_USBSTACK
|
||||
case USB_REQUEST_DISK:
|
||||
if(!waiting_for_ack)
|
||||
{
|
||||
/* Tell all threads that they have to back off the ATA.
|
||||
We subtract one for our own thread. */
|
||||
num_acks_to_expect =
|
||||
queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
|
||||
waiting_for_ack = true;
|
||||
DEBUGF("USB inserted. Waiting for ack from %d threads...\n",
|
||||
num_acks_to_expect);
|
||||
}
|
||||
break;
|
||||
case USB_RELEASE_DISK:
|
||||
if(!waiting_for_ack)
|
||||
{
|
||||
/* Tell all threads that they have to back off the ATA.
|
||||
We subtract one for our own thread. */
|
||||
num_acks_to_expect =
|
||||
queue_broadcast(SYS_USB_DISCONNECTED, 0) - 1;
|
||||
waiting_for_ack = true;
|
||||
DEBUGF("USB inserted. Waiting for ack from %d threads...\n",
|
||||
num_acks_to_expect);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SYS_USB_CONNECTED_ACK:
|
||||
if(waiting_for_ack)
|
||||
{
|
||||
num_acks_to_expect--;
|
||||
if(num_acks_to_expect == 0)
|
||||
{
|
||||
DEBUGF("All threads have acknowledged the connect.\n");
|
||||
#ifdef HAVE_USBSTACK
|
||||
#ifndef USE_ROCKBOX_USB
|
||||
/* until we have native mass-storage mode, we want to reboot on
|
||||
usb host connect */
|
||||
try_reboot();
|
||||
#endif /* USE_ROCKBOX_USB */
|
||||
#ifdef HAVE_PRIORITY_SCHEDULING
|
||||
thread_set_priority(usb_thread_entry,PRIORITY_REALTIME);
|
||||
#endif
|
||||
exclusive_storage_access = true;
|
||||
|
||||
#else
|
||||
usb_slave_mode(true);
|
||||
cpu_idle_mode(true);
|
||||
#endif
|
||||
usb_state = USB_INSERTED;
|
||||
waiting_for_ack = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGF("usb: got ack, %d to go...\n",
|
||||
num_acks_to_expect);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_EXTRACTED:
|
||||
#ifdef HAVE_USBSTACK
|
||||
usb_enable(false);
|
||||
#ifdef HAVE_PRIORITY_SCHEDULING
|
||||
thread_set_priority(usb_thread_entry,PRIORITY_SYSTEM);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
if(do_screendump_instead_of_usb)
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_USB_POWER
|
||||
if(usb_state == USB_SCREENDUMP)
|
||||
{
|
||||
usb_state = USB_EXTRACTED;
|
||||
break; /* Connected for screendump only */
|
||||
}
|
||||
#endif /* HAVE_LCD_BITMAP */
|
||||
#ifndef HAVE_USBSTACK /* Stack must undo this if POWERED state was transitional */
|
||||
if(usb_state == USB_POWERED)
|
||||
{
|
||||
usb_state = USB_EXTRACTED;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifndef HAVE_USBSTACK
|
||||
#endif /* HAVE_USBSTACK */
|
||||
if(usb_state == USB_INSERTED)
|
||||
{
|
||||
/* Only disable the USB mode if we really have enabled it
|
||||
some threads might not have acknowledged the
|
||||
insertion */
|
||||
usb_slave_mode(false);
|
||||
cpu_idle_mode(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_state = USB_EXTRACTED;
|
||||
#ifdef HAVE_USBSTACK
|
||||
if(exclusive_storage_access)
|
||||
{
|
||||
int rc = disk_mount_all();
|
||||
if (rc <= 0) /* no partition */
|
||||
panicf("mount: %d",rc);
|
||||
exclusive_storage_access = false;
|
||||
#endif
|
||||
/* Tell all threads that we are back in business */
|
||||
num_acks_to_expect =
|
||||
queue_broadcast(SYS_USB_DISCONNECTED, 0) - 1;
|
||||
waiting_for_ack = true;
|
||||
DEBUGF("USB extracted. Waiting for ack from %d threads...\n",
|
||||
num_acks_to_expect);
|
||||
#ifdef HAVE_USBSTACK
|
||||
}
|
||||
#endif
|
||||
if (!exclusive_storage_access)
|
||||
break;
|
||||
|
||||
exclusive_storage_access = false;
|
||||
#endif /* HAVE_USBSTACK */
|
||||
/* Tell all threads that we are back in business */
|
||||
num_acks_to_expect =
|
||||
queue_broadcast(SYS_USB_DISCONNECTED, 0) - 1;
|
||||
DEBUGF("USB extracted. Waiting for ack from %d threads...\n",
|
||||
num_acks_to_expect);
|
||||
break;
|
||||
|
||||
case SYS_USB_DISCONNECTED_ACK:
|
||||
if(waiting_for_ack)
|
||||
if(num_acks_to_expect > 0 && --num_acks_to_expect == 0)
|
||||
{
|
||||
num_acks_to_expect--;
|
||||
if(num_acks_to_expect == 0)
|
||||
{
|
||||
DEBUGF("All threads have acknowledged. "
|
||||
"We're in business.\n");
|
||||
waiting_for_ack = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGF("usb: got ack, %d to go...\n",
|
||||
num_acks_to_expect);
|
||||
}
|
||||
DEBUGF("All threads have acknowledged. "
|
||||
"We're in business.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGF("usb: got ack, %d to go...\n",
|
||||
num_acks_to_expect);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -347,49 +347,44 @@ static void usb_thread(void)
|
|||
case SYS_HOTSWAP_EXTRACTED:
|
||||
#ifdef HAVE_USBSTACK
|
||||
usb_core_hotswap_event(1,ev.id == SYS_HOTSWAP_INSERTED);
|
||||
#else
|
||||
#else /* !HAVE_USBSTACK */
|
||||
if(usb_state == USB_INSERTED)
|
||||
{
|
||||
usb_enable(false);
|
||||
#if (CONFIG_STORAGE & STORAGE_MMC)
|
||||
usb_mmc_countdown = HZ/2; /* re-enable after 0.5 sec */
|
||||
#endif
|
||||
#endif /* STORAGE_MMC */
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_USBSTACK */
|
||||
break;
|
||||
|
||||
#if (CONFIG_STORAGE & STORAGE_MMC)
|
||||
case USB_REENABLE:
|
||||
if(usb_state == USB_INSERTED)
|
||||
usb_enable(true); /* reenable only if still inserted */
|
||||
break;
|
||||
#endif /* STORAGE_MMC */
|
||||
#endif /* HAVE_HOTSWAP */
|
||||
|
||||
#ifdef USB_FIREWIRE_HANDLING
|
||||
case USB_REQUEST_REBOOT:
|
||||
#ifdef HAVE_USB_POWER
|
||||
if((button_status() & ~USBPOWER_BTN_IGNORE) != USBPOWER_BUTTON)
|
||||
if (usb_reboot_button())
|
||||
#endif
|
||||
try_reboot();
|
||||
break;
|
||||
#endif /* USB_FIREWIRE_HANDLING */
|
||||
}
|
||||
}
|
||||
}
|
||||
#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
|
||||
|
||||
#ifdef USB_FULL_INIT
|
||||
static void usb_tick(void)
|
||||
{
|
||||
int current_status;
|
||||
|
||||
if(usb_monitor_enabled)
|
||||
{
|
||||
#if defined(IPOD_COLOR) || defined(IPOD_4G) \
|
||||
|| defined(IPOD_MINI) || defined(IPOD_MINI2G)
|
||||
#ifdef USB_FIREWIRE_HANDLING
|
||||
int current_firewire_status = firewire_detect();
|
||||
if(current_firewire_status != last_firewire_status)
|
||||
{
|
||||
|
@ -409,7 +404,7 @@ static void usb_tick(void)
|
|||
queue_post(&usb_queue, USB_REQUEST_REBOOT, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* USB_FIREWIRE_HANDLING */
|
||||
|
||||
current_status = usb_detect();
|
||||
|
||||
|
@ -442,7 +437,7 @@ static void usb_tick(void)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif /* USB_FULL_INIT */
|
||||
|
||||
void usb_acknowledge(long id)
|
||||
{
|
||||
|
@ -458,8 +453,7 @@ void usb_init(void)
|
|||
usb_monitor_enabled = false;
|
||||
countdown = -1;
|
||||
|
||||
#if defined(IPOD_COLOR) || defined(IPOD_4G) \
|
||||
|| defined(IPOD_MINI) || defined(IPOD_MINI2G)
|
||||
#ifdef USB_FIREWIRE_HANDLING
|
||||
firewire_countdown = -1;
|
||||
last_firewire_status = false;
|
||||
#endif
|
||||
|
@ -480,8 +474,7 @@ void usb_init(void)
|
|||
IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU));
|
||||
|
||||
tick_add_task(usb_tick);
|
||||
#endif
|
||||
|
||||
#endif /* USB_FULL_INIT */
|
||||
}
|
||||
|
||||
void usb_wait_for_disconnect(struct event_queue *q)
|
||||
|
@ -518,10 +511,8 @@ int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks)
|
|||
case SYS_USB_DISCONNECTED:
|
||||
usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
|
||||
return 0;
|
||||
break;
|
||||
case SYS_TIMEOUT:
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -562,27 +553,7 @@ bool usb_inserted(void)
|
|||
}
|
||||
|
||||
#ifdef HAVE_USBSTACK
|
||||
void usb_request_exclusive_ata(void)
|
||||
{
|
||||
/* This is not really a clean place to start boosting the cpu. but it's
|
||||
* currently the best one. We want to get rid of having to boost the cpu
|
||||
* for usb anyway */
|
||||
trigger_cpu_boost();
|
||||
if(!exclusive_storage_access) {
|
||||
queue_post(&usb_queue, USB_REQUEST_DISK, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_release_exclusive_ata(void)
|
||||
{
|
||||
cancel_cpu_boost();
|
||||
if(exclusive_storage_access) {
|
||||
queue_post(&usb_queue, USB_RELEASE_DISK, 0);
|
||||
exclusive_storage_access = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_exclusive_ata(void)
|
||||
bool usb_exclusive_storage(void)
|
||||
{
|
||||
return exclusive_storage_access;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id: $
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2008 by Frank Gevaerts
|
||||
*
|
||||
|
|
|
@ -33,7 +33,7 @@ struct usb_class_driver {
|
|||
/* Driver api starts here */
|
||||
|
||||
/* Set this to true if the driver needs exclusive disk access (e.g. usb storage) */
|
||||
bool needs_exclusive_ata;
|
||||
bool needs_exclusive_storage;
|
||||
|
||||
/* Let the driver request endpoints it need. Returns zero on success */
|
||||
int (*request_endpoints)(struct usb_class_driver *);
|
||||
|
|
|
@ -54,6 +54,9 @@
|
|||
#include "ata.h"
|
||||
#endif
|
||||
|
||||
#ifndef USB_MAX_CURRENT
|
||||
#define USB_MAX_CURRENT 500
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/* USB protocol descriptors: */
|
||||
|
@ -94,7 +97,7 @@ static struct usb_config_descriptor __attribute__((aligned(2)))
|
|||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
|
||||
.bMaxPower = 250, /* 500mA in 2mA units */
|
||||
.bMaxPower = (USB_MAX_CURRENT+1) / 2, /* In 2mA units */
|
||||
};
|
||||
|
||||
|
||||
|
@ -179,7 +182,7 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
|
|||
#ifdef USB_STORAGE
|
||||
[USB_DRIVER_MASS_STORAGE] = {
|
||||
.enabled = false,
|
||||
.needs_exclusive_ata = true,
|
||||
.needs_exclusive_storage = true,
|
||||
.first_interface = 0,
|
||||
.last_interface = 0,
|
||||
.request_endpoints = usb_storage_request_endpoints,
|
||||
|
@ -198,7 +201,7 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
|
|||
#ifdef USB_SERIAL
|
||||
[USB_DRIVER_SERIAL] = {
|
||||
.enabled = false,
|
||||
.needs_exclusive_ata = false,
|
||||
.needs_exclusive_storage = false,
|
||||
.first_interface = 0,
|
||||
.last_interface = 0,
|
||||
.request_endpoints = usb_serial_request_endpoints,
|
||||
|
@ -217,7 +220,7 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
|
|||
#ifdef USB_CHARGING_ONLY
|
||||
[USB_DRIVER_CHARGING_ONLY] = {
|
||||
.enabled = false,
|
||||
.needs_exclusive_ata = false,
|
||||
.needs_exclusive_storage = false,
|
||||
.first_interface = 0,
|
||||
.last_interface = 0,
|
||||
.request_endpoints = usb_charging_only_request_endpoints,
|
||||
|
@ -353,13 +356,17 @@ void usb_core_exit(void)
|
|||
int i;
|
||||
for(i=0;i<USB_NUM_DRIVERS;i++) {
|
||||
if(drivers[i].enabled && drivers[i].disconnect != NULL)
|
||||
{
|
||||
drivers[i].disconnect ();
|
||||
drivers[i].enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (initialized) {
|
||||
usb_drv_exit();
|
||||
}
|
||||
initialized = false;
|
||||
usb_state = DEFAULT;
|
||||
logf("usb_core_exit() finished");
|
||||
}
|
||||
|
||||
|
@ -392,6 +399,20 @@ bool usb_core_driver_enabled(int driver)
|
|||
return drivers[driver].enabled;
|
||||
}
|
||||
|
||||
bool usb_core_any_exclusive_storage(void)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<USB_NUM_DRIVERS;i++) {
|
||||
if(drivers[i].enabled &&
|
||||
drivers[i].needs_exclusive_storage)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_HOTSWAP
|
||||
void usb_core_hotswap_event(int volume,bool inserted)
|
||||
{
|
||||
|
@ -484,14 +505,6 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
|
|||
usb_core_set_serial_function_id();
|
||||
|
||||
allocate_interfaces_and_endpoints();
|
||||
|
||||
for(i=0;i<USB_NUM_DRIVERS;i++) {
|
||||
if(drivers[i].enabled &&
|
||||
drivers[i].needs_exclusive_ata) {
|
||||
usb_request_exclusive_ata();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(req->bRequestType & 0x1f) {
|
||||
|
@ -788,7 +801,7 @@ unsigned short usb_allowed_current()
|
|||
{
|
||||
if (usb_state == CONFIGURED)
|
||||
{
|
||||
return 500;
|
||||
return MAX(USB_MAX_CURRENT, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -293,6 +293,7 @@ static bool check_disk_present(IF_MV_NONVOID(int volume))
|
|||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void try_release_ata(void)
|
||||
{
|
||||
/* Check if there is a connected drive left. If not,
|
||||
|
@ -310,6 +311,7 @@ static void try_release_ata(void)
|
|||
usb_release_exclusive_ata();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HOTSWAP
|
||||
void usb_storage_notify_hotswap(int volume,bool inserted)
|
||||
|
@ -320,9 +322,7 @@ void usb_storage_notify_hotswap(int volume,bool inserted)
|
|||
}
|
||||
else {
|
||||
ejected[volume] = true;
|
||||
try_release_ata();
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -334,7 +334,6 @@ void usb_storage_reconnect(void)
|
|||
for(i=0;i<NUM_VOLUMES;i++)
|
||||
ejected[i] = !check_disk_present(IF_MV(i));
|
||||
logf("%s", __func__);
|
||||
usb_request_exclusive_ata();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -682,7 +681,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
|
|||
#ifdef HAVE_HOTSWAP
|
||||
if(storage_removable(lun) && !storage_present(lun)) {
|
||||
ejected[lun] = true;
|
||||
try_release_ata();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -699,7 +697,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
|
|||
switch (cbw->command_block[0]) {
|
||||
case SCSI_TEST_UNIT_READY:
|
||||
logf("scsi test_unit_ready %d",lun);
|
||||
if(!usb_exclusive_ata()) {
|
||||
if(!usb_exclusive_storage()) {
|
||||
send_csw(UMS_STATUS_FAIL);
|
||||
cur_sense_data.sense_key=SENSE_NOT_READY;
|
||||
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
|
||||
|
@ -885,7 +883,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
|
|||
{
|
||||
logf("scsi eject");
|
||||
ejected[lun]=true;
|
||||
try_release_ata();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue