summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 }