Imported Upstream version 3.0
[debian/gnuradio] / usrp / firmware / lib / usb_common.c
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2003 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "usb_common.h"
24 #include "fx2regs.h"
25 #include "syncdelay.h"
26 #include "fx2utils.h"
27 #include "isr.h"
28 #include "usb_descriptors.h"
29 #include "usb_requests.h"
30
31 extern xdata char str0[];
32 extern xdata char str1[];
33 extern xdata char str2[];
34 extern xdata char str3[];
35 extern xdata char str4[];
36 extern xdata char str5[];
37
38
39 #define bRequestType    SETUPDAT[0]
40 #define bRequest        SETUPDAT[1]
41 #define wValueL         SETUPDAT[2]
42 #define wValueH         SETUPDAT[3]
43 #define wIndexL         SETUPDAT[4]
44 #define wIndexH         SETUPDAT[5]
45 #define wLengthL        SETUPDAT[6]
46 #define wLengthH        SETUPDAT[7]
47
48 #define MSB(x)  (((unsigned short) x) >> 8)
49 #define LSB(x)  (((unsigned short) x) & 0xff)
50
51 volatile bit _usb_got_SUDAV;
52
53 unsigned char   _usb_config = 0;
54 unsigned char   _usb_alt_setting = 0;   // FIXME really 1/interface
55
56 xdata unsigned char *current_device_descr;
57 xdata unsigned char *current_devqual_descr;
58 xdata unsigned char *current_config_descr;
59 xdata unsigned char *other_config_descr;
60
61 static void
62 setup_descriptors (void)
63 {
64   if (USBCS & bmHSM){           // high speed mode
65     current_device_descr  = high_speed_device_descr;
66     current_devqual_descr = high_speed_devqual_descr;
67     current_config_descr  = high_speed_config_descr;
68     other_config_descr    = full_speed_config_descr;
69   }
70   else {
71     current_device_descr  = full_speed_device_descr;
72     current_devqual_descr = full_speed_devqual_descr;
73     current_config_descr  = full_speed_config_descr;
74     other_config_descr    = high_speed_config_descr;
75   }
76
77   // whack the type fields
78   // FIXME, may not be required.
79   // current_config_descr[1] = DT_CONFIG;
80   // other_config_descr[1]   = DT_OTHER_SPEED;
81 }
82
83 static void
84 isr_SUDAV (void) interrupt
85 {
86   clear_usb_irq ();
87   _usb_got_SUDAV = 1;
88 }
89
90 static void
91 isr_USBRESET (void) interrupt
92 {
93   clear_usb_irq ();
94   setup_descriptors ();
95 }
96
97 static void
98 isr_HIGHSPEED (void) interrupt
99 {
100   clear_usb_irq ();
101   setup_descriptors ();
102 }
103
104 void
105 usb_install_handlers (void)
106 {
107   setup_descriptors ();     // ensure that they're set before use
108
109   hook_uv (UV_SUDAV,     (unsigned short) isr_SUDAV);
110   hook_uv (UV_USBRESET,  (unsigned short) isr_USBRESET);
111   hook_uv (UV_HIGHSPEED, (unsigned short) isr_HIGHSPEED);
112
113   USBIE = bmSUDAV | bmURES | bmHSGRANT;
114 }
115
116 // On the FX2 the only plausible endpoints are 0, 1, 2, 4, 6, 8
117 // This doesn't check to see that they're enabled
118
119 unsigned char
120 plausible_endpoint (unsigned char ep)
121 {
122   ep &= ~0x80;  // ignore direction bit
123
124   if (ep > 8)
125     return 0;
126
127   if (ep == 1)
128     return 1;
129
130   return (ep & 0x1) == 0;       // must be even
131 }
132
133 // return pointer to control and status register for endpoint.
134 // only called with plausible_endpoints
135
136 xdata volatile unsigned char *
137 epcs (unsigned char ep)
138 {
139   if (ep == 0x01)               // ep1 has different in and out CS regs
140     return EP1OUTCS;
141
142   if (ep == 0x81)
143     return EP1INCS;
144
145   ep &= ~0x80;                  // ignore direction bit
146
147   if (ep == 0x00)               // ep0
148     return EP0CS;
149
150   return EP2CS + (ep >> 1);     // 2, 4, 6, 8 are consecutive
151 }
152
153 void
154 usb_handle_setup_packet (void)
155 {
156   _usb_got_SUDAV = 0;
157
158   // handle the standard requests...
159
160   switch (bRequestType & bmRT_TYPE_MASK){
161
162   case bmRT_TYPE_CLASS:
163   case bmRT_TYPE_RESERVED:
164     fx2_stall_ep0 ();           // we don't handle these.  indicate error
165     break;
166     
167   case bmRT_TYPE_VENDOR:
168     // call the application code.
169     // If it handles the command it returns non-zero
170
171     if (!app_vendor_cmd ())     
172       fx2_stall_ep0 ();
173     break;
174
175   case bmRT_TYPE_STD:
176     // these are the standard requests...
177
178     if ((bRequestType & bmRT_DIR_MASK) == bmRT_DIR_IN){
179
180       ////////////////////////////////////
181       //    handle the IN requests
182       ////////////////////////////////////
183
184       switch (bRequest){
185
186       case RQ_GET_CONFIG:
187         EP0BUF[0] = _usb_config;        // FIXME app should handle
188         EP0BCH = 0;
189         EP0BCL = 1;
190         break;
191         
192       // --------------------------------
193
194       case RQ_GET_INTERFACE:
195         EP0BUF[0] = _usb_alt_setting;   // FIXME app should handle
196         EP0BCH = 0;
197         EP0BCL = 1;
198         break;
199
200       // --------------------------------
201
202       case RQ_GET_DESCR:
203         switch (wValueH){
204
205         case DT_DEVICE:
206           SUDPTRH = MSB (current_device_descr);
207           SUDPTRL = LSB (current_device_descr);
208           break;
209           
210         case DT_DEVQUAL:
211           SUDPTRH = MSB (current_devqual_descr);
212           SUDPTRL = LSB (current_devqual_descr);
213           break;
214
215         case DT_CONFIG:
216           if (0 && wValueL != 1)        // FIXME only a single configuration
217             fx2_stall_ep0 ();
218           else {
219             SUDPTRH = MSB (current_config_descr);
220             SUDPTRL = LSB (current_config_descr);
221           }
222           break;
223
224         case DT_OTHER_SPEED:
225           if (0 && wValueL != 1)        // FIXME only a single configuration
226             fx2_stall_ep0 ();
227           else {
228             SUDPTRH = MSB (other_config_descr);
229             SUDPTRL = LSB (other_config_descr);
230           }
231           break;
232
233         case DT_STRING:
234           if (wValueL >= nstring_descriptors)
235             fx2_stall_ep0 ();
236           else {
237             xdata char *p = string_descriptors[wValueL];
238             SUDPTRH = MSB (p);
239             SUDPTRL = LSB (p);
240           }
241           break;
242
243         default:
244           fx2_stall_ep0 ();     // invalid request
245           break;
246         }
247         break;
248         
249       // --------------------------------
250
251       case RQ_GET_STATUS:
252         switch (bRequestType & bmRT_RECIP_MASK){
253         case bmRT_RECIP_DEVICE:
254           EP0BUF[0] = bmGSDA_SELF_POWERED;      // FIXME app should handle
255           EP0BUF[1] = 0;
256           EP0BCH = 0;
257           EP0BCL = 2;
258           break;
259
260         case bmRT_RECIP_INTERFACE:
261           EP0BUF[0] = 0;
262           EP0BUF[1] = 0;
263           EP0BCH = 0;
264           EP0BCL = 2;
265           break;
266
267         case bmRT_RECIP_ENDPOINT:
268           if (plausible_endpoint (wIndexL)){
269             EP0BUF[0] = *epcs (wIndexL) & bmEPSTALL;
270             EP0BUF[1] = 0;
271             EP0BCH = 0;
272             EP0BCL = 2;
273           }
274           else
275             fx2_stall_ep0 ();
276           break;
277
278         default:
279           fx2_stall_ep0 ();
280           break;
281         }
282
283       // --------------------------------
284
285       case RQ_SYNCH_FRAME:      // not implemented
286       default:
287         fx2_stall_ep0 ();
288         break;
289       }
290     }
291
292     else {
293
294       ////////////////////////////////////
295       //    handle the OUT requests
296       ////////////////////////////////////
297
298       switch (bRequest){
299
300       case RQ_SET_CONFIG:
301         _usb_config = wValueL;          // FIXME app should handle
302         break;
303
304       case RQ_SET_INTERFACE:
305         _usb_alt_setting = wValueL;     // FIXME app should handle
306         break;
307
308       // --------------------------------
309
310       case RQ_CLEAR_FEATURE:
311         switch (bRequestType & bmRT_RECIP_MASK){
312
313         case bmRT_RECIP_DEVICE:
314           switch (wValueL){
315           case FS_DEV_REMOTE_WAKEUP:
316           default:
317             fx2_stall_ep0 ();
318           }
319           break;
320
321         case bmRT_RECIP_ENDPOINT:
322           if (wValueL == FS_ENDPOINT_HALT && plausible_endpoint (wIndexL)){
323             *epcs (wIndexL) &= ~bmEPSTALL;
324             fx2_reset_data_toggle (wIndexL);
325           }
326           else
327             fx2_stall_ep0 ();
328           break;
329
330         default:
331           fx2_stall_ep0 ();
332           break;
333         }
334         break;
335
336       // --------------------------------
337
338       case RQ_SET_FEATURE:
339         switch (bRequestType & bmRT_RECIP_MASK){
340
341         case bmRT_RECIP_DEVICE:
342           switch (wValueL){
343           case FS_TEST_MODE:
344             // hardware handles this after we complete SETUP phase handshake
345             break;
346
347           case FS_DEV_REMOTE_WAKEUP:
348           default:
349             fx2_stall_ep0 ();
350             break;
351           }
352         }
353         break;
354
355       case bmRT_RECIP_ENDPOINT:
356         switch (wValueL){
357         case FS_ENDPOINT_HALT:
358           if (plausible_endpoint (wIndexL))
359             *epcs (wIndexL) |= bmEPSTALL;
360           else
361             fx2_stall_ep0 ();
362           break;
363
364         default:
365           fx2_stall_ep0 ();
366           break;
367         }
368         break;
369
370       // --------------------------------
371
372       case RQ_SET_ADDRESS:      // handled by fx2 hardware
373       case RQ_SET_DESCR:        // not implemented
374       default:
375         fx2_stall_ep0 ();
376       }
377
378     }
379     break;
380
381   }     // bmRT_TYPE_MASK
382
383   // ack handshake phase of device request
384   EP0CS |= bmHSNAK;
385 }