OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_LPC1768_GCC_Rowley/] [LPCUSB/] [usbstdreq.c] - Blame information for rev 581

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 581 jeremybenn
/*
2
        LPCUSB, an USB device driver for LPC microcontrollers
3
        Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
4
 
5
        Redistribution and use in source and binary forms, with or without
6
        modification, are permitted provided that the following conditions are met:
7
 
8
        1. Redistributions of source code must retain the above copyright
9
           notice, this list of conditions and the following disclaimer.
10
        2. Redistributions in binary form must reproduce the above copyright
11
           notice, this list of conditions and the following disclaimer in the
12
           documentation and/or other materials provided with the distribution.
13
        3. The name of the author may not be used to endorse or promote products
14
           derived from this software without specific prior written permission.
15
 
16
        THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
        IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
        OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
        IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
        INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
        NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
        DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
        THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
        (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
        THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*/
27
 
28
 
29
/** @file
30
        Standard request handler.
31
 
32
        This modules handles the 'chapter 9' processing, specifically the
33
        standard device requests in table 9-3 from the universal serial bus
34
        specification revision 2.0
35
 
36
        Specific types of devices may specify additional requests (for example
37
        HID devices add a GET_DESCRIPTOR request for interfaces), but they
38
        will not be part of this module.
39
 
40
        @todo some requests have to return a request error if device not configured:
41
        @todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME
42
        @todo this applies to the following if endpoint != 0:
43
        @todo SET_FEATURE, GET_FEATURE
44
*/
45
 
46
#include "usbdebug.h"
47
#include "usbstruct.h"
48
#include "usbapi.h"
49
 
50
#define MAX_DESC_HANDLERS       4               /**< device, interface, endpoint, other */
51
 
52
 
53
/* general descriptor field offsets */
54
#define DESC_bLength                                    0        /**< length offset */
55
#define DESC_bDescriptorType                    1       /**< descriptor type offset */
56
 
57
/* config descriptor field offsets */
58
#define CONF_DESC_wTotalLength                  2       /**< total length offset */
59
#define CONF_DESC_bConfigurationValue   5       /**< configuration value offset */
60
#define CONF_DESC_bmAttributes                  7       /**< configuration characteristics */
61
 
62
/* interface descriptor field offsets */
63
#define INTF_DESC_bAlternateSetting             3       /**< alternate setting offset */
64
 
65
/* endpoint descriptor field offsets */
66
#define ENDP_DESC_bEndpointAddress              2       /**< endpoint address offset */
67
#define ENDP_DESC_wMaxPacketSize                4       /**< maximum packet size offset */
68
 
69
 
70
/** Currently selected configuration */
71
static unsigned char                            bConfiguration = 0;
72
/** Installed custom request handler */
73
static TFnHandleRequest *pfnHandleCustomReq = NULL;
74
/** Pointer to registered descriptors */
75
static const unsigned char                      *pabDescrip = NULL;
76
 
77
 
78
/**
79
        Registers a pointer to a descriptor block containing all descriptors
80
        for the device.
81
 
82
        @param [in]     pabDescriptors  The descriptor byte array
83
 */
84
void USBRegisterDescriptors(const unsigned char *pabDescriptors)
85
{
86
        pabDescrip = pabDescriptors;
87
}
88
 
89
 
90
/**
91
        Parses the list of installed USB descriptors and attempts to find
92
        the specified USB descriptor.
93
 
94
        @param [in]             wTypeIndex      Type and index of the descriptor
95
        @param [in]             wLangID         Language ID of the descriptor (currently unused)
96
        @param [out]    *piLen          Descriptor length
97
        @param [out]    *ppbData        Descriptor data
98
 
99
        @return TRUE if the descriptor was found, FALSE otherwise
100
 */
101
BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData)
102
{
103
        unsigned char   bType, bIndex;
104
        unsigned char   *pab;
105
        int iCurIndex;
106
 
107
        ( void ) wLangID;
108
        ASSERT(pabDescrip != NULL);
109
 
110
        bType = GET_DESC_TYPE(wTypeIndex);
111
        bIndex = GET_DESC_INDEX(wTypeIndex);
112
 
113
        pab = (unsigned char *)pabDescrip;
114
        iCurIndex = 0;
115
 
116
        while (pab[DESC_bLength] != 0) {
117
                if (pab[DESC_bDescriptorType] == bType) {
118
                        if (iCurIndex == bIndex) {
119
                                // set data pointer
120
                                *ppbData = pab;
121
                                // get length from structure
122
                                if (bType == DESC_CONFIGURATION) {
123
                                        // configuration descriptor is an exception, length is at offset 2 and 3
124
                                        *piLen =        (pab[CONF_DESC_wTotalLength]) |
125
                                                                (pab[CONF_DESC_wTotalLength + 1] << 8);
126
                                }
127
                                else {
128
                                        // normally length is at offset 0
129
                                        *piLen = pab[DESC_bLength];
130
                                }
131
                                return TRUE;
132
                        }
133
                        iCurIndex++;
134
                }
135
                // skip to next descriptor
136
                pab += pab[DESC_bLength];
137
        }
138
        // nothing found
139
        DBG("Desc %x not found!\n", wTypeIndex);
140
        return FALSE;
141
}
142
 
143
 
144
/**
145
        Configures the device according to the specified configuration index and
146
        alternate setting by parsing the installed USB descriptor list.
147
        A configuration index of 0 unconfigures the device.
148
 
149
        @param [in]             bConfigIndex    Configuration index
150
        @param [in]             bAltSetting             Alternate setting number
151
 
152
        @todo function always returns TRUE, add stricter checking?
153
 
154
        @return TRUE if successfully configured, FALSE otherwise
155
 */
156
static BOOL USBSetConfiguration(unsigned char bConfigIndex, unsigned char bAltSetting)
157
{
158
        unsigned char   *pab;
159
        unsigned char   bCurConfig, bCurAltSetting;
160
        unsigned char   bEP;
161
        unsigned short  wMaxPktSize;
162
 
163
        ASSERT(pabDescrip != NULL);
164
 
165
        if (bConfigIndex == 0) {
166
                // unconfigure device
167
                USBHwConfigDevice(FALSE);
168
        }
169
        else {
170
                // configure endpoints for this configuration/altsetting
171
                pab = (unsigned char *)pabDescrip;
172
                bCurConfig = 0xFF;
173
                bCurAltSetting = 0xFF;
174
 
175
                while (pab[DESC_bLength] != 0) {
176
 
177
                        switch (pab[DESC_bDescriptorType]) {
178
 
179
                        case DESC_CONFIGURATION:
180
                                // remember current configuration index
181
                                bCurConfig = pab[CONF_DESC_bConfigurationValue];
182
                                break;
183
 
184
                        case DESC_INTERFACE:
185
                                // remember current alternate setting
186
                                bCurAltSetting = pab[INTF_DESC_bAlternateSetting];
187
                                break;
188
 
189
                        case DESC_ENDPOINT:
190
                                if ((bCurConfig == bConfigIndex) &&
191
                                        (bCurAltSetting == bAltSetting)) {
192
                                        // endpoint found for desired config and alternate setting
193
                                        bEP = pab[ENDP_DESC_bEndpointAddress];
194
                                        wMaxPktSize =   (pab[ENDP_DESC_wMaxPacketSize]) |
195
                                                                        (pab[ENDP_DESC_wMaxPacketSize + 1] << 8);
196
                                        // configure endpoint
197
                                        USBHwEPConfig(bEP, wMaxPktSize);
198
                                }
199
                                break;
200
 
201
                        default:
202
                                break;
203
                        }
204
                        // skip to next descriptor
205
                        pab += pab[DESC_bLength];
206
                }
207
 
208
                // configure device
209
                USBHwConfigDevice(TRUE);
210
        }
211
 
212
        return TRUE;
213
}
214
 
215
 
216
/**
217
        Local function to handle a standard device request
218
 
219
        @param [in]             pSetup          The setup packet
220
        @param [in,out] *piLen          Pointer to data length
221
        @param [in,out] ppbData         Data buffer.
222
 
223
        @return TRUE if the request was handled successfully
224
 */
225
static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
226
{
227
        unsigned char   *pbData = *ppbData;
228
 
229
        switch (pSetup->bRequest) {
230
 
231
        case REQ_GET_STATUS:
232
                // bit 0: self-powered
233
                // bit 1: remote wakeup = not supported
234
                pbData[0] = 0;
235
                pbData[1] = 0;
236
                *piLen = 2;
237
                break;
238
 
239
        case REQ_SET_ADDRESS:
240
                USBHwSetAddress(pSetup->wValue);
241
                break;
242
 
243
        case REQ_GET_DESCRIPTOR:
244
                DBG("D%x", pSetup->wValue);
245
                return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData);
246
 
247
        case REQ_GET_CONFIGURATION:
248
                // indicate if we are configured
249
                pbData[0] = bConfiguration;
250
                *piLen = 1;
251
                break;
252
 
253
        case REQ_SET_CONFIGURATION:
254
                if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) {
255
                        DBG("USBSetConfiguration failed!\n");
256
                        return FALSE;
257
                }
258
                // configuration successful, update current configuration
259
                bConfiguration = pSetup->wValue & 0xFF;
260
                break;
261
 
262
        case REQ_CLEAR_FEATURE:
263
        case REQ_SET_FEATURE:
264
                if (pSetup->wValue == FEA_REMOTE_WAKEUP) {
265
                        // put DEVICE_REMOTE_WAKEUP code here
266
                }
267
                if (pSetup->wValue == FEA_TEST_MODE) {
268
                        // put TEST_MODE code here
269
                }
270
                return FALSE;
271
 
272
        case REQ_SET_DESCRIPTOR:
273
                DBG("Device req %d not implemented\n", pSetup->bRequest);
274
                return FALSE;
275
 
276
        default:
277
                DBG("Illegal device req %d\n", pSetup->bRequest);
278
                return FALSE;
279
        }
280
 
281
        return TRUE;
282
}
283
 
284
 
285
/**
286
        Local function to handle a standard interface request
287
 
288
        @param [in]             pSetup          The setup packet
289
        @param [in,out] *piLen          Pointer to data length
290
        @param [in]             ppbData         Data buffer.
291
 
292
        @return TRUE if the request was handled successfully
293
 */
294
static BOOL HandleStdInterfaceReq(TSetupPacket  *pSetup, int *piLen, unsigned char **ppbData)
295
{
296
        unsigned char   *pbData = *ppbData;
297
 
298
        switch (pSetup->bRequest) {
299
 
300
        case REQ_GET_STATUS:
301
                // no bits specified
302
                pbData[0] = 0;
303
                pbData[1] = 0;
304
                *piLen = 2;
305
                break;
306
 
307
        case REQ_CLEAR_FEATURE:
308
        case REQ_SET_FEATURE:
309
                // not defined for interface
310
                return FALSE;
311
 
312
        case REQ_GET_INTERFACE: // TODO use bNumInterfaces
313
        // there is only one interface, return n-1 (= 0)
314
                pbData[0] = 0;
315
                *piLen = 1;
316
                break;
317
 
318
        case REQ_SET_INTERFACE: // TODO use bNumInterfaces
319
                // there is only one interface (= 0)
320
                if (pSetup->wValue != 0) {
321
                        return FALSE;
322
                }
323
                *piLen = 0;
324
                break;
325
 
326
        default:
327
                DBG("Illegal interface req %d\n", pSetup->bRequest);
328
                return FALSE;
329
        }
330
 
331
        return TRUE;
332
}
333
 
334
 
335
/**
336
        Local function to handle a standard endpoint request
337
 
338
        @param [in]             pSetup          The setup packet
339
        @param [in,out] *piLen          Pointer to data length
340
        @param [in]             ppbData         Data buffer.
341
 
342
        @return TRUE if the request was handled successfully
343
 */
344
static BOOL HandleStdEndPointReq(TSetupPacket   *pSetup, int *piLen, unsigned char **ppbData)
345
{
346
        unsigned char   *pbData = *ppbData;
347
 
348
        switch (pSetup->bRequest) {
349
        case REQ_GET_STATUS:
350
                // bit 0 = endpointed halted or not
351
                pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0;
352
                pbData[1] = 0;
353
                *piLen = 2;
354
                break;
355
 
356
        case REQ_CLEAR_FEATURE:
357
                if (pSetup->wValue == FEA_ENDPOINT_HALT) {
358
                        // clear HALT by unstalling
359
                        USBHwEPStall(pSetup->wIndex, FALSE);
360
                        break;
361
                }
362
                // only ENDPOINT_HALT defined for endpoints
363
                return FALSE;
364
 
365
        case REQ_SET_FEATURE:
366
                if (pSetup->wValue == FEA_ENDPOINT_HALT) {
367
                        // set HALT by stalling
368
                        USBHwEPStall(pSetup->wIndex, TRUE);
369
                        break;
370
                }
371
                // only ENDPOINT_HALT defined for endpoints
372
                return FALSE;
373
 
374
        case REQ_SYNCH_FRAME:
375
                DBG("EP req %d not implemented\n", pSetup->bRequest);
376
                return FALSE;
377
 
378
        default:
379
                DBG("Illegal EP req %d\n", pSetup->bRequest);
380
                return FALSE;
381
        }
382
 
383
        return TRUE;
384
}
385
 
386
 
387
/**
388
        Default handler for standard ('chapter 9') requests
389
 
390
        If a custom request handler was installed, this handler is called first.
391
 
392
        @param [in]             pSetup          The setup packet
393
        @param [in,out] *piLen          Pointer to data length
394
        @param [in]             ppbData         Data buffer.
395
 
396
        @return TRUE if the request was handled successfully
397
 */
398
BOOL USBHandleStandardRequest(TSetupPacket      *pSetup, int *piLen, unsigned char **ppbData)
399
{
400
        // try the custom request handler first
401
        if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) {
402
                return TRUE;
403
        }
404
 
405
        switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) {
406
        case REQTYPE_RECIP_DEVICE:              return HandleStdDeviceReq(pSetup, piLen, ppbData);
407
        case REQTYPE_RECIP_INTERFACE:   return HandleStdInterfaceReq(pSetup, piLen, ppbData);
408
        case REQTYPE_RECIP_ENDPOINT:    return HandleStdEndPointReq(pSetup, piLen, ppbData);
409
        default:                                                return FALSE;
410
        }
411
}
412
 
413
 
414
/**
415
        Registers a callback for custom device requests
416
 
417
        In USBHandleStandardRequest, the custom request handler gets a first
418
        chance at handling the request before it is handed over to the 'chapter 9'
419
        request handler.
420
 
421
        This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR
422
        request is sent to an interface, which is not covered by the 'chapter 9'
423
        specification.
424
 
425
        @param [in]     pfnHandler      Callback function pointer
426
 */
427
void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler)
428
{
429
        pfnHandleCustomReq = pfnHandler;
430
}
431
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.