summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2008-03-02 00:15:02 +0000
committerFrank Gevaerts <frank@gevaerts.be>2008-03-02 00:15:02 +0000
commitf18d20ee36f8a23e0f37fd342cf186e3b6a91408 (patch)
treed5917d19491bc5fa80c61ea440279c4ed168c91f
parent5f1e1a5e5efd9051c9aeda5a8cd671e523bac6e9 (diff)
downloadrockbox-f18d20ee36f8a23e0f37fd342cf186e3b6a91408.zip
rockbox-f18d20ee36f8a23e0f37fd342cf186e3b6a91408.tar.gz
rockbox-f18d20ee36f8a23e0f37fd342cf186e3b6a91408.tar.bz2
rockbox-f18d20ee36f8a23e0f37fd342cf186e3b6a91408.tar.xz
Only show the usb screen once a real usb connection is established. In case other threads are slow in acknowledging the SYS_USB_CONNECTED message, tell the OS that the disk is not ready yet (the OS interprets this as "spinning up")
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16471 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/usb.h3
-rw-r--r--firmware/usb.c59
-rw-r--r--firmware/usbstack/usb_core.c4
-rw-r--r--firmware/usbstack/usb_storage.c42
4 files changed, 92 insertions, 16 deletions
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index 4bfbfd4..833d2ab 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -29,6 +29,7 @@ enum {
USB_REENABLE,
USB_POWERED,
USB_TRANSFER_COMPLETION,
+ USB_REQUEST_DISK,
USB_REQUEST_REBOOT
};
@@ -102,6 +103,8 @@ 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);
#endif
#if defined(IPOD_COLOR) || defined(IPOD_4G) \
diff --git a/firmware/usb.c b/firmware/usb.c
index 07d2c58..d9c13df 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -73,6 +73,7 @@ static struct thread_entry *usb_thread_entry;
static struct event_queue usb_queue;
static int last_usb_status;
static bool usb_monitor_enabled;
+static bool exclusive_disk;
#if defined(IPOD_COLOR) || defined(IPOD_4G) \
@@ -197,6 +198,16 @@ static void usb_thread(void)
else
#endif
{
+#ifdef HAVE_USBSTACK
+#ifdef USE_ROCKBOX_USB
+ 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_request_exclusive_ata();
+#endif /* USE_ROCKBOX_USB */
+#else
/* Tell all threads that they have to back off the ATA.
We subtract one for our own thread. */
num_acks_to_expect =
@@ -204,9 +215,23 @@ static void usb_thread(void)
waiting_for_ack = true;
DEBUGF("USB inserted. Waiting for ack from %d threads...\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;
+#endif
case SYS_USB_CONNECTED_ACK:
if(waiting_for_ack)
{
@@ -215,25 +240,22 @@ static void usb_thread(void)
{
DEBUGF("All threads have acknowledged the connect.\n");
#ifdef HAVE_USBSTACK
-#ifdef HAVE_PRIORITY_SCHEDULING
- thread_set_priority(usb_thread_entry,PRIORITY_REALTIME);
-#endif
-#ifdef USE_ROCKBOX_USB
- 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 /* USE_ROCKBOX_USB */
+#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);
+ exclusive_disk = true;
+#endif
#else
usb_slave_mode(true);
cpu_idle_mode(true);
#endif
usb_state = USB_INSERTED;
+ waiting_for_ack = false;
}
else
{
@@ -246,6 +268,7 @@ static void usb_thread(void)
case USB_EXTRACTED:
#ifdef HAVE_USBSTACK
usb_enable(false);
+ exclusive_disk = false;
#ifdef HAVE_PRIORITY_SCHEDULING
thread_set_priority(usb_thread_entry,PRIORITY_SYSTEM);
#endif
@@ -290,6 +313,7 @@ static void usb_thread(void)
{
DEBUGF("All threads have acknowledged. "
"We're in business.\n");
+ waiting_for_ack = false;
}
else
{
@@ -403,6 +427,7 @@ void usb_acknowledge(long id)
void usb_init(void)
{
usb_state = USB_EXTRACTED;
+ exclusive_disk = false;
usb_monitor_enabled = false;
countdown = -1;
@@ -481,6 +506,20 @@ bool usb_inserted(void)
#endif
}
+#ifdef HAVE_USBSTACK
+void usb_request_exclusive_ata(void)
+{
+ if(!exclusive_disk) {
+ queue_post(&usb_queue, USB_REQUEST_DISK, 0);
+ }
+}
+
+bool usb_exclusive_ata(void)
+{
+ return exclusive_disk;
+}
+#endif
+
#ifdef HAVE_USB_POWER
bool usb_powered(void)
{
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index aa0f06e..f40d76b 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -460,6 +460,10 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
{
if(usb_state == DEFAULT) {
set_serial_descriptor();
+#ifdef USB_STORAGE
+ if(usb_core_storage_enabled)
+ usb_request_exclusive_ata();
+#endif
}
#ifdef USB_BENCHMARK
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 73464cf..bde774e 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -80,6 +80,8 @@
#define ASC_LBA_OUT_OF_RANGE 0x21
#define ASC_WRITE_ERROR 0x0C
#define ASC_READ_ERROR 0x11
+#define ASC_NOT_READY 0x04
+#define ASCQ_BECOMING_READY 0x01
#define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000
@@ -207,6 +209,7 @@ static struct {
unsigned char sense_key;
unsigned char information;
unsigned char asc;
+ unsigned char ascq;
} cur_sense_data;
static void handle_scsi(struct command_block_wrapper* cbw);
@@ -228,10 +231,6 @@ static enum {
/* called by usb_code_init() */
void usb_storage_init(void)
{
- size_t bufsize;
- unsigned char * audio_buffer = audio_get_buffer(false,&bufsize);
- /* TODO : check if bufsize is at least 32K ? */
- tb.transfer_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer + 31) & 0xffffffe0);
logf("usb_storage_init done");
}
@@ -270,6 +269,7 @@ void usb_storage_transfer_complete(bool in,int status,int length)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_MEDIUM_ERROR;
cur_sense_data.asc=ASC_WRITE_ERROR;
+ cur_sense_data.ascq=0;
break;
}
@@ -291,6 +291,7 @@ void usb_storage_transfer_complete(bool in,int status,int length)
cur_sense_data.sense_key=0;
cur_sense_data.information=0;
cur_sense_data.asc=0;
+ cur_sense_data.ascq=0;
}
break;
case WAITING_FOR_COMMAND:
@@ -329,6 +330,7 @@ void usb_storage_transfer_complete(bool in,int status,int length)
cur_sense_data.sense_key=0;
cur_sense_data.information=0;
cur_sense_data.asc=0;
+ cur_sense_data.ascq=0;
}
break;
case SENDING_BLOCKS:
@@ -351,6 +353,7 @@ void usb_storage_transfer_complete(bool in,int status,int length)
cur_sense_data.sense_key=0;
cur_sense_data.information=0;
cur_sense_data.asc=0;
+ cur_sense_data.ascq=0;
}
break;
}
@@ -390,13 +393,20 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req)
handled = true;
break;
- case USB_REQ_SET_CONFIGURATION:
+ case USB_REQ_SET_CONFIGURATION: {
+ size_t bufsize;
+ unsigned char * audio_buffer;
logf("ums: set config");
/* prime rx endpoint. We only need room for commands */
state = WAITING_FOR_COMMAND;
+
+ /* TODO : check if bufsize is at least 32K ? */
+ audio_buffer = audio_get_buffer(false,&bufsize);
+ tb.transfer_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer + 31) & 0xffffffe0);
usb_drv_recv(EP_MASS_STORAGE, tb.transfer_buffer, 1024);
handled = true;
break;
+ }
}
return handled;
@@ -409,6 +419,7 @@ static void send_and_read_next(void)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_MEDIUM_ERROR;
cur_sense_data.asc=ASC_READ_ERROR;
+ cur_sense_data.ascq=0;
return;
}
send_block_data(current_cmd.data[current_cmd.data_select],
@@ -472,6 +483,13 @@ 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()) {
+ send_csw(UMS_STATUS_FAIL);
+ cur_sense_data.sense_key=SENSE_NOT_READY;
+ cur_sense_data.asc=ASC_NOT_READY;
+ cur_sense_data.ascq=ASCQ_BECOMING_READY;
+ break;
+ }
if(lun_present) {
send_csw(UMS_STATUS_GOOD);
}
@@ -479,6 +497,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
+ cur_sense_data.ascq=0;
}
break;
@@ -516,7 +535,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
tb.sense_data->AdditionalSenseLength=10;
tb.sense_data->CommandSpecificInformation=0;
tb.sense_data->AdditionalSenseCode=cur_sense_data.asc;
- tb.sense_data->AdditionalSenseCodeQualifier=0;
+ tb.sense_data->AdditionalSenseCodeQualifier=cur_sense_data.ascq;
tb.sense_data->FieldReplaceableUnitCode=0;
tb.sense_data->SKSV=0;
tb.sense_data->SenseKeySpecific=0;
@@ -531,6 +550,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
+ cur_sense_data.ascq=0;
break;
}
/*unsigned char pc = (cbw->command_block[2] & 0xc0) >>6;*/
@@ -563,6 +583,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST;
cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD;
+ cur_sense_data.ascq=0;
break;
}
break;
@@ -573,6 +594,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
+ cur_sense_data.ascq=0;
break;
}
/*unsigned char pc = (cbw->command_block[2] & 0xc0) >>6;*/
@@ -608,6 +630,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST;
cur_sense_data.asc=ASC_INVALID_FIELD_IN_CBD;
+ cur_sense_data.ascq=0;
break;
}
break;
@@ -641,6 +664,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
+ cur_sense_data.ascq=0;
}
break;
}
@@ -660,6 +684,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
+ cur_sense_data.ascq=0;
}
break;
}
@@ -671,6 +696,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
+ cur_sense_data.ascq=0;
break;
}
current_cmd.data[0] = tb.transfer_buffer;
@@ -692,6 +718,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST;
cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE;
+ cur_sense_data.ascq=0;
}
else {
current_cmd.last_result = ata_read_sectors(IF_MV2(current_cmd.lun,) current_cmd.sector,
@@ -708,6 +735,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_NOT_READY;
cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
+ cur_sense_data.ascq=0;
break;
}
current_cmd.data[0] = tb.transfer_buffer;
@@ -727,6 +755,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
send_csw(UMS_STATUS_FAIL);
cur_sense_data.sense_key=SENSE_ILLEGAL_REQUEST;
cur_sense_data.asc=ASC_LBA_OUT_OF_RANGE;
+ cur_sense_data.ascq=0;
}
else {
receive_block_data(current_cmd.data[0],
@@ -776,6 +805,7 @@ static void send_csw(int status)
cur_sense_data.sense_key=0;
cur_sense_data.information=0;
cur_sense_data.asc=0;
+ cur_sense_data.ascq=0;
}
}