summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/screens.c45
-rw-r--r--firmware/export/usb.h1
-rw-r--r--firmware/usbstack/usb_storage.c21
3 files changed, 54 insertions, 13 deletions
diff --git a/apps/screens.c b/apps/screens.c
index c327e65037..e1e1c37bf5 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -91,6 +91,42 @@ static int clamp_value_wrap(int value, int max, int min)
91} 91}
92#endif 92#endif
93 93
94int handle_usb_events(struct event_queue *q)
95{
96 struct queue_event ev;
97 int next_update=0;
98
99 /* Don't return until we get SYS_USB_DISCONNECTED or SYS_TIMEOUT */
100 while(1)
101 {
102 queue_wait_w_tmo(q, &ev, HZ/4);
103 switch(ev.id)
104 {
105 case SYS_USB_DISCONNECTED:
106 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
107 return 0;
108 case SYS_TIMEOUT:
109 break;
110 }
111#if defined(HAVE_USBSTACK) && defined(USE_ROCKBOX_USB)
112 if((button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON)
113 {
114 usb_storage_try_release_storage();
115 }
116#endif
117 if(TIME_AFTER(current_tick,next_update))
118 {
119 if(usb_inserted()) {
120#if (CONFIG_STORAGE & STORAGE_MMC) /* USB-MMC bridge can report activity */
121 led(mmc_usb_active(HZ));
122#endif /* STORAGE_MMC */
123 gui_syncstatusbar_draw(&statusbars, false);
124 }
125 next_update=current_tick+HZ/2;
126 }
127 }
128}
129
94void usb_screen(void) 130void usb_screen(void)
95{ 131{
96#ifdef USB_NONE 132#ifdef USB_NONE
@@ -142,14 +178,7 @@ void usb_screen(void)
142 while (button_get(true) & BUTTON_REL); 178 while (button_get(true) & BUTTON_REL);
143#else 179#else
144 usb_acknowledge(SYS_USB_CONNECTED_ACK); 180 usb_acknowledge(SYS_USB_CONNECTED_ACK);
145 while(usb_wait_for_disconnect_w_tmo(&button_queue, HZ)) { 181 while(handle_usb_events(&button_queue));
146 if(usb_inserted()) {
147#if (CONFIG_STORAGE & STORAGE_MMC) /* USB-MMC bridge can report activity */
148 led(mmc_usb_active(HZ));
149#endif /* STORAGE_MMC */
150 gui_syncstatusbar_draw(&statusbars, false);
151 }
152 }
153#endif /* SIMULATOR */ 182#endif /* SIMULATOR */
154#ifdef HAVE_LCD_CHARCELLS 183#ifdef HAVE_LCD_CHARCELLS
155 status_set_usb(false); 184 status_set_usb(false);
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);