Statistics
| Branch: | Tag: | Revision:

root / firmware / fx2 / lib / usb_common.c @ 70eae1d2

History | View | Annotate | Download (8.1 kB)

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 3, 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
        break;
283

    
284
      // --------------------------------
285

    
286
      case RQ_SYNCH_FRAME:        // not implemented
287
      default:
288
        fx2_stall_ep0 ();
289
        break;
290
      }
291
    }
292

    
293
    else {
294

    
295
      ////////////////////////////////////
296
      //    handle the OUT requests
297
      ////////////////////////////////////
298

    
299
      switch (bRequest){
300

    
301
      case RQ_SET_CONFIG:
302
        _usb_config = wValueL;                // FIXME app should handle
303
        break;
304

    
305
      case RQ_SET_INTERFACE:
306
        _usb_alt_setting = wValueL;        // FIXME app should handle
307
        break;
308

    
309
      // --------------------------------
310

    
311
      case RQ_CLEAR_FEATURE:
312
        switch (bRequestType & bmRT_RECIP_MASK){
313

    
314
        case bmRT_RECIP_DEVICE:
315
          switch (wValueL){
316
          case FS_DEV_REMOTE_WAKEUP:
317
          default:
318
            fx2_stall_ep0 ();
319
          }
320
          break;
321

    
322
        case bmRT_RECIP_ENDPOINT:
323
          if (wValueL == FS_ENDPOINT_HALT && plausible_endpoint (wIndexL)){
324
            *epcs (wIndexL) &= ~bmEPSTALL;
325
            fx2_reset_data_toggle (wIndexL);
326
          }
327
          else
328
            fx2_stall_ep0 ();
329
          break;
330

    
331
        default:
332
          fx2_stall_ep0 ();
333
          break;
334
        }
335
        break;
336

    
337
      // --------------------------------
338

    
339
      case RQ_SET_FEATURE:
340
        switch (bRequestType & bmRT_RECIP_MASK){
341

    
342
        case bmRT_RECIP_DEVICE:
343
          switch (wValueL){
344
          case FS_TEST_MODE:
345
            // hardware handles this after we complete SETUP phase handshake
346
            break;
347

    
348
          case FS_DEV_REMOTE_WAKEUP:
349
          default:
350
            fx2_stall_ep0 ();
351
            break;
352
          }
353
        }
354
        break;
355

    
356
      case bmRT_RECIP_ENDPOINT:
357
        switch (wValueL){
358
        case FS_ENDPOINT_HALT:
359
          if (plausible_endpoint (wIndexL))
360
            *epcs (wIndexL) |= bmEPSTALL;
361
          else
362
            fx2_stall_ep0 ();
363
          break;
364

    
365
        default:
366
          fx2_stall_ep0 ();
367
          break;
368
        }
369
        break;
370

    
371
      // --------------------------------
372

    
373
      case RQ_SET_ADDRESS:        // handled by fx2 hardware
374
      case RQ_SET_DESCR:        // not implemented
375
      default:
376
        fx2_stall_ep0 ();
377
      }
378

    
379
    }
380
    break;
381

    
382
  }        // bmRT_TYPE_MASK
383

    
384
  // ack handshake phase of device request
385
  EP0CS |= bmHSNAK;
386
}