changing circuitry to disable RTC, update initialization to match
[fw/openalt] / usb / usbstdreq.c
1 /** @file
2   Standard request handler.
3   
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
7   
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.
11
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 
16 */
17
18 #include "usbstruct.h"
19 #include "usbapi.h"
20
21 #define MAX_DESC_HANDLERS 4   /**< device, interface, endpoint, other */
22
23
24 //
25 //  General descriptor field offsets 
26 //
27 #define DESC_bLength          0 /**< length offset */
28 #define DESC_bDescriptorType  1 /**< descriptor type offset */  
29
30 //
31 //  Config descriptor field offsets 
32 //
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 */
36
37 //
38 //  Interface descriptor field offsets 
39 //
40 #define INTF_DESC_bAlternateSetting   3 /**< alternate setting offset */
41
42 //
43 //  Endpoint descriptor field offsets 
44 //
45 #define ENDP_DESC_bEndpointAddress    2 /**< endpoint address offset */
46 #define ENDP_DESC_wMaxPacketSize      4 /**< maximum packet size offset */
47
48
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 */
52
53
54 //
55 //  Registers a pointer to a descriptor block containing all descriptors for the device.
56 //
57 void usbRegisterDescriptors (const U8 *pabDescriptors)
58 {
59   pabDescrip = pabDescriptors;
60 }
61
62 //
63 //  Parses the list of installed USB descriptors and attempts to find the specified USB descriptor.
64 //
65 BOOL usbGetDescriptor (U16 wTypeIndex, U16 wLangID __attribute__ ((unused)), int *piLen, U8 **ppbData)
66 {
67   U8  bType, bIndex;
68   U8  *pab;
69   int iCurIndex;
70
71   bType = GET_DESC_TYPE (wTypeIndex);
72   bIndex = GET_DESC_INDEX (wTypeIndex);
73
74   pab = (U8 *)pabDescrip;
75   iCurIndex = 0;
76
77   while (pab [DESC_bLength] != 0) 
78   {
79     if (pab [DESC_bDescriptorType] == bType) 
80     {
81       if (iCurIndex == bIndex) 
82       {
83         *ppbData = pab;
84
85         if (bType == DESC_CONFIGURATION) 
86           *piLen =  (pab [CONF_DESC_wTotalLength]) | (pab [CONF_DESC_wTotalLength + 1] << 8);
87         else 
88           *piLen = pab [DESC_bLength];
89
90         return TRUE;
91       }
92
93       iCurIndex++;
94     }
95
96     pab += pab [DESC_bLength];
97   }
98
99   return FALSE;
100 }
101
102 //
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.
106 //
107 static BOOL usbSetConfiguration (U8 bConfigIndex, U8 bAltSetting)
108 {
109   U8  *pab;
110   U8  bCurConfig, bCurAltSetting;
111   U8  bEP;
112   U16 wMaxPktSize;
113
114   if (bConfigIndex == 0) 
115     usbHardwareConfigDevice(FALSE);
116   else 
117   {
118     pab = (U8 *) pabDescrip;
119     bCurConfig = 0xFF;
120     bCurAltSetting = 0xFF;
121
122     while (pab [DESC_bLength] != 0) 
123     {
124       switch (pab [DESC_bDescriptorType]) 
125       {
126         case DESC_CONFIGURATION :
127           {
128             bCurConfig = pab [CONF_DESC_bConfigurationValue];
129           }
130           break;
131
132         case DESC_INTERFACE :
133           {
134             bCurAltSetting = pab [INTF_DESC_bAlternateSetting];
135           }
136           break;
137
138         case DESC_ENDPOINT :
139           {
140             if ((bCurConfig == bConfigIndex) && (bCurAltSetting == bAltSetting)) 
141             {
142               bEP = pab [ENDP_DESC_bEndpointAddress];
143               wMaxPktSize = (pab [ENDP_DESC_wMaxPacketSize]) | (pab [ENDP_DESC_wMaxPacketSize + 1] << 8);
144               usbHardwareEndpointConfig (bEP, wMaxPktSize);
145             }
146           }
147           break;
148
149         default :
150           break;
151       }
152
153       pab += pab [DESC_bLength];
154     }
155
156     usbHardwareConfigDevice (TRUE);
157   }
158
159   return TRUE;
160 }
161
162 //
163 //  Local function to handle a standard device request
164 //
165 static BOOL usbHandleStdDeviceReq (TSetupPacket *pSetup, int *piLen, U8 **ppbData)
166 {
167   U8  *pbData = *ppbData;
168
169   switch (pSetup->bRequest) 
170   {
171     case REQ_GET_STATUS :
172       {
173         pbData [0] = 0;
174         pbData [1] = 0;
175         *piLen = 2;
176       }
177       break;
178
179     case REQ_SET_ADDRESS :
180       {
181         usbHardwareSetAddress (pSetup->wValue);
182       }
183       break;
184
185     case REQ_GET_DESCRIPTOR :
186       return usbGetDescriptor (pSetup->wValue, pSetup->wIndex, piLen, ppbData);
187
188     case REQ_GET_CONFIGURATION :
189       {
190         pbData [0] = bConfiguration;
191         *piLen = 1;
192       }
193       break;
194
195     case REQ_SET_CONFIGURATION :
196       {
197         if (!usbSetConfiguration(pSetup->wValue & 0xFF, 0))
198           return FALSE;
199
200         bConfiguration = pSetup->wValue & 0xFF; 
201       }
202       break;
203
204     case REQ_CLEAR_FEATURE :
205     case REQ_SET_FEATURE :
206       {
207         if (pSetup->wValue == FEA_REMOTE_WAKEUP) {
208         }
209         if (pSetup->wValue == FEA_TEST_MODE) {
210         }
211       }
212       return FALSE;
213
214     case REQ_SET_DESCRIPTOR :
215       return FALSE;
216
217     default :
218       return FALSE;
219   }
220
221   return TRUE;
222 }
223
224 //
225 //  Local function to handle a standard interface request
226 //
227 static BOOL usbHandleStdInterfaceReq (TSetupPacket  *pSetup, int *piLen, U8 **ppbData)
228 {
229   U8  *pbData = *ppbData;
230
231   switch (pSetup->bRequest) 
232   {
233     case REQ_GET_STATUS :
234       {
235         pbData [0] = 0;
236         pbData [1] = 0;
237         *piLen = 2;
238       }
239       break;
240
241     case REQ_CLEAR_FEATURE :
242     case REQ_SET_FEATURE :
243       return FALSE;
244
245     case REQ_GET_INTERFACE :
246       {
247         pbData [0] = 0;
248         *piLen = 1;
249       }
250       break;
251
252     case REQ_SET_INTERFACE :
253       {
254         if (pSetup->wValue != 0)
255           return FALSE;
256
257         *piLen = 0;
258       }
259       break;
260
261     default :
262       return FALSE;
263   }
264
265   return TRUE;
266 }
267
268 //
269 //  Local function to handle a standard endpoint request
270 // 
271 static BOOL usbHandleStdEndPointReq (TSetupPacket *pSetup, int *piLen, U8 **ppbData)
272 {
273   U8  *pbData = *ppbData;
274
275   switch (pSetup->bRequest) 
276   {
277     case REQ_GET_STATUS :
278       {
279         pbData [0] = usbHardwareEndpointIsStalled (pSetup->wIndex) ? 1 : 0;
280         pbData [1] = 0;
281         *piLen = 2;
282       }
283       break;
284
285     case REQ_CLEAR_FEATURE :
286       {
287         if (pSetup->wValue == FEA_ENDPOINT_HALT) 
288         {
289           usbHardwareEndpointStall(pSetup->wIndex, FALSE);
290           break;
291         }
292       }
293       return FALSE;
294
295     case REQ_SET_FEATURE :
296       {
297         if (pSetup->wValue == FEA_ENDPOINT_HALT) 
298         {
299           usbHardwareEndpointStall(pSetup->wIndex, TRUE);
300           break;
301         }
302       }
303       return FALSE;
304
305     case REQ_SYNCH_FRAME :
306       return FALSE;
307
308     default :
309       return FALSE;
310   }
311
312   return TRUE;
313 }
314
315
316 //
317 //  Default handler for standard ('chapter 9') requests
318 //  If a custom request handler was installed, this handler is called first.
319 //
320 BOOL usbHandleStandardRequest (TSetupPacket  *pSetup, int *piLen, U8 **ppbData)
321 {
322   if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq (pSetup, piLen, ppbData))
323     return TRUE;
324
325   switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) 
326   {
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;
331   }
332 }
333
334 //
335 //  Registers a callback for custom device requests
336 // 
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'
339 //  request handler.
340 // 
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'
343 //  specification.
344 //    
345 void usbRegisterCustomReqHandler (TFnHandleRequest *pfnHandler)
346 {
347   pfnHandleCustomReq = pfnHandler;
348 }
349