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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_LPC1768_IAR/] [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
        ASSERT(pabDescrip != NULL);
108
 
109
        bType = GET_DESC_TYPE(wTypeIndex);
110
        bIndex = GET_DESC_INDEX(wTypeIndex);
111
 
112
        pab = (unsigned char *)pabDescrip;
113
        iCurIndex = 0;
114
 
115
        while (pab[DESC_bLength] != 0) {
116
                if (pab[DESC_bDescriptorType] == bType) {
117
                        if (iCurIndex == bIndex) {
118
                                // set data pointer
119
                                *ppbData = pab;
120
                                // get length from structure
121
                                if (bType == DESC_CONFIGURATION) {
122
                                        // configuration descriptor is an exception, length is at offset 2 and 3
123
                                        *piLen =        (pab[CONF_DESC_wTotalLength]) |
124
                                                                (pab[CONF_DESC_wTotalLength + 1] << 8);
125
                                }
126
                                else {
127
                                        // normally length is at offset 0
128
                                        *piLen = pab[DESC_bLength];
129
                                }
130
                                return TRUE;
131
                        }
132
                        iCurIndex++;
133
                }
134
                // skip to next descriptor
135
                pab += pab[DESC_bLength];
136
        }
137
        // nothing found
138
        DBG("Desc %x not found!\n", wTypeIndex);
139
        return FALSE;
140
}
141
 
142
 
143
/**
144
        Configures the device according to the specified configuration index and
145
        alternate setting by parsing the installed USB descriptor list.
146
        A configuration index of 0 unconfigures the device.
147
 
148
        @param [in]             bConfigIndex    Configuration index
149
        @param [in]             bAltSetting             Alternate setting number
150
 
151
        @todo function always returns TRUE, add stricter checking?
152
 
153
        @return TRUE if successfully configured, FALSE otherwise
154
 */
155
static BOOL USBSetConfiguration(unsigned char bConfigIndex, unsigned char bAltSetting)
156
{
157
        unsigned char   *pab;
158
        unsigned char   bCurConfig, bCurAltSetting;
159
        unsigned char   bEP;
160
        unsigned short  wMaxPktSize;
161
 
162
        ASSERT(pabDescrip != NULL);
163
 
164
        if (bConfigIndex == 0) {
165
                // unconfigure device
166
                USBHwConfigDevice(FALSE);
167
        }
168
        else {
169
                // configure endpoints for this configuration/altsetting
170
                pab = (unsigned char *)pabDescrip;
171
                bCurConfig = 0xFF;
172
                bCurAltSetting = 0xFF;
173
 
174
                while (pab[DESC_bLength] != 0) {
175
 
176
                        switch (pab[DESC_bDescriptorType]) {
177
 
178
                        case DESC_CONFIGURATION:
179
                                // remember current configuration index
180
                                bCurConfig = pab[CONF_DESC_bConfigurationValue];
181
                                break;
182
 
183
                        case DESC_INTERFACE:
184
                                // remember current alternate setting
185
                                bCurAltSetting = pab[INTF_DESC_bAlternateSetting];
186
                                break;
187
 
188
                        case DESC_ENDPOINT:
189
                                if ((bCurConfig == bConfigIndex) &&
190
                                        (bCurAltSetting == bAltSetting)) {
191
                                        // endpoint found for desired config and alternate setting
192
                                        bEP = pab[ENDP_DESC_bEndpointAddress];
193
                                        wMaxPktSize =   (pab[ENDP_DESC_wMaxPacketSize]) |
194
                                                                        (pab[ENDP_DESC_wMaxPacketSize + 1] << 8);
195
                                        // configure endpoint
196
                                        USBHwEPConfig(bEP, wMaxPktSize);
197
                                }
198
                                break;
199
 
200
                        default:
201
                                break;
202
                        }
203
                        // skip to next descriptor
204
                        pab += pab[DESC_bLength];
205
                }
206
 
207
                // configure device
208
                USBHwConfigDevice(TRUE);
209
        }
210
 
211
        return TRUE;
212
}
213
 
214
 
215
/**
216
        Local function to handle a standard device request
217
 
218
        @param [in]             pSetup          The setup packet
219
        @param [in,out] *piLen          Pointer to data length
220
        @param [in,out] ppbData         Data buffer.
221
 
222
        @return TRUE if the request was handled successfully
223
 */
224
static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
225
{
226
        unsigned char   *pbData = *ppbData;
227
 
228
        switch (pSetup->bRequest) {
229
 
230
        case REQ_GET_STATUS:
231
                // bit 0: self-powered
232
                // bit 1: remote wakeup = not supported
233
                pbData[0] = 0;
234
                pbData[1] = 0;
235
                *piLen = 2;
236
                break;
237
 
238
        case REQ_SET_ADDRESS:
239
                USBHwSetAddress(pSetup->wValue);
240
                break;
241
 
242
        case REQ_GET_DESCRIPTOR:
243
                DBG("D%x", pSetup->wValue);
244
                return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData);
245
 
246
        case REQ_GET_CONFIGURATION:
247
                // indicate if we are configured
248
                pbData[0] = bConfiguration;
249
                *piLen = 1;
250
                break;
251
 
252
        case REQ_SET_CONFIGURATION:
253
                if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) {
254
                        DBG("USBSetConfiguration failed!\n");
255
                        return FALSE;
256
                }
257
                // configuration successful, update current configuration
258
                bConfiguration = pSetup->wValue & 0xFF;
259
                break;
260
 
261
        case REQ_CLEAR_FEATURE:
262
        case REQ_SET_FEATURE:
263
                if (pSetup->wValue == FEA_REMOTE_WAKEUP) {
264
                        // put DEVICE_REMOTE_WAKEUP code here
265
                }
266
                if (pSetup->wValue == FEA_TEST_MODE) {
267
                        // put TEST_MODE code here
268
                }
269
                return FALSE;
270
 
271
        case REQ_SET_DESCRIPTOR:
272
                DBG("Device req %d not implemented\n", pSetup->bRequest);
273
                return FALSE;
274
 
275
        default:
276
                DBG("Illegal device req %d\n", pSetup->bRequest);
277
                return FALSE;
278
        }
279
 
280
        return TRUE;
281
}
282
 
283
 
284
/**
285
        Local function to handle a standard interface request
286
 
287
        @param [in]             pSetup          The setup packet
288
        @param [in,out] *piLen          Pointer to data length
289
        @param [in]             ppbData         Data buffer.
290
 
291
        @return TRUE if the request was handled successfully
292
 */
293
static BOOL HandleStdInterfaceReq(TSetupPacket  *pSetup, int *piLen, unsigned char **ppbData)
294
{
295
        unsigned char   *pbData = *ppbData;
296
 
297
        switch (pSetup->bRequest) {
298
 
299
        case REQ_GET_STATUS:
300
                // no bits specified
301
                pbData[0] = 0;
302
                pbData[1] = 0;
303
                *piLen = 2;
304
                break;
305
 
306
        case REQ_CLEAR_FEATURE:
307
        case REQ_SET_FEATURE:
308
                // not defined for interface
309
                return FALSE;
310
 
311
        case REQ_GET_INTERFACE: // TODO use bNumInterfaces
312
        // there is only one interface, return n-1 (= 0)
313
                pbData[0] = 0;
314
                *piLen = 1;
315
                break;
316
 
317
        case REQ_SET_INTERFACE: // TODO use bNumInterfaces
318
                // there is only one interface (= 0)
319
                if (pSetup->wValue != 0) {
320
                        return FALSE;
321
                }
322
                *piLen = 0;
323
                break;
324
 
325
        default:
326
                DBG("Illegal interface req %d\n", pSetup->bRequest);
327
                return FALSE;
328
        }
329
 
330
        return TRUE;
331
}
332
 
333
 
334
/**
335
        Local function to handle a standard endpoint request
336
 
337
        @param [in]             pSetup          The setup packet
338
        @param [in,out] *piLen          Pointer to data length
339
        @param [in]             ppbData         Data buffer.
340
 
341
        @return TRUE if the request was handled successfully
342
 */
343
static BOOL HandleStdEndPointReq(TSetupPacket   *pSetup, int *piLen, unsigned char **ppbData)
344
{
345
        unsigned char   *pbData = *ppbData;
346
 
347
        switch (pSetup->bRequest) {
348
        case REQ_GET_STATUS:
349
                // bit 0 = endpointed halted or not
350
                pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0;
351
                pbData[1] = 0;
352
                *piLen = 2;
353
                break;
354
 
355
        case REQ_CLEAR_FEATURE:
356
                if (pSetup->wValue == FEA_ENDPOINT_HALT) {
357
                        // clear HALT by unstalling
358
                        USBHwEPStall(pSetup->wIndex, FALSE);
359
                        break;
360
                }
361
                // only ENDPOINT_HALT defined for endpoints
362
                return FALSE;
363
 
364
        case REQ_SET_FEATURE:
365
                if (pSetup->wValue == FEA_ENDPOINT_HALT) {
366
                        // set HALT by stalling
367
                        USBHwEPStall(pSetup->wIndex, TRUE);
368
                        break;
369
                }
370
                // only ENDPOINT_HALT defined for endpoints
371
                return FALSE;
372
 
373
        case REQ_SYNCH_FRAME:
374
                DBG("EP req %d not implemented\n", pSetup->bRequest);
375
                return FALSE;
376
 
377
        default:
378
                DBG("Illegal EP req %d\n", pSetup->bRequest);
379
                return FALSE;
380
        }
381
 
382
        return TRUE;
383
}
384
 
385
 
386
/**
387
        Default handler for standard ('chapter 9') requests
388
 
389
        If a custom request handler was installed, this handler is called first.
390
 
391
        @param [in]             pSetup          The setup packet
392
        @param [in,out] *piLen          Pointer to data length
393
        @param [in]             ppbData         Data buffer.
394
 
395
        @return TRUE if the request was handled successfully
396
 */
397
BOOL USBHandleStandardRequest(TSetupPacket      *pSetup, int *piLen, unsigned char **ppbData)
398
{
399
        // try the custom request handler first
400
        if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) {
401
                return TRUE;
402
        }
403
 
404
        switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) {
405
        case REQTYPE_RECIP_DEVICE:              return HandleStdDeviceReq(pSetup, piLen, ppbData);
406
        case REQTYPE_RECIP_INTERFACE:   return HandleStdInterfaceReq(pSetup, piLen, ppbData);
407
        case REQTYPE_RECIP_ENDPOINT:    return HandleStdEndPointReq(pSetup, piLen, ppbData);
408
        default:                                                return FALSE;
409
        }
410
}
411
 
412
 
413
/**
414
        Registers a callback for custom device requests
415
 
416
        In USBHandleStandardRequest, the custom request handler gets a first
417
        chance at handling the request before it is handed over to the 'chapter 9'
418
        request handler.
419
 
420
        This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR
421
        request is sent to an interface, which is not covered by the 'chapter 9'
422
        specification.
423
 
424
        @param [in]     pfnHandler      Callback function pointer
425
 */
426
void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler)
427
{
428
        pfnHandleCustomReq = pfnHandler;
429
}
430
 

powered by: WebSVN 2.1.0

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