2 Standard request handler.
4 This modules handles the 'chapter 9' processing, specifically the
5 standard device requests in table 9-3 from the universal serial bus
6 specification revision 2.0
8 Specific types of devices may specify additional requests (for example
9 HID devices add a GET_DESCRIPTOR request for interfaces), but they
10 will not be part of this module.
12 @todo some requests have to return a request error if device not configured:
13 @todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME
14 @todo this applies to the following if endpoint != 0:
15 @todo SET_FEATURE, GET_FEATURE
18 #include "usbstruct.h"
21 #define MAX_DESC_HANDLERS 4 /**< device, interface, endpoint, other */
25 // General descriptor field offsets
27 #define DESC_bLength 0 /**< length offset */
28 #define DESC_bDescriptorType 1 /**< descriptor type offset */
31 // Config descriptor field offsets
33 #define CONF_DESC_wTotalLength 2 /**< total length offset */
34 #define CONF_DESC_bConfigurationValue 5 /**< configuration value offset */
35 #define CONF_DESC_bmAttributes 7 /**< configuration characteristics */
38 // Interface descriptor field offsets
40 #define INTF_DESC_bAlternateSetting 3 /**< alternate setting offset */
43 // Endpoint descriptor field offsets
45 #define ENDP_DESC_bEndpointAddress 2 /**< endpoint address offset */
46 #define ENDP_DESC_wMaxPacketSize 4 /**< maximum packet size offset */
49 static U8 bConfiguration = 0; /** Currently selected configuration */
50 static TFnHandleRequest *pfnHandleCustomReq = NULL; /** Installed custom request handler */
51 static const U8 *pabDescrip = NULL; /** Pointer to registered descriptors */
55 // Registers a pointer to a descriptor block containing all descriptors for the device.
57 void usbRegisterDescriptors (const U8 *pabDescriptors)
59 pabDescrip = pabDescriptors;
63 // Parses the list of installed USB descriptors and attempts to find the specified USB descriptor.
65 BOOL usbGetDescriptor (U16 wTypeIndex, U16 wLangID __attribute__ ((unused)), int *piLen, U8 **ppbData)
71 bType = GET_DESC_TYPE (wTypeIndex);
72 bIndex = GET_DESC_INDEX (wTypeIndex);
74 pab = (U8 *)pabDescrip;
77 while (pab [DESC_bLength] != 0)
79 if (pab [DESC_bDescriptorType] == bType)
81 if (iCurIndex == bIndex)
85 if (bType == DESC_CONFIGURATION)
86 *piLen = (pab [CONF_DESC_wTotalLength]) | (pab [CONF_DESC_wTotalLength + 1] << 8);
88 *piLen = pab [DESC_bLength];
96 pab += pab [DESC_bLength];
103 // Configures the device according to the specified configuration index and
104 // alternate setting by parsing the installed USB descriptor list.
105 // A configuration index of 0 unconfigures the device.
107 static BOOL usbSetConfiguration (U8 bConfigIndex, U8 bAltSetting)
110 U8 bCurConfig, bCurAltSetting;
114 if (bConfigIndex == 0)
115 usbHardwareConfigDevice(FALSE);
118 pab = (U8 *) pabDescrip;
120 bCurAltSetting = 0xFF;
122 while (pab [DESC_bLength] != 0)
124 switch (pab [DESC_bDescriptorType])
126 case DESC_CONFIGURATION :
128 bCurConfig = pab [CONF_DESC_bConfigurationValue];
132 case DESC_INTERFACE :
134 bCurAltSetting = pab [INTF_DESC_bAlternateSetting];
140 if ((bCurConfig == bConfigIndex) && (bCurAltSetting == bAltSetting))
142 bEP = pab [ENDP_DESC_bEndpointAddress];
143 wMaxPktSize = (pab [ENDP_DESC_wMaxPacketSize]) | (pab [ENDP_DESC_wMaxPacketSize + 1] << 8);
144 usbHardwareEndpointConfig (bEP, wMaxPktSize);
153 pab += pab [DESC_bLength];
156 usbHardwareConfigDevice (TRUE);
163 // Local function to handle a standard device request
165 static BOOL usbHandleStdDeviceReq (TSetupPacket *pSetup, int *piLen, U8 **ppbData)
167 U8 *pbData = *ppbData;
169 switch (pSetup->bRequest)
171 case REQ_GET_STATUS :
179 case REQ_SET_ADDRESS :
181 usbHardwareSetAddress (pSetup->wValue);
185 case REQ_GET_DESCRIPTOR :
186 return usbGetDescriptor (pSetup->wValue, pSetup->wIndex, piLen, ppbData);
188 case REQ_GET_CONFIGURATION :
190 pbData [0] = bConfiguration;
195 case REQ_SET_CONFIGURATION :
197 if (!usbSetConfiguration(pSetup->wValue & 0xFF, 0))
200 bConfiguration = pSetup->wValue & 0xFF;
204 case REQ_CLEAR_FEATURE :
205 case REQ_SET_FEATURE :
207 if (pSetup->wValue == FEA_REMOTE_WAKEUP) {
209 if (pSetup->wValue == FEA_TEST_MODE) {
214 case REQ_SET_DESCRIPTOR :
225 // Local function to handle a standard interface request
227 static BOOL usbHandleStdInterfaceReq (TSetupPacket *pSetup, int *piLen, U8 **ppbData)
229 U8 *pbData = *ppbData;
231 switch (pSetup->bRequest)
233 case REQ_GET_STATUS :
241 case REQ_CLEAR_FEATURE :
242 case REQ_SET_FEATURE :
245 case REQ_GET_INTERFACE :
252 case REQ_SET_INTERFACE :
254 if (pSetup->wValue != 0)
269 // Local function to handle a standard endpoint request
271 static BOOL usbHandleStdEndPointReq (TSetupPacket *pSetup, int *piLen, U8 **ppbData)
273 U8 *pbData = *ppbData;
275 switch (pSetup->bRequest)
277 case REQ_GET_STATUS :
279 pbData [0] = usbHardwareEndpointIsStalled (pSetup->wIndex) ? 1 : 0;
285 case REQ_CLEAR_FEATURE :
287 if (pSetup->wValue == FEA_ENDPOINT_HALT)
289 usbHardwareEndpointStall(pSetup->wIndex, FALSE);
295 case REQ_SET_FEATURE :
297 if (pSetup->wValue == FEA_ENDPOINT_HALT)
299 usbHardwareEndpointStall(pSetup->wIndex, TRUE);
305 case REQ_SYNCH_FRAME :
317 // Default handler for standard ('chapter 9') requests
318 // If a custom request handler was installed, this handler is called first.
320 BOOL usbHandleStandardRequest (TSetupPacket *pSetup, int *piLen, U8 **ppbData)
322 if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq (pSetup, piLen, ppbData))
325 switch (REQTYPE_GET_RECIP(pSetup->bmRequestType))
327 case REQTYPE_RECIP_DEVICE : return usbHandleStdDeviceReq (pSetup, piLen, ppbData);
328 case REQTYPE_RECIP_INTERFACE : return usbHandleStdInterfaceReq (pSetup, piLen, ppbData);
329 case REQTYPE_RECIP_ENDPOINT : return usbHandleStdEndPointReq (pSetup, piLen, ppbData);
330 default : return FALSE;
335 // Registers a callback for custom device requests
337 // In usbHandleStandardRequest, the custom request handler gets a first
338 // chance at handling the request before it is handed over to the 'chapter 9'
341 // This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR
342 // request is sent to an interface, which is not covered by the 'chapter 9'
345 void usbRegisterCustomReqHandler (TFnHandleRequest *pfnHandler)
347 pfnHandleCustomReq = pfnHandler;