summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2009-03-08 18:45:19 +0000
committerFrank Gevaerts <frank@gevaerts.be>2009-03-08 18:45:19 +0000
commit871db6f5d997e9fffe4fe951e708e42ac77cc181 (patch)
tree4daacd7068637d12c4c43726a235567f96104bda
parent30a2713b6eef28194d9feb4e9758624f821936ff (diff)
downloadrockbox-871db6f5d997e9fffe4fe951e708e42ac77cc181.tar.gz
rockbox-871db6f5d997e9fffe4fe951e708e42ac77cc181.zip
Allow the user to leave MSC mode by pressing the USB POWER button (the one that's used to go to usb power mode on plugin) when the host OS hasn't locked the device.
This only works for devices that expose a removable device, so for now the gigabeat S is out of luck. (slightly modified from FS#9993) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20244 a1c6a512-1295-4272-9138-f99709370657
-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);