summaryrefslogtreecommitdiff
path: root/firmware/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/usb.c')
-rw-r--r--firmware/usb.c146
1 files changed, 134 insertions, 12 deletions
diff --git a/firmware/usb.c b/firmware/usb.c
index a3421c7d47..c6ae306218 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -22,6 +22,14 @@
22#include "thread.h" 22#include "thread.h"
23#include "system.h" 23#include "system.h"
24#include "debug.h" 24#include "debug.h"
25#include "ata.h"
26#include "fat.h"
27#include "disk.h"
28#include "panic.h"
29
30
31#define USB_REALLY_BRAVE
32
25 33
26#ifndef SIMULATOR 34#ifndef SIMULATOR
27 35
@@ -30,7 +38,55 @@
30 38
31static char usb_stack[0x100]; 39static char usb_stack[0x100];
32static struct event_queue usb_queue; 40static struct event_queue usb_queue;
33static bool usb_connected; 41static bool last_usb_status;
42static bool usb_monitor_enabled;
43
44static void usb_enable(bool on)
45{
46#ifdef ARCHOS_RECORDER
47 if(!on) /* The pin is inverted on the Recorder */
48#else
49 if(on)
50#endif
51 PADR &= ~0x400; /* enable USB */
52 else
53 PADR |= 0x400;
54 PAIOR |= 0x400;
55}
56
57static void usb_slave_mode(bool on)
58{
59 int rc;
60 struct partinfo* pinfo;
61
62 if(on)
63 {
64 DEBUGF("Entering USB slave mode\n");
65 ata_enable(false);
66 usb_enable(true);
67 }
68 else
69 {
70 DEBUGF("Leaving USB slave mode\n");
71
72 /* Let the ISDx00 settle */
73 sleep(HZ*1);
74
75 usb_enable(false);
76
77 rc = ata_init();
78 if(rc)
79 panicf("ata: %d",rc);
80
81 pinfo = disk_init();
82 if (!pinfo)
83 panicf("disk: NULL");
84
85 rc = fat_mount(pinfo[0].start);
86 if(rc)
87 panicf("mount: %d",rc);
88 }
89}
34 90
35static void usb_thread(void) 91static void usb_thread(void)
36{ 92{
@@ -50,7 +106,8 @@ static void usb_thread(void)
50 We subtract one for our own thread. */ 106 We subtract one for our own thread. */
51 num_acks_to_expect = queue_broadcast(SYS_USB_CONNECTED, NULL) - 1; 107 num_acks_to_expect = queue_broadcast(SYS_USB_CONNECTED, NULL) - 1;
52 waiting_for_ack = true; 108 waiting_for_ack = true;
53 DEBUGF("USB inserted. Waiting for ack from %d threads...\n"); 109 DEBUGF("USB inserted. Waiting for ack from %d threads...\n",
110 num_acks_to_expect);
54 break; 111 break;
55 112
56 case SYS_USB_CONNECTED_ACK: 113 case SYS_USB_CONNECTED_ACK:
@@ -65,13 +122,43 @@ static void usb_thread(void)
65 current firmware isn't quite ready for this yet. 122 current firmware isn't quite ready for this yet.
66 Let's just chicken out and reboot. */ 123 Let's just chicken out and reboot. */
67 DEBUGF("All threads have acknowledged. Rebooting...\n"); 124 DEBUGF("All threads have acknowledged. Rebooting...\n");
125#ifdef USB_REALLY_BRAVE
126 usb_slave_mode(true);
127#else
68 system_reboot(); 128 system_reboot();
129#endif
69 } 130 }
70 else 131 else
71 { 132 {
72 DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect); 133 DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect);
73 } 134 }
74 } 135 }
136 break;
137
138 case USB_EXTRACTED:
139 /* Tell all threads that we are back in business */
140 num_acks_to_expect =
141 queue_broadcast(SYS_USB_DISCONNECTED, NULL) - 1;
142 waiting_for_ack = true;
143 DEBUGF("USB extracted. Waiting for ack from %d threads...\n",
144 num_acks_to_expect);
145 break;
146
147 case SYS_USB_DISCONNECTED_ACK:
148 if(waiting_for_ack)
149 {
150 num_acks_to_expect--;
151 if(num_acks_to_expect == 0)
152 {
153 DEBUGF("All threads have acknowledged. We're in business.\n");
154 usb_slave_mode(false);
155 }
156 else
157 {
158 DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect);
159 }
160 }
161 break;
75 } 162 }
76 } 163 }
77} 164}
@@ -80,16 +167,23 @@ static void usb_tick(void)
80{ 167{
81 bool current_status; 168 bool current_status;
82 169
170 if(usb_monitor_enabled)
171 {
83#ifdef ARCHOS_RECORDER 172#ifdef ARCHOS_RECORDER
84 current_status = (PCDR & 0x04)?true:false; 173 current_status = (PCDR & 0x04)?true:false;
85#else 174#else
86 current_status = (PADR & 0x8000)?false:true; 175 current_status = (PADR & 0x8000)?false:true;
87#endif 176#endif
88 177
89 if(current_status && !usb_connected) 178 /* Only report when the status has changed */
90 { 179 if(current_status != last_usb_status)
91 usb_connected = true; 180 {
92 queue_post(&usb_queue, USB_INSERTED, NULL); 181 last_usb_status = current_status;
182 if(current_status)
183 queue_post(&usb_queue, USB_INSERTED, NULL);
184 else
185 queue_post(&usb_queue, USB_EXTRACTED, NULL);
186 }
93 } 187 }
94} 188}
95 189
@@ -100,14 +194,38 @@ void usb_acknowledge(int id)
100 194
101void usb_init(void) 195void usb_init(void)
102{ 196{
103 int rc; 197 usb_monitor_enabled = false;
104 198
105 usb_connected = false; 199 usb_enable(false);
200
201 /* We assume that the USB cable is extracted */
202 last_usb_status = false;
106 203
107 queue_init(&usb_queue); 204 queue_init(&usb_queue);
108 create_thread(usb_thread, usb_stack, sizeof(usb_stack)); 205 create_thread(usb_thread, usb_stack, sizeof(usb_stack));
109 206
110 rc = tick_add_task(usb_tick); 207 tick_add_task(usb_tick);
208}
209
210void usb_wait_for_disconnect(struct event_queue *q)
211{
212 struct event ev;
213
214 /* Don't return until we get SYS_USB_DISCONNECTED */
215 while(1)
216 {
217 queue_wait(q, &ev);
218 if(ev.id == SYS_USB_DISCONNECTED)
219 {
220 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
221 return;
222 }
223 }
224}
225
226void usb_start_monitoring(void)
227{
228 usb_monitor_enabled = true;
111} 229}
112 230
113#else 231#else
@@ -122,4 +240,8 @@ void usb_init(void)
122{ 240{
123} 241}
124 242
243void usb_start_monitoring(void)
244{
245}
246
125#endif 247#endif