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:
Michael Sevakis 2009-01-13 16:27:35 +00:00
parent 30414d56c9
commit 6da8b4eb49
9 changed files with 267 additions and 267 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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(

View File

@ -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;
}

View File

@ -5,7 +5,7 @@
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: $
* $Id$
*
* Copyright (C) 2008 by Frank Gevaerts
*

View File

@ -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 *);

View File

@ -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
{

View File

@ -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();
}
}
}