diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/export/usb.h | 1 | ||||
-rw-r--r-- | firmware/usbstack/usb_storage.c | 21 |
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); | |||
131 | void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data); | 131 | void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data); |
132 | bool usb_driver_enabled(int driver); | 132 | bool usb_driver_enabled(int driver); |
133 | bool usb_exclusive_storage(void); /* storage is available for usb */ | 133 | bool usb_exclusive_storage(void); /* storage is available for usb */ |
134 | void usb_storage_try_release_storage(void); | ||
134 | #endif | 135 | #endif |
135 | int usb_release_exclusive_storage(void); | 136 | int 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); | |||
260 | static void fill_inquiry(IF_MV_NONVOID(int lun)); | 260 | static void fill_inquiry(IF_MV_NONVOID(int lun)); |
261 | static void send_and_read_next(void); | 261 | static void send_and_read_next(void); |
262 | static bool ejected[NUM_VOLUMES]; | 262 | static bool ejected[NUM_VOLUMES]; |
263 | static bool locked[NUM_VOLUMES]; | ||
263 | 264 | ||
264 | static int usb_interface; | 265 | static int usb_interface; |
265 | static int ep_in, ep_out; | 266 | static 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 | ||
307 | static void try_release_ata(void) | 308 | void 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); |