2 Control transfer handler.
4 This module handles control transfers and is normally installed on the
7 Control transfers can be of the following type:
13 A callback can be installed for each of these control transfers using
14 USBRegisterRequestHandler.
15 When an OUT request arrives, data is collected in the data store provided
16 with the usbRegisterRequestHandler call. When the transfer is done, the
18 When an IN request arrives, the callback is called immediately to either
19 put the control transfer data in the data store, or to get a pointer to
20 control transfer data. The data is then packetised and sent to the host.
25 #include "usbstruct.h"
31 #define MAX_CONTROL_SIZE 128 /**< maximum total size of control transfer data */
32 #define MAX_REQ_HANDLERS 4 /**< standard, class, vendor, reserved */
34 static TSetupPacket Setup; /**< setup packet */
36 static U8 *pbData; /**< pointer to data buffer */
37 static int iResidue; /**< remaining bytes in buffer */
38 static int iLen; /**< total length of control transfer */
40 static TFnHandleRequest *apfnReqHandlers [4] = { NULL, NULL, NULL, NULL }; // Array of installed request handler callbacks
41 static U8 *apbDataStore [4] = { NULL, NULL, NULL, NULL }; // Array of installed request data pointers */
44 // Local function to handle a request by calling one of the installed
47 // In case of data going from host to device, the data is at *ppbData.
48 // In case of data going from device to host, the handler can either
49 // choose to write its data at *ppbData or update the data pointer.
51 static BOOL _HandleRequest (TSetupPacket *pSetup, int *piLen, U8 **ppbData)
53 TFnHandleRequest *pfnHandler;
56 iType = REQTYPE_GET_TYPE (pSetup->bmRequestType);
57 pfnHandler = apfnReqHandlers [iType];
59 if (pfnHandler == NULL)
62 return pfnHandler (pSetup, piLen, ppbData);
66 // Local function to stall the control endpoint
68 static void usbStallControlPipe (U8 bEPStat __attribute__ ((unused)))
70 usbHardwareEndpointStall (0x80, TRUE);
74 // Sends next chunk of data (possibly 0 bytes) to host
76 static void usbDataIn (void)
80 iChunk = MIN (MAX_PACKET_SIZE0, iResidue);
81 usbHardwareEndpointWrite (0x80, pbData, iChunk);
87 // Handles IN/OUT transfers on EP0
89 int usbHandleControlTransfer (U8 bEP, U8 bEPStat)
99 if (bEPStat & EP_STATUS_SETUP)
102 // Setup packet, reset request message state machine
104 usbHardwareEndpointRead (0x00, (U8 *) &Setup, sizeof (Setup));
107 // Defaults for data pointer and residue
109 iType = REQTYPE_GET_TYPE (Setup.bmRequestType);
110 pbData = apbDataStore [iType];
111 iResidue = Setup.wLength;
112 iLen = Setup.wLength;
114 if ((Setup.wLength == 0) || (REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST))
116 if (!_HandleRequest (&Setup, &iLen, &pbData))
118 usbStallControlPipe (bEPStat);
122 iResidue = MIN (iLen, Setup.wLength);
130 iChunk = usbHardwareEndpointRead (0x00, pbData, iResidue);
134 usbStallControlPipe (bEPStat);
143 iType = REQTYPE_GET_TYPE (Setup.bmRequestType);
144 pbData = apbDataStore [iType];
146 if (!_HandleRequest (&Setup, &iLen, &pbData))
148 usbStallControlPipe (bEPStat);
156 iChunk = usbHardwareEndpointRead (0x00, NULL, 0);
159 else if (bEP == 0x80)
167 // Registers a callback for handling requests
169 void usbRegisterRequestHandler (int iType, TFnHandleRequest *pfnHandler, U8 *pbDataStore)
171 apfnReqHandlers [iType] = pfnHandler;
172 apbDataStore [iType] = pbDataStore;