summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/usb.h1
-rw-r--r--firmware/usbstack/usb_storage.c21
2 files changed, 17 insertions, 5 deletions
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index ecbec3a914..be36ee0b31 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -131,6 +131,7 @@ bool usb_charging_enabled(void);
131void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data); 131void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data);
132bool usb_driver_enabled(int driver); 132bool usb_driver_enabled(int driver);
133bool usb_exclusive_storage(void); /* storage is available for usb */ 133bool usb_exclusive_storage(void); /* storage is available for usb */
134void usb_storage_try_release_storage(void);
134#endif 135#endif
135int usb_release_exclusive_storage(void); 136int usb_release_exclusive_storage(void);
136 137
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 9b0625e4e2..aa8cb29da3 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -260,6 +260,7 @@ static void receive_block_data(void *data,int size);
260static void fill_inquiry(IF_MV_NONVOID(int lun)); 260static void fill_inquiry(IF_MV_NONVOID(int lun));
261static void send_and_read_next(void); 261static void send_and_read_next(void);
262static bool ejected[NUM_VOLUMES]; 262static bool ejected[NUM_VOLUMES];
263static bool locked[NUM_VOLUMES];
263 264
264static int usb_interface; 265static int usb_interface;
265static int ep_in, ep_out; 266static int ep_in, ep_out;
@@ -304,14 +305,14 @@ static bool check_disk_present(IF_MV_NONVOID(int volume))
304#endif 305#endif
305} 306}
306 307
307static void try_release_ata(void) 308void usb_storage_try_release_storage(void)
308{ 309{
309 /* Check if there is a connected drive left. If not, 310 /* Check if there is a connected drive left. If not,
310 release excusive access */ 311 release excusive access */
311 bool canrelease=true; 312 bool canrelease=true;
312 int i; 313 int i;
313 for(i=0;i<NUM_VOLUMES;i++) { 314 for(i=0;i<NUM_VOLUMES;i++) {
314 if(ejected[i]==false){ 315 if(ejected[i]==false && locked[i]==true){
315 canrelease=false; 316 canrelease=false;
316 break; 317 break;
317 } 318 }
@@ -331,7 +332,9 @@ void usb_storage_notify_hotswap(int volume,bool inserted)
331 } 332 }
332 else { 333 else {
333 ejected[volume] = true; 334 ejected[volume] = true;
334 try_release_ata(); 335 /* If this happens while the device is locked, weird things may happen.
336 At least try to keep our state consistent */
337 locked[volume]=false;
335 } 338 }
336} 339}
337#endif 340#endif
@@ -419,6 +422,14 @@ void usb_storage_init_connection(void)
419 422
420 int i; 423 int i;
421 for(i=0;i<NUM_VOLUMES;i++) { 424 for(i=0;i<NUM_VOLUMES;i++) {
425#ifdef TOSHIBA_GIGABEAT_S
426 /* As long as the Gigabeat S is a non-removable device, we need
427 to mark the device as locked to avoid usb_storage_try_release_ata()
428 to leave MSC mode while the device is in use */
429 locked[i] = true;
430#else
431 locked[i] = false;
432#endif
422 ejected[i] = !check_disk_present(IF_MV(i)); 433 ejected[i] = !check_disk_present(IF_MV(i));
423 queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0); 434 queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0);
424 } 435 }
@@ -685,7 +696,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
685#ifdef HAVE_HOTSWAP 696#ifdef HAVE_HOTSWAP
686 if(storage_removable(lun) && !storage_present(lun)) { 697 if(storage_removable(lun) && !storage_present(lun)) {
687 ejected[lun] = true; 698 ejected[lun] = true;
688 try_release_ata();
689 } 699 }
690#endif 700#endif
691 701
@@ -889,7 +899,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
889 { 899 {
890 logf("scsi eject"); 900 logf("scsi eject");
891 ejected[lun]=true; 901 ejected[lun]=true;
892 try_release_ata();
893 } 902 }
894 } 903 }
895 } 904 }
@@ -900,10 +909,12 @@ static void handle_scsi(struct command_block_wrapper* cbw)
900 logf("scsi allow_medium_removal %d",lun); 909 logf("scsi allow_medium_removal %d",lun);
901 if((cbw->command_block[4] & 0x03) == 0) 910 if((cbw->command_block[4] & 0x03) == 0)
902 { 911 {
912 locked[lun]=false;
903 queue_broadcast(SYS_USB_LUN_LOCKED, (lun<<16)+0); 913 queue_broadcast(SYS_USB_LUN_LOCKED, (lun<<16)+0);
904 } 914 }
905 else 915 else
906 { 916 {
917 locked[lun]=true;
907 queue_broadcast(SYS_USB_LUN_LOCKED, (lun<<16)+1); 918 queue_broadcast(SYS_USB_LUN_LOCKED, (lun<<16)+1);
908 } 919 }
909 send_csw(UMS_STATUS_GOOD); 920 send_csw(UMS_STATUS_GOOD);