summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2009-01-13 16:27:35 +0000
committerMichael Sevakis <jethead71@rockbox.org>2009-01-13 16:27:35 +0000
commit6da8b4eb4925f167588c868a64d2d057ca3bf85f (patch)
tree1441169e97f7ece3422a49e51dc512c8be0b31ae
parent30414d56c9f8b4fc35ac2918c4d22e5e2ded0eb6 (diff)
downloadrockbox-6da8b4eb4925f167588c868a64d2d057ca3bf85f.tar.gz
rockbox-6da8b4eb4925f167588c868a64d2d057ca3bf85f.zip
USB retweaking: Take out the USB_REQUEST/RELEASE_DISK scheme and simply ask the USB core whether or not any drivers require exclusive access at the moment of connect. Doing anthing else just produces nasty effects on Windows because it expects some communication just for enabling the PHY and not allowing it to mount volumes if a thread doesn't ack causes annoying error message boxes. Make behavior of each USB type identical from the system perspective. Some miscellaneous changes (simplify, ata->storage naming, define only used USB_* enums values were possible).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19762 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/debug_menu.c4
-rw-r--r--firmware/drivers/ata.c35
-rw-r--r--firmware/export/usb.h40
-rw-r--r--firmware/export/usb_core.h2
-rw-r--r--firmware/usb.c357
-rw-r--r--firmware/usbstack/usb_charging_only.h2
-rw-r--r--firmware/usbstack/usb_class_driver.h2
-rw-r--r--firmware/usbstack/usb_core.c39
-rw-r--r--firmware/usbstack/usb_storage.c9
9 files changed, 245 insertions, 245 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 7477bb001c..d3022df78e 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -2575,7 +2575,7 @@ static bool logf_usb_serial(void)
2575} 2575}
2576#endif 2576#endif
2577 2577
2578#if defined(HAVE_USBSTACK) && defined(USB_STORAGE) 2578#if 0 && defined(HAVE_USBSTACK) && defined(USB_STORAGE)
2579static bool usb_reconnect(void) 2579static bool usb_reconnect(void)
2580{ 2580{
2581 splash(HZ, "Reconnect mass storage"); 2581 splash(HZ, "Reconnect mass storage");
@@ -2720,7 +2720,7 @@ static const struct the_menu_item menuitems[] = {
2720#if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) && defined(USB_SERIAL) 2720#if defined(HAVE_USBSTACK) && defined(ROCKBOX_HAS_LOGF) && defined(USB_SERIAL)
2721 {"logf over usb",logf_usb_serial }, 2721 {"logf over usb",logf_usb_serial },
2722#endif 2722#endif
2723#if defined(HAVE_USBSTACK) && defined(USB_STORAGE) 2723#if 0 && defined(HAVE_USBSTACK) && defined(USB_STORAGE)
2724 {"reconnect usb storage",usb_reconnect}, 2724 {"reconnect usb storage",usb_reconnect},
2725#endif 2725#endif
2726#ifdef CPU_BOOST_LOGGING 2726#ifdef CPU_BOOST_LOGGING
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index edef507e0d..5f5829736f 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -61,8 +61,9 @@
61#define CMD_SET_FEATURES 0xEF 61#define CMD_SET_FEATURES 0xEF
62#define CMD_SECURITY_FREEZE_LOCK 0xF5 62#define CMD_SECURITY_FREEZE_LOCK 0xF5
63 63
64#define Q_SLEEP 0 64/* Should all be < 0x100 (which are reserved for control messages) */
65#define Q_CLOSE 1 65#define Q_SLEEP 0
66#define Q_CLOSE 1
66 67
67#define READ_TIMEOUT 5*HZ 68#define READ_TIMEOUT 5*HZ
68 69
@@ -143,7 +144,7 @@ static void ata_lock_unlock(struct ata_lock *l)
143#define mutex_unlock ata_lock_unlock 144#define mutex_unlock ata_lock_unlock
144#endif /* MAX_PHYS_SECTOR_SIZE */ 145#endif /* MAX_PHYS_SECTOR_SIZE */
145 146
146#if defined(HAVE_USBSTACK) && defined(USE_ROCKBOX_USB) && !defined(BOOTLOADER) 147#if defined(HAVE_USBSTACK) && defined(USE_ROCKBOX_USB)
147#define ALLOW_USB_SPINDOWN 148#define ALLOW_USB_SPINDOWN
148#endif 149#endif
149 150
@@ -164,7 +165,7 @@ static bool lba48 = false; /* set for 48 bit addressing */
164#endif 165#endif
165static long ata_stack[(DEFAULT_STACK_SIZE*3)/sizeof(long)]; 166static long ata_stack[(DEFAULT_STACK_SIZE*3)/sizeof(long)];
166static const char ata_thread_name[] = "ata"; 167static const char ata_thread_name[] = "ata";
167static struct event_queue ata_queue; 168static struct event_queue ata_queue SHAREDBSS_ATTR;
168static bool initialized = false; 169static bool initialized = false;
169 170
170static long last_user_activity = -1; 171static long last_user_activity = -1;
@@ -910,7 +911,9 @@ static void ata_thread(void)
910#ifdef ALLOW_USB_SPINDOWN 911#ifdef ALLOW_USB_SPINDOWN
911 if(!usb_mode) 912 if(!usb_mode)
912#endif 913#endif
914 {
913 call_storage_idle_notifys(false); 915 call_storage_idle_notifys(false);
916 }
914 last_seen_mtx_unlock = 0; 917 last_seen_mtx_unlock = 0;
915 } 918 }
916 } 919 }
@@ -923,7 +926,9 @@ static void ata_thread(void)
923#ifdef ALLOW_USB_SPINDOWN 926#ifdef ALLOW_USB_SPINDOWN
924 if(!usb_mode) 927 if(!usb_mode)
925#endif 928#endif
929 {
926 call_storage_idle_notifys(true); 930 call_storage_idle_notifys(true);
931 }
927 ata_perform_sleep(); 932 ata_perform_sleep();
928 last_sleep = current_tick; 933 last_sleep = current_tick;
929 } 934 }
@@ -935,14 +940,21 @@ static void ata_thread(void)
935 { 940 {
936 mutex_lock(&ata_mtx); 941 mutex_lock(&ata_mtx);
937 ide_power_enable(false); 942 ide_power_enable(false);
938 mutex_unlock(&ata_mtx);
939 poweroff = true; 943 poweroff = true;
944 mutex_unlock(&ata_mtx);
940 } 945 }
941#endif 946#endif
942 break; 947 break;
943 948
944#ifndef USB_NONE 949#ifndef USB_NONE
945 case SYS_USB_CONNECTED: 950 case SYS_USB_CONNECTED:
951 /* Tell the USB thread that we are safe */
952 DEBUGF("ata_thread got SYS_USB_CONNECTED\n");
953#ifdef ALLOW_USB_SPINDOWN
954 usb_mode = true;
955 usb_acknowledge(SYS_USB_CONNECTED_ACK);
956 /* There is no need to force ATA power on */
957#else
946 if (poweroff) { 958 if (poweroff) {
947 mutex_lock(&ata_mtx); 959 mutex_lock(&ata_mtx);
948 ata_led(true); 960 ata_led(true);
@@ -951,14 +963,8 @@ static void ata_thread(void)
951 mutex_unlock(&ata_mtx); 963 mutex_unlock(&ata_mtx);
952 } 964 }
953 965
954 /* Tell the USB thread that we are safe */
955 DEBUGF("ata_thread got SYS_USB_CONNECTED\n");
956 usb_acknowledge(SYS_USB_CONNECTED_ACK);
957
958#ifdef ALLOW_USB_SPINDOWN
959 usb_mode = true;
960#else
961 /* Wait until the USB cable is extracted again */ 966 /* Wait until the USB cable is extracted again */
967 usb_acknowledge(SYS_USB_CONNECTED_ACK);
962 usb_wait_for_disconnect(&ata_queue); 968 usb_wait_for_disconnect(&ata_queue);
963#endif 969#endif
964 break; 970 break;
@@ -971,12 +977,15 @@ static void ata_thread(void)
971 usb_mode = false; 977 usb_mode = false;
972 break; 978 break;
973#endif 979#endif
974#endif 980#endif /* USB_NONE */
981
975 case Q_SLEEP: 982 case Q_SLEEP:
976#ifdef ALLOW_USB_SPINDOWN 983#ifdef ALLOW_USB_SPINDOWN
977 if(!usb_mode) 984 if(!usb_mode)
978#endif 985#endif
986 {
979 call_storage_idle_notifys(false); 987 call_storage_idle_notifys(false);
988 }
980 last_disk_activity = current_tick - sleep_timeout + (HZ/2); 989 last_disk_activity = current_tick - sleep_timeout + (HZ/2);
981 break; 990 break;
982 991
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index c8bbf28267..49b70f659a 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -24,20 +24,33 @@
24#include "kernel.h" 24#include "kernel.h"
25#include "button.h" 25#include "button.h"
26 26
27#if defined(IPOD_COLOR) || defined(IPOD_4G) \
28 || defined(IPOD_MINI) || defined(IPOD_MINI2G)
29#define USB_FIREWIRE_HANDLING
30#endif
31
27/* Messages from usb_tick and thread states */ 32/* Messages from usb_tick and thread states */
28enum { 33enum {
29 USB_INSERTED, 34 USB_INSERTED, /* Event+State */
30 USB_EXTRACTED, 35 USB_EXTRACTED, /* Event+State */
31 USB_REENABLE, 36#ifdef HAVE_USB_POWER
32 USB_POWERED, 37 USB_POWERED, /* State */
33 USB_TRANSFER_COMPLETION, 38#endif
34 USB_REQUEST_DISK, 39#ifdef HAVE_LCD_BITMAP
35 USB_RELEASE_DISK, 40 USB_SCREENDUMP, /* State */
36 USB_REQUEST_REBOOT, 41#endif
37 USB_QUIT, 42#if (CONFIG_STORAGE & STORAGE_MMC)
43 USB_REENABLE, /* Event */
44#endif
45#ifdef HAVE_USBSTACK
46 USB_TRANSFER_COMPLETION, /* Event */
47#endif
48#ifdef USB_FIREWIRE_HANDLING
49 USB_REQUEST_REBOOT, /* Event */
50#endif
51 USB_QUIT, /* Event */
38}; 52};
39 53
40
41#ifdef HAVE_USB_POWER 54#ifdef HAVE_USB_POWER
42#if CONFIG_KEYPAD == RECORDER_PAD 55#if CONFIG_KEYPAD == RECORDER_PAD
43#define USBPOWER_BUTTON BUTTON_F1 56#define USBPOWER_BUTTON BUTTON_F1
@@ -111,13 +124,10 @@ bool usb_charging_enabled(void);
111#ifdef HAVE_USBSTACK 124#ifdef HAVE_USBSTACK
112void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data); 125void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data);
113bool usb_driver_enabled(int driver); 126bool usb_driver_enabled(int driver);
114bool usb_exclusive_ata(void); /* ata is available for usb */ 127bool usb_exclusive_storage(void); /* storage is available for usb */
115void usb_request_exclusive_ata(void);
116void usb_release_exclusive_ata(void);
117#endif 128#endif
118 129
119#if defined(IPOD_COLOR) || defined(IPOD_4G) \ 130#ifdef USB_FIREWIRE_HANDLING
120 || defined(IPOD_MINI) || defined(IPOD_MINI2G)
121bool firewire_detect(void); 131bool firewire_detect(void);
122#endif 132#endif
123 133
diff --git a/firmware/export/usb_core.h b/firmware/export/usb_core.h
index 9d9e327bb3..7af8e43c8d 100644
--- a/firmware/export/usb_core.h
+++ b/firmware/export/usb_core.h
@@ -52,7 +52,7 @@ void usb_core_exit(void);
52void usb_core_control_request(struct usb_ctrlrequest* req); 52void usb_core_control_request(struct usb_ctrlrequest* req);
53void usb_core_transfer_complete(int endpoint, int dir, int status, int length); 53void usb_core_transfer_complete(int endpoint, int dir, int status, int length);
54void usb_core_bus_reset(void); 54void usb_core_bus_reset(void);
55bool usb_core_exclusive_connection(void); 55bool usb_core_any_exclusive_storage(void);
56void usb_core_enable_driver(int driver,bool enabled); 56void usb_core_enable_driver(int driver,bool enabled);
57bool usb_core_driver_enabled (int driver); 57bool usb_core_driver_enabled (int driver);
58void usb_core_handle_transfer_completion( 58void usb_core_handle_transfer_completion(
diff --git a/firmware/usb.c b/firmware/usb.c
index ec47e0653c..b52a255c0a 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -79,7 +79,7 @@ static int usb_mmc_countdown = 0;
79static long usb_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)]; 79static long usb_stack[(DEFAULT_STACK_SIZE + 0x800)/sizeof(long)];
80static const char usb_thread_name[] = "usb"; 80static const char usb_thread_name[] = "usb";
81static unsigned int usb_thread_entry = 0; 81static unsigned int usb_thread_entry = 0;
82#endif 82#endif /* USB_FULL_INIT */
83static struct event_queue usb_queue; 83static struct event_queue usb_queue;
84static int last_usb_status; 84static int last_usb_status;
85static bool usb_monitor_enabled; 85static bool usb_monitor_enabled;
@@ -87,16 +87,80 @@ static bool usb_monitor_enabled;
87static bool exclusive_storage_access; 87static bool exclusive_storage_access;
88#endif 88#endif
89 89
90 90#ifdef USB_FIREWIRE_HANDLING
91#if defined(IPOD_COLOR) || defined(IPOD_4G) \
92 || defined(IPOD_MINI) || defined(IPOD_MINI2G)
93static int firewire_countdown; 91static int firewire_countdown;
94static bool last_firewire_status; 92static bool last_firewire_status;
95#endif 93#endif
96 94
97#ifdef USB_FULL_INIT 95#ifdef USB_FULL_INIT
98#ifndef HAVE_USBSTACK 96
99static void usb_slave_mode(bool on) 97#if defined(USB_FIREWIRE_HANDLING) \
98 || (defined(HAVE_USBSTACK) && !defined(USE_ROCKBOX_USB))
99static void try_reboot(void)
100{
101#ifdef HAVE_DISK_STORAGE
102 storage_sleepnow(); /* Immediately spindown the disk. */
103 sleep(HZ*2);
104#endif
105
106#ifdef IPOD_ARCH /* The following code is based on ipodlinux */
107#if CONFIG_CPU == PP5020
108 memcpy((void *)0x40017f00, "diskmode\0\0hotstuff\0\0\1", 21);
109#elif CONFIG_CPU == PP5022
110 memcpy((void *)0x4001ff00, "diskmode\0\0hotstuff\0\0\1", 21);
111#endif /* CONFIG_CPU */
112#endif /* IPOD_ARCH */
113
114 system_reboot(); /* Reboot */
115}
116#endif /* USB_FIRWIRE_HANDLING || (HAVE_USBSTACK && !USE_ROCKBOX_USB) */
117
118#ifdef HAVE_USBSTACK
119/* inline since branch is chosen at compile time */
120static inline void usb_slave_mode(bool on)
121{
122#ifdef USE_ROCKBOX_USB
123 int rc;
124
125 if (on)
126 {
127 trigger_cpu_boost();
128#ifdef HAVE_PRIORITY_SCHEDULING
129 thread_set_priority(THREAD_ID_CURRENT, PRIORITY_REALTIME);
130#endif
131 usb_enable(true);
132 }
133 else /* usb_state == USB_INSERTED (only!) */
134 {
135 usb_enable(false);
136#ifdef HAVE_PRIORITY_SCHEDULING
137 thread_set_priority(THREAD_ID_CURRENT, PRIORITY_SYSTEM);
138#endif
139 /* Entered exclusive mode */
140 rc = disk_mount_all();
141 if (rc <= 0) /* no partition */
142 panicf("mount: %d",rc);
143
144 cancel_cpu_boost();
145 }
146#else /* !USB_ROCKBOX_USB */
147 if (on)
148 {
149 /* until we have native mass-storage mode, we want to reboot on
150 usb host connect */
151 try_reboot();
152 }
153#endif /* USE_ROCKBOX_USB */
154}
155
156void usb_signal_transfer_completion(
157 struct usb_transfer_completion_event_data* event_data)
158{
159 queue_post(&usb_queue, USB_TRANSFER_COMPLETION, (intptr_t)event_data);
160}
161#else /* !HAVE_USBSTACK */
162/* inline since branch is chosen at compile time */
163static inline void usb_slave_mode(bool on)
100{ 164{
101 int rc; 165 int rc;
102 166
@@ -107,11 +171,14 @@ static void usb_slave_mode(bool on)
107 storage_init(); 171 storage_init();
108 storage_enable(false); 172 storage_enable(false);
109 usb_enable(true); 173 usb_enable(true);
174 cpu_idle_mode(true);
110 } 175 }
111 else 176 else
112 { 177 {
113 DEBUGF("Leaving USB slave mode\n"); 178 DEBUGF("Leaving USB slave mode\n");
114 179
180 cpu_idle_mode(false);
181
115 /* Let the ISDx00 settle */ 182 /* Let the ISDx00 settle */
116 sleep(HZ*1); 183 sleep(HZ*1);
117 184
@@ -126,34 +193,31 @@ static void usb_slave_mode(bool on)
126 panicf("mount: %d",rc); 193 panicf("mount: %d",rc);
127 } 194 }
128} 195}
129#endif 196#endif /* HAVE_USBSTACK */
130 197
131static void try_reboot(void) 198#ifdef HAVE_USB_POWER
199static inline bool usb_power_button(void)
132{ 200{
133#ifdef HAVE_DISK_STORAGE 201#if defined(IRIVER_H10) || defined (IRIVER_H10_5GB)
134 storage_sleepnow(); /* Immediately spindown the disk. */ 202 return (button_status() & ~USBPOWER_BTN_IGNORE) != USBPOWER_BUTTON;
135 sleep(HZ*2); 203#else
204 return (button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON;
136#endif 205#endif
206}
137 207
138#ifdef IPOD_ARCH /* The following code is based on ipodlinux */ 208#ifdef USB_FIREWIRE_HANDLING
139#if CONFIG_CPU == PP5020 209static inline bool usb_reboot_button(void)
140 memcpy((void *)0x40017f00, "diskmode\0\0hotstuff\0\0\1", 21); 210{
141#elif CONFIG_CPU == PP5022 211 return (button_status() & ~USBPOWER_BTN_IGNORE) != USBPOWER_BUTTON;
142 memcpy((void *)0x4001ff00, "diskmode\0\0hotstuff\0\0\1", 21);
143#endif /* CONFIG_CPU */
144#endif /* IPOD_ARCH */
145
146 system_reboot(); /* Reboot */
147} 212}
213#endif
214#endif /* HAVE_USB_POWER */
148 215
149static void usb_thread(void) 216static void usb_thread(void)
150{ 217{
151 int num_acks_to_expect = -1; 218 int num_acks_to_expect = 0;
152 bool waiting_for_ack;
153 struct queue_event ev; 219 struct queue_event ev;
154 220
155 waiting_for_ack = false;
156
157 while(1) 221 while(1)
158 { 222 {
159 queue_wait(&usb_queue, &ev); 223 queue_wait(&usb_queue, &ev);
@@ -165,180 +229,116 @@ static void usb_thread(void)
165#endif 229#endif
166#ifdef HAVE_USBSTACK 230#ifdef HAVE_USBSTACK
167 case USB_TRANSFER_COMPLETION: 231 case USB_TRANSFER_COMPLETION:
168 usb_core_handle_transfer_completion((struct usb_transfer_completion_event_data*)ev.data); 232 usb_core_handle_transfer_completion(
169 break; 233 (struct usb_transfer_completion_event_data*)ev.data);
170#endif
171#ifdef HAVE_USB_POWER
172 case USB_POWERED:
173 usb_state = USB_POWERED;
174 break; 234 break;
175#endif 235#endif
176 case USB_INSERTED: 236 case USB_INSERTED:
177#ifdef HAVE_LCD_BITMAP 237#ifdef HAVE_LCD_BITMAP
178 if(do_screendump_instead_of_usb) 238 if(do_screendump_instead_of_usb)
179 { 239 {
240 usb_state = USB_SCREENDUMP;
180 screen_dump(); 241 screen_dump();
242 break;
181 } 243 }
182 else
183#endif 244#endif
184#ifdef HAVE_USB_POWER 245#ifdef HAVE_USB_POWER
185#if defined(IRIVER_H10) || defined (IRIVER_H10_5GB) 246 if (usb_power_button())
186 if((button_status() & ~USBPOWER_BTN_IGNORE) != USBPOWER_BUTTON)
187#else
188 if((button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON)
189#endif
190 { 247 {
248 /* Only charging is desired */
191 usb_state = USB_POWERED; 249 usb_state = USB_POWERED;
192#ifdef HAVE_USBSTACK 250#ifdef HAVE_USBSTACK
193 usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,false); 251 usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, false);
194 usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,true); 252 usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, true);
195 usb_enable(true);
196#endif
197 }
198 else
199#endif
200 {
201#ifdef HAVE_USBSTACK
202 /* Set the state to USB_POWERED for now. if a real
203 connection is detected it will switch to USB_INSERTED */
204 usb_state = USB_POWERED;
205 usb_core_enable_driver(USB_DRIVER_MASS_STORAGE,true);
206 usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY,false);
207 usb_enable(true); 253 usb_enable(true);
208#else
209 /* Tell all threads that they have to back off the ATA.
210 We subtract one for our own thread. */
211 num_acks_to_expect =
212 queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
213 waiting_for_ack = true;
214 DEBUGF("USB inserted. Waiting for ack from %d threads...\n",
215 num_acks_to_expect);
216#endif 254#endif
255 break;
217 } 256 }
218 break; 257#endif /* HAVE_USB_POWER */
219#ifdef HAVE_USBSTACK 258#ifdef HAVE_USBSTACK
220 case USB_REQUEST_DISK: 259 /* Set the state to USB_POWERED for now. If permission to connect
221 if(!waiting_for_ack) 260 * by threads and storage is granted it will be changed to
261 * USB_CONNECTED. */
262 usb_state = USB_POWERED;
263 usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, true);
264 usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, false);
265
266 /* Check any drivers enabled at this point for exclusive storage
267 * access requirements. */
268 exclusive_storage_access = usb_core_any_exclusive_storage();
269
270 if (exclusive_storage_access)
271#endif /* HAVE_USBSTACK */
222 { 272 {
223 /* Tell all threads that they have to back off the ATA. 273 /* Tell all threads that they have to back off the storage.
224 We subtract one for our own thread. */ 274 We subtract one for our own thread. */
225 num_acks_to_expect = 275 num_acks_to_expect = queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
226 queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
227 waiting_for_ack = true;
228 DEBUGF("USB inserted. Waiting for ack from %d threads...\n", 276 DEBUGF("USB inserted. Waiting for ack from %d threads...\n",
229 num_acks_to_expect); 277 num_acks_for_connect);
230 } 278 }
231 break; 279 break;
232 case USB_RELEASE_DISK: 280
233 if(!waiting_for_ack) 281 case SYS_USB_CONNECTED_ACK:
282 if(num_acks_to_expect > 0 && --num_acks_to_expect == 0)
234 { 283 {
235 /* Tell all threads that they have to back off the ATA. 284 DEBUGF("All threads have acknowledged the connect.\n");
236 We subtract one for our own thread. */ 285 usb_slave_mode(true);
237 num_acks_to_expect = 286 usb_state = USB_INSERTED;
238 queue_broadcast(SYS_USB_DISCONNECTED, 0) - 1;
239 waiting_for_ack = true;
240 DEBUGF("USB inserted. Waiting for ack from %d threads...\n",
241 num_acks_to_expect);
242 } 287 }
243 break; 288 else
244#endif
245 case SYS_USB_CONNECTED_ACK:
246 if(waiting_for_ack)
247 { 289 {
248 num_acks_to_expect--; 290 DEBUGF("usb: got ack, %d to go...\n",
249 if(num_acks_to_expect == 0) 291 num_acks_to_expect);
250 {
251 DEBUGF("All threads have acknowledged the connect.\n");
252#ifdef HAVE_USBSTACK
253#ifndef USE_ROCKBOX_USB
254 /* until we have native mass-storage mode, we want to reboot on
255 usb host connect */
256 try_reboot();
257#endif /* USE_ROCKBOX_USB */
258#ifdef HAVE_PRIORITY_SCHEDULING
259 thread_set_priority(usb_thread_entry,PRIORITY_REALTIME);
260#endif
261 exclusive_storage_access = true;
262
263#else
264 usb_slave_mode(true);
265 cpu_idle_mode(true);
266#endif
267 usb_state = USB_INSERTED;
268 waiting_for_ack = false;
269 }
270 else
271 {
272 DEBUGF("usb: got ack, %d to go...\n",
273 num_acks_to_expect);
274 }
275 } 292 }
276 break; 293 break;
277 294
278 case USB_EXTRACTED: 295 case USB_EXTRACTED:
279#ifdef HAVE_USBSTACK
280 usb_enable(false);
281#ifdef HAVE_PRIORITY_SCHEDULING
282 thread_set_priority(usb_thread_entry,PRIORITY_SYSTEM);
283#endif
284#endif
285#ifdef HAVE_LCD_BITMAP 296#ifdef HAVE_LCD_BITMAP
286 if(do_screendump_instead_of_usb) 297 if(usb_state == USB_SCREENDUMP)
287 break; 298 {
288#endif 299 usb_state = USB_EXTRACTED;
289#ifdef HAVE_USB_POWER 300 break; /* Connected for screendump only */
301 }
302#endif /* HAVE_LCD_BITMAP */
303#ifndef HAVE_USBSTACK /* Stack must undo this if POWERED state was transitional */
290 if(usb_state == USB_POWERED) 304 if(usb_state == USB_POWERED)
291 { 305 {
292 usb_state = USB_EXTRACTED; 306 usb_state = USB_EXTRACTED;
293 break; 307 break;
294 } 308 }
295#endif 309#endif /* HAVE_USBSTACK */
296#ifndef HAVE_USBSTACK
297 if(usb_state == USB_INSERTED) 310 if(usb_state == USB_INSERTED)
298 { 311 {
299 /* Only disable the USB mode if we really have enabled it 312 /* Only disable the USB mode if we really have enabled it
300 some threads might not have acknowledged the 313 some threads might not have acknowledged the
301 insertion */ 314 insertion */
302 usb_slave_mode(false); 315 usb_slave_mode(false);
303 cpu_idle_mode(false);
304 } 316 }
305#endif
306 317
307 usb_state = USB_EXTRACTED; 318 usb_state = USB_EXTRACTED;
308#ifdef HAVE_USBSTACK 319#ifdef HAVE_USBSTACK
309 if(exclusive_storage_access) 320 if (!exclusive_storage_access)
310 { 321 break;
311 int rc = disk_mount_all(); 322
312 if (rc <= 0) /* no partition */ 323 exclusive_storage_access = false;
313 panicf("mount: %d",rc); 324#endif /* HAVE_USBSTACK */
314 exclusive_storage_access = false; 325 /* Tell all threads that we are back in business */
315#endif 326 num_acks_to_expect =
316 /* Tell all threads that we are back in business */ 327 queue_broadcast(SYS_USB_DISCONNECTED, 0) - 1;
317 num_acks_to_expect = 328 DEBUGF("USB extracted. Waiting for ack from %d threads...\n",
318 queue_broadcast(SYS_USB_DISCONNECTED, 0) - 1; 329 num_acks_to_expect);
319 waiting_for_ack = true;
320 DEBUGF("USB extracted. Waiting for ack from %d threads...\n",
321 num_acks_to_expect);
322#ifdef HAVE_USBSTACK
323 }
324#endif
325 break; 330 break;
326 331
327 case SYS_USB_DISCONNECTED_ACK: 332 case SYS_USB_DISCONNECTED_ACK:
328 if(waiting_for_ack) 333 if(num_acks_to_expect > 0 && --num_acks_to_expect == 0)
329 { 334 {
330 num_acks_to_expect--; 335 DEBUGF("All threads have acknowledged. "
331 if(num_acks_to_expect == 0) 336 "We're in business.\n");
332 { 337 }
333 DEBUGF("All threads have acknowledged. " 338 else
334 "We're in business.\n"); 339 {
335 waiting_for_ack = false; 340 DEBUGF("usb: got ack, %d to go...\n",
336 } 341 num_acks_to_expect);
337 else
338 {
339 DEBUGF("usb: got ack, %d to go...\n",
340 num_acks_to_expect);
341 }
342 } 342 }
343 break; 343 break;
344 344
@@ -347,49 +347,44 @@ static void usb_thread(void)
347 case SYS_HOTSWAP_EXTRACTED: 347 case SYS_HOTSWAP_EXTRACTED:
348#ifdef HAVE_USBSTACK 348#ifdef HAVE_USBSTACK
349 usb_core_hotswap_event(1,ev.id == SYS_HOTSWAP_INSERTED); 349 usb_core_hotswap_event(1,ev.id == SYS_HOTSWAP_INSERTED);
350#else 350#else /* !HAVE_USBSTACK */
351 if(usb_state == USB_INSERTED) 351 if(usb_state == USB_INSERTED)
352 { 352 {
353 usb_enable(false); 353 usb_enable(false);
354#if (CONFIG_STORAGE & STORAGE_MMC) 354#if (CONFIG_STORAGE & STORAGE_MMC)
355 usb_mmc_countdown = HZ/2; /* re-enable after 0.5 sec */ 355 usb_mmc_countdown = HZ/2; /* re-enable after 0.5 sec */
356#endif 356#endif /* STORAGE_MMC */
357 } 357 }
358#endif 358#endif /* HAVE_USBSTACK */
359 break; 359 break;
360 360
361#if (CONFIG_STORAGE & STORAGE_MMC)
361 case USB_REENABLE: 362 case USB_REENABLE:
362 if(usb_state == USB_INSERTED) 363 if(usb_state == USB_INSERTED)
363 usb_enable(true); /* reenable only if still inserted */ 364 usb_enable(true); /* reenable only if still inserted */
364 break; 365 break;
366#endif /* STORAGE_MMC */
365#endif /* HAVE_HOTSWAP */ 367#endif /* HAVE_HOTSWAP */
368
369#ifdef USB_FIREWIRE_HANDLING
366 case USB_REQUEST_REBOOT: 370 case USB_REQUEST_REBOOT:
367#ifdef HAVE_USB_POWER 371#ifdef HAVE_USB_POWER
368 if((button_status() & ~USBPOWER_BTN_IGNORE) != USBPOWER_BUTTON) 372 if (usb_reboot_button())
369#endif 373#endif
370 try_reboot(); 374 try_reboot();
371 break; 375 break;
376#endif /* USB_FIREWIRE_HANDLING */
372 } 377 }
373 } 378 }
374} 379}
375#endif
376 380
377#ifdef HAVE_USBSTACK
378void usb_signal_transfer_completion(struct usb_transfer_completion_event_data* event_data)
379{
380 queue_post(&usb_queue, USB_TRANSFER_COMPLETION, (intptr_t)event_data);
381}
382#endif
383
384#ifdef USB_FULL_INIT
385static void usb_tick(void) 381static void usb_tick(void)
386{ 382{
387 int current_status; 383 int current_status;
388 384
389 if(usb_monitor_enabled) 385 if(usb_monitor_enabled)
390 { 386 {
391#if defined(IPOD_COLOR) || defined(IPOD_4G) \ 387#ifdef USB_FIREWIRE_HANDLING
392 || defined(IPOD_MINI) || defined(IPOD_MINI2G)
393 int current_firewire_status = firewire_detect(); 388 int current_firewire_status = firewire_detect();
394 if(current_firewire_status != last_firewire_status) 389 if(current_firewire_status != last_firewire_status)
395 { 390 {
@@ -409,7 +404,7 @@ static void usb_tick(void)
409 queue_post(&usb_queue, USB_REQUEST_REBOOT, 0); 404 queue_post(&usb_queue, USB_REQUEST_REBOOT, 0);
410 } 405 }
411 } 406 }
412#endif 407#endif /* USB_FIREWIRE_HANDLING */
413 408
414 current_status = usb_detect(); 409 current_status = usb_detect();
415 410
@@ -442,7 +437,7 @@ static void usb_tick(void)
442 } 437 }
443#endif 438#endif
444} 439}
445#endif 440#endif /* USB_FULL_INIT */
446 441
447void usb_acknowledge(long id) 442void usb_acknowledge(long id)
448{ 443{
@@ -458,8 +453,7 @@ void usb_init(void)
458 usb_monitor_enabled = false; 453 usb_monitor_enabled = false;
459 countdown = -1; 454 countdown = -1;
460 455
461#if defined(IPOD_COLOR) || defined(IPOD_4G) \ 456#ifdef USB_FIREWIRE_HANDLING
462 || defined(IPOD_MINI) || defined(IPOD_MINI2G)
463 firewire_countdown = -1; 457 firewire_countdown = -1;
464 last_firewire_status = false; 458 last_firewire_status = false;
465#endif 459#endif
@@ -480,8 +474,7 @@ void usb_init(void)
480 IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU)); 474 IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU));
481 475
482 tick_add_task(usb_tick); 476 tick_add_task(usb_tick);
483#endif 477#endif /* USB_FULL_INIT */
484
485} 478}
486 479
487void usb_wait_for_disconnect(struct event_queue *q) 480void usb_wait_for_disconnect(struct event_queue *q)
@@ -518,10 +511,8 @@ int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks)
518 case SYS_USB_DISCONNECTED: 511 case SYS_USB_DISCONNECTED:
519 usb_acknowledge(SYS_USB_DISCONNECTED_ACK); 512 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
520 return 0; 513 return 0;
521 break;
522 case SYS_TIMEOUT: 514 case SYS_TIMEOUT:
523 return 1; 515 return 1;
524 break;
525 } 516 }
526 } 517 }
527#else 518#else
@@ -562,27 +553,7 @@ bool usb_inserted(void)
562} 553}
563 554
564#ifdef HAVE_USBSTACK 555#ifdef HAVE_USBSTACK
565void usb_request_exclusive_ata(void) 556bool usb_exclusive_storage(void)
566{
567 /* This is not really a clean place to start boosting the cpu. but it's
568 * currently the best one. We want to get rid of having to boost the cpu
569 * for usb anyway */
570 trigger_cpu_boost();
571 if(!exclusive_storage_access) {
572 queue_post(&usb_queue, USB_REQUEST_DISK, 0);
573 }
574}
575
576void usb_release_exclusive_ata(void)
577{
578 cancel_cpu_boost();
579 if(exclusive_storage_access) {
580 queue_post(&usb_queue, USB_RELEASE_DISK, 0);
581 exclusive_storage_access = false;
582 }
583}
584
585bool usb_exclusive_ata(void)
586{ 557{
587 return exclusive_storage_access; 558 return exclusive_storage_access;
588} 559}
diff --git a/firmware/usbstack/usb_charging_only.h b/firmware/usbstack/usb_charging_only.h
index 8bdf58ff1d..839e07dae4 100644
--- a/firmware/usbstack/usb_charging_only.h
+++ b/firmware/usbstack/usb_charging_only.h
@@ -5,7 +5,7 @@
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id: $ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2008 by Frank Gevaerts 10 * Copyright (C) 2008 by Frank Gevaerts
11 * 11 *
diff --git a/firmware/usbstack/usb_class_driver.h b/firmware/usbstack/usb_class_driver.h
index e089c488a8..b037e1dec2 100644
--- a/firmware/usbstack/usb_class_driver.h
+++ b/firmware/usbstack/usb_class_driver.h
@@ -33,7 +33,7 @@ struct usb_class_driver {
33 /* Driver api starts here */ 33 /* Driver api starts here */
34 34
35 /* Set this to true if the driver needs exclusive disk access (e.g. usb storage) */ 35 /* Set this to true if the driver needs exclusive disk access (e.g. usb storage) */
36 bool needs_exclusive_ata; 36 bool needs_exclusive_storage;
37 37
38 /* Let the driver request endpoints it need. Returns zero on success */ 38 /* Let the driver request endpoints it need. Returns zero on success */
39 int (*request_endpoints)(struct usb_class_driver *); 39 int (*request_endpoints)(struct usb_class_driver *);
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index ea5d6590f6..50c9d8589c 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -54,6 +54,9 @@
54#include "ata.h" 54#include "ata.h"
55#endif 55#endif
56 56
57#ifndef USB_MAX_CURRENT
58#define USB_MAX_CURRENT 500
59#endif
57 60
58/*-------------------------------------------------------------------------*/ 61/*-------------------------------------------------------------------------*/
59/* USB protocol descriptors: */ 62/* USB protocol descriptors: */
@@ -94,7 +97,7 @@ static struct usb_config_descriptor __attribute__((aligned(2)))
94 .bConfigurationValue = 1, 97 .bConfigurationValue = 1,
95 .iConfiguration = 0, 98 .iConfiguration = 0,
96 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, 99 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
97 .bMaxPower = 250, /* 500mA in 2mA units */ 100 .bMaxPower = (USB_MAX_CURRENT+1) / 2, /* In 2mA units */
98}; 101};
99 102
100 103
@@ -179,7 +182,7 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
179#ifdef USB_STORAGE 182#ifdef USB_STORAGE
180 [USB_DRIVER_MASS_STORAGE] = { 183 [USB_DRIVER_MASS_STORAGE] = {
181 .enabled = false, 184 .enabled = false,
182 .needs_exclusive_ata = true, 185 .needs_exclusive_storage = true,
183 .first_interface = 0, 186 .first_interface = 0,
184 .last_interface = 0, 187 .last_interface = 0,
185 .request_endpoints = usb_storage_request_endpoints, 188 .request_endpoints = usb_storage_request_endpoints,
@@ -198,7 +201,7 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
198#ifdef USB_SERIAL 201#ifdef USB_SERIAL
199 [USB_DRIVER_SERIAL] = { 202 [USB_DRIVER_SERIAL] = {
200 .enabled = false, 203 .enabled = false,
201 .needs_exclusive_ata = false, 204 .needs_exclusive_storage = false,
202 .first_interface = 0, 205 .first_interface = 0,
203 .last_interface = 0, 206 .last_interface = 0,
204 .request_endpoints = usb_serial_request_endpoints, 207 .request_endpoints = usb_serial_request_endpoints,
@@ -217,7 +220,7 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
217#ifdef USB_CHARGING_ONLY 220#ifdef USB_CHARGING_ONLY
218 [USB_DRIVER_CHARGING_ONLY] = { 221 [USB_DRIVER_CHARGING_ONLY] = {
219 .enabled = false, 222 .enabled = false,
220 .needs_exclusive_ata = false, 223 .needs_exclusive_storage = false,
221 .first_interface = 0, 224 .first_interface = 0,
222 .last_interface = 0, 225 .last_interface = 0,
223 .request_endpoints = usb_charging_only_request_endpoints, 226 .request_endpoints = usb_charging_only_request_endpoints,
@@ -353,13 +356,17 @@ void usb_core_exit(void)
353 int i; 356 int i;
354 for(i=0;i<USB_NUM_DRIVERS;i++) { 357 for(i=0;i<USB_NUM_DRIVERS;i++) {
355 if(drivers[i].enabled && drivers[i].disconnect != NULL) 358 if(drivers[i].enabled && drivers[i].disconnect != NULL)
359 {
356 drivers[i].disconnect (); 360 drivers[i].disconnect ();
361 drivers[i].enabled = false;
362 }
357 } 363 }
358 364
359 if (initialized) { 365 if (initialized) {
360 usb_drv_exit(); 366 usb_drv_exit();
361 } 367 }
362 initialized = false; 368 initialized = false;
369 usb_state = DEFAULT;
363 logf("usb_core_exit() finished"); 370 logf("usb_core_exit() finished");
364} 371}
365 372
@@ -392,6 +399,20 @@ bool usb_core_driver_enabled(int driver)
392 return drivers[driver].enabled; 399 return drivers[driver].enabled;
393} 400}
394 401
402bool usb_core_any_exclusive_storage(void)
403{
404 int i;
405 for(i=0;i<USB_NUM_DRIVERS;i++) {
406 if(drivers[i].enabled &&
407 drivers[i].needs_exclusive_storage)
408 {
409 return true;
410 }
411 }
412
413 return false;
414}
415
395#ifdef HAVE_HOTSWAP 416#ifdef HAVE_HOTSWAP
396void usb_core_hotswap_event(int volume,bool inserted) 417void usb_core_hotswap_event(int volume,bool inserted)
397{ 418{
@@ -484,14 +505,6 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req)
484 usb_core_set_serial_function_id(); 505 usb_core_set_serial_function_id();
485 506
486 allocate_interfaces_and_endpoints(); 507 allocate_interfaces_and_endpoints();
487
488 for(i=0;i<USB_NUM_DRIVERS;i++) {
489 if(drivers[i].enabled &&
490 drivers[i].needs_exclusive_ata) {
491 usb_request_exclusive_ata();
492 break;
493 }
494 }
495 } 508 }
496 509
497 switch(req->bRequestType & 0x1f) { 510 switch(req->bRequestType & 0x1f) {
@@ -788,7 +801,7 @@ unsigned short usb_allowed_current()
788{ 801{
789 if (usb_state == CONFIGURED) 802 if (usb_state == CONFIGURED)
790 { 803 {
791 return 500; 804 return MAX(USB_MAX_CURRENT, 100);
792 } 805 }
793 else 806 else
794 { 807 {
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 8a4915123c..a70681d3e0 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -293,6 +293,7 @@ static bool check_disk_present(IF_MV_NONVOID(int volume))
293#endif 293#endif
294} 294}
295 295
296#if 0
296static void try_release_ata(void) 297static void try_release_ata(void)
297{ 298{
298 /* Check if there is a connected drive left. If not, 299 /* Check if there is a connected drive left. If not,
@@ -310,6 +311,7 @@ static void try_release_ata(void)
310 usb_release_exclusive_ata(); 311 usb_release_exclusive_ata();
311 } 312 }
312} 313}
314#endif
313 315
314#ifdef HAVE_HOTSWAP 316#ifdef HAVE_HOTSWAP
315void usb_storage_notify_hotswap(int volume,bool inserted) 317void usb_storage_notify_hotswap(int volume,bool inserted)
@@ -320,9 +322,7 @@ void usb_storage_notify_hotswap(int volume,bool inserted)
320 } 322 }
321 else { 323 else {
322 ejected[volume] = true; 324 ejected[volume] = true;
323 try_release_ata();
324 } 325 }
325
326} 326}
327#endif 327#endif
328 328
@@ -334,7 +334,6 @@ void usb_storage_reconnect(void)
334 for(i=0;i<NUM_VOLUMES;i++) 334 for(i=0;i<NUM_VOLUMES;i++)
335 ejected[i] = !check_disk_present(IF_MV(i)); 335 ejected[i] = !check_disk_present(IF_MV(i));
336 logf("%s", __func__); 336 logf("%s", __func__);
337 usb_request_exclusive_ata();
338 } 337 }
339} 338}
340 339
@@ -682,7 +681,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
682#ifdef HAVE_HOTSWAP 681#ifdef HAVE_HOTSWAP
683 if(storage_removable(lun) && !storage_present(lun)) { 682 if(storage_removable(lun) && !storage_present(lun)) {
684 ejected[lun] = true; 683 ejected[lun] = true;
685 try_release_ata();
686 } 684 }
687#endif 685#endif
688 686
@@ -699,7 +697,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
699 switch (cbw->command_block[0]) { 697 switch (cbw->command_block[0]) {
700 case SCSI_TEST_UNIT_READY: 698 case SCSI_TEST_UNIT_READY:
701 logf("scsi test_unit_ready %d",lun); 699 logf("scsi test_unit_ready %d",lun);
702 if(!usb_exclusive_ata()) { 700 if(!usb_exclusive_storage()) {
703 send_csw(UMS_STATUS_FAIL); 701 send_csw(UMS_STATUS_FAIL);
704 cur_sense_data.sense_key=SENSE_NOT_READY; 702 cur_sense_data.sense_key=SENSE_NOT_READY;
705 cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; 703 cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
@@ -885,7 +883,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
885 { 883 {
886 logf("scsi eject"); 884 logf("scsi eject");
887 ejected[lun]=true; 885 ejected[lun]=true;
888 try_release_ata();
889 } 886 }
890 } 887 }
891 } 888 }