1 /** @file
2 
3   The library provides USB HID Class standard and specific requests defined
4   in USB HID Firmware Specification 7 section : Requests.
5 
6   Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
7   This program and the accompanying materials
8   are licensed and made available under the terms and conditions of the BSD License
9   which accompanies this distribution.  The full text of the license may be found at
10   http://opensource.org/licenses/bsd-license.php.
11 
12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 **/
16 
17 #include "UefiUsbLibInternal.h"
18 
19 //
20 //  Hid RequestType Bits specifying characteristics of request.
21 //  Valid values are 10100001b (0xa1) or 00100001b (0x21).
22 //  The following description:
23 //    7 Data transfer direction
24 //        0 = Host to device
25 //        1 = Device to host
26 //    6..5 Type
27 //        1 = Class
28 //    4..0 Recipient
29 //        1 = Interface
30 //
31 
32 /**
33   Get the descriptor of the specified USB HID interface.
34 
35   Submit a USB get HID descriptor request for the USB device specified by UsbIo
36   and Interface and return the HID descriptor in HidDescriptor.
37   If UsbIo is NULL, then ASSERT().
38   If HidDescriptor is NULL, then ASSERT().
39 
40   @param  UsbIo          A pointer to the USB I/O Protocol instance for the specific USB target.
41   @param  Interface      The index of the HID interface on the USB target.
42   @param  HidDescriptor  The pointer to the USB HID descriptor that was retrieved from
43                          the specified USB target and interface. Type EFI_USB_HID_DESCRIPTOR
44                          is defined in the MDE Package Industry Standard include file Usb.h.
45 
46   @retval EFI_SUCCESS       The request executed successfully.
47   @retval EFI_TIMEOUT       A timeout occurred executing the request.
48   @retval EFI_DEVICE_ERROR  The request failed due to a device error.
49 
50 **/
51 EFI_STATUS
52 EFIAPI
UsbGetHidDescriptor(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT8 Interface,OUT EFI_USB_HID_DESCRIPTOR * HidDescriptor)53 UsbGetHidDescriptor (
54   IN  EFI_USB_IO_PROTOCOL        *UsbIo,
55   IN  UINT8                      Interface,
56   OUT EFI_USB_HID_DESCRIPTOR     *HidDescriptor
57   )
58 {
59   UINT32                  Status;
60   EFI_STATUS              Result;
61   EFI_USB_DEVICE_REQUEST  Request;
62 
63   ASSERT(UsbIo != NULL);
64   ASSERT(HidDescriptor != NULL);
65 
66   Request.RequestType = USB_HID_GET_DESCRIPTOR_REQ_TYPE;
67   Request.Request     = USB_REQ_GET_DESCRIPTOR;
68   Request.Value       = (UINT16) (USB_DESC_TYPE_HID << 8);
69   Request.Index       = Interface;
70   Request.Length      = (UINT16) sizeof (EFI_USB_HID_DESCRIPTOR);
71 
72   Result = UsbIo->UsbControlTransfer (
73                     UsbIo,
74                     &Request,
75                     EfiUsbDataIn,
76                     PcdGet32 (PcdUsbTransferTimeoutValue),
77                     HidDescriptor,
78                     sizeof (EFI_USB_HID_DESCRIPTOR),
79                     &Status
80                     );
81 
82   return Result;
83 
84 }
85 
86 /**
87   Get the report descriptor of the specified USB HID interface.
88 
89   Submit a USB get HID report descriptor request for the USB device specified by
90   UsbIo and Interface and return the report descriptor in DescriptorBuffer.
91   If UsbIo is NULL, then ASSERT().
92   If DescriptorBuffer is NULL, then ASSERT().
93 
94   @param  UsbIo             A pointer to the USB I/O Protocol instance for the specific USB target.
95   @param  Interface         The index of the report interface on the USB target.
96   @param  DescriptorLength  The size, in bytes, of DescriptorBuffer.
97   @param  DescriptorBuffer  A pointer to the buffer to store the report class descriptor.
98 
99   @retval  EFI_SUCCESS           The request executed successfully.
100   @retval  EFI_OUT_OF_RESOURCES  The request could not be completed because the
101                                  buffer specified by DescriptorLength and DescriptorBuffer
102                                  is not large enough to hold the result of the request.
103   @retval  EFI_TIMEOUT           A timeout occurred executing the request.
104   @retval  EFI_DEVICE_ERROR      The request failed due to a device error.
105 
106 **/
107 EFI_STATUS
108 EFIAPI
UsbGetReportDescriptor(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT8 Interface,IN UINT16 DescriptorLength,OUT UINT8 * DescriptorBuffer)109 UsbGetReportDescriptor (
110   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
111   IN  UINT8                   Interface,
112   IN  UINT16                  DescriptorLength,
113   OUT UINT8                   *DescriptorBuffer
114   )
115 {
116   UINT32                  Status;
117   EFI_STATUS              Result;
118   EFI_USB_DEVICE_REQUEST  Request;
119 
120   ASSERT (UsbIo != NULL);
121   ASSERT (DescriptorBuffer != NULL);
122 
123   //
124   // Fill Device request packet
125   //
126   Request.RequestType = USB_HID_GET_DESCRIPTOR_REQ_TYPE;
127   Request.Request     = USB_REQ_GET_DESCRIPTOR;
128   Request.Value       = (UINT16) (USB_DESC_TYPE_REPORT << 8);
129   Request.Index       = Interface;
130   Request.Length      = DescriptorLength;
131 
132   Result = UsbIo->UsbControlTransfer (
133                     UsbIo,
134                     &Request,
135                     EfiUsbDataIn,
136                     PcdGet32 (PcdUsbTransferTimeoutValue),
137                     DescriptorBuffer,
138                     DescriptorLength,
139                     &Status
140                     );
141 
142   return Result;
143 
144 }
145 
146 /**
147   Get the HID protocol of the specified USB HID interface.
148 
149   Submit a USB get HID protocol request for the USB device specified by UsbIo
150   and Interface and return the protocol retrieved in Protocol.
151   If UsbIo is NULL, then ASSERT().
152   If Protocol is NULL, then ASSERT().
153 
154   @param  UsbIo      A pointer to the USB I/O Protocol instance for the specific USB target.
155   @param  Interface  The index of the report interface on the USB target.
156   @param  Protocol   A pointer to the protocol for the specified USB target.
157 
158   @retval  EFI_SUCCESS       The request executed successfully.
159   @retval  EFI_TIMEOUT       A timeout occurred executing the request.
160   @retval  EFI_DEVICE_ERROR  The request failed due to a device error.
161 
162 **/
163 EFI_STATUS
164 EFIAPI
UsbGetProtocolRequest(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT8 Interface,OUT UINT8 * Protocol)165 UsbGetProtocolRequest (
166   IN EFI_USB_IO_PROTOCOL     *UsbIo,
167   IN UINT8                   Interface,
168   OUT UINT8                   *Protocol
169   )
170 {
171   UINT32                  Status;
172   EFI_STATUS              Result;
173   EFI_USB_DEVICE_REQUEST  Request;
174 
175   ASSERT (UsbIo != NULL);
176   ASSERT (Protocol != NULL);
177 
178   //
179   // Fill Device request packet
180   //
181   Request.RequestType = USB_HID_CLASS_GET_REQ_TYPE;
182   Request.Request = EFI_USB_GET_PROTOCOL_REQUEST;
183   Request.Value   = 0;
184   Request.Index   = Interface;
185   Request.Length  = 1;
186 
187   Result = UsbIo->UsbControlTransfer (
188                     UsbIo,
189                     &Request,
190                     EfiUsbDataIn,
191                     PcdGet32 (PcdUsbTransferTimeoutValue),
192                     Protocol,
193                     sizeof (UINT8),
194                     &Status
195                     );
196 
197   return Result;
198 }
199 
200 
201 
202 /**
203   Set the HID protocol of the specified USB HID interface.
204 
205   Submit a USB set HID protocol request for the USB device specified by UsbIo
206   and Interface and set the protocol to the value specified by Protocol.
207   If UsbIo is NULL, then ASSERT().
208 
209   @param  UsbIo      A pointer to the USB I/O Protocol instance for the specific USB target.
210   @param  Interface  The index of the report interface on the USB target.
211   @param  Protocol   The protocol value to set for the specified USB target.
212 
213   @retval  EFI_SUCCESS       The request executed successfully.
214   @retval  EFI_TIMEOUT       A timeout occurred executing the request.
215   @retval  EFI_DEVICE_ERROR  The request failed due to a device error.
216 
217 **/
218 EFI_STATUS
219 EFIAPI
UsbSetProtocolRequest(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT8 Interface,IN UINT8 Protocol)220 UsbSetProtocolRequest (
221   IN EFI_USB_IO_PROTOCOL     *UsbIo,
222   IN UINT8                   Interface,
223   IN UINT8                   Protocol
224   )
225 {
226   UINT32                  Status;
227   EFI_STATUS              Result;
228   EFI_USB_DEVICE_REQUEST  Request;
229 
230   ASSERT (UsbIo != NULL);
231 
232   //
233   // Fill Device request packet
234   //
235   Request.RequestType = USB_HID_CLASS_SET_REQ_TYPE;
236   Request.Request = EFI_USB_SET_PROTOCOL_REQUEST;
237   Request.Value   = Protocol;
238   Request.Index   = Interface;
239   Request.Length  = 0;
240 
241   Result = UsbIo->UsbControlTransfer (
242                     UsbIo,
243                     &Request,
244                     EfiUsbNoData,
245                     PcdGet32 (PcdUsbTransferTimeoutValue),
246                     NULL,
247                     0,
248                     &Status
249                     );
250   return Result;
251 }
252 
253 
254 /**
255   Set the idle rate of the specified USB HID report.
256 
257   Submit a USB set HID report idle request for the USB device specified by UsbIo,
258   Interface, and ReportId, and set the idle rate to the value specified by Duration.
259   If UsbIo is NULL, then ASSERT().
260 
261   @param  UsbIo      A pointer to the USB I/O Protocol instance for the specific USB target.
262   @param  Interface  The index of the report interface on the USB target.
263   @param  ReportId   The identifier of the report to retrieve.
264   @param  Duration   The idle rate to set for the specified USB target.
265 
266   @retval  EFI_SUCCESS       The request executed successfully.
267   @retval  EFI_TIMEOUT       A timeout occurred executing the request.
268   @retval  EFI_DEVICE_ERROR  The request failed due to a device error.
269 
270 **/
271 EFI_STATUS
272 EFIAPI
UsbSetIdleRequest(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT8 Interface,IN UINT8 ReportId,IN UINT8 Duration)273 UsbSetIdleRequest (
274   IN EFI_USB_IO_PROTOCOL     *UsbIo,
275   IN UINT8                   Interface,
276   IN UINT8                   ReportId,
277   IN UINT8                   Duration
278   )
279 {
280   UINT32                  Status;
281   EFI_STATUS              Result;
282   EFI_USB_DEVICE_REQUEST  Request;
283 
284   ASSERT (UsbIo != NULL);
285   //
286   // Fill Device request packet
287   //
288   Request.RequestType = USB_HID_CLASS_SET_REQ_TYPE;
289   Request.Request = EFI_USB_SET_IDLE_REQUEST;
290   Request.Value   = (UINT16) ((Duration << 8) | ReportId);
291   Request.Index   = Interface;
292   Request.Length  = 0;
293 
294   Result = UsbIo->UsbControlTransfer (
295                     UsbIo,
296                     &Request,
297                     EfiUsbNoData,
298                     PcdGet32 (PcdUsbTransferTimeoutValue),
299                     NULL,
300                     0,
301                     &Status
302                     );
303   return Result;
304 }
305 
306 
307 /**
308   Get the idle rate of the specified USB HID report.
309 
310   Submit a USB get HID report idle request for the USB device specified by UsbIo,
311   Interface, and ReportId, and return the ide rate in Duration.
312   If UsbIo is NULL, then ASSERT().
313   If Duration is NULL, then ASSERT().
314 
315   @param  UsbIo      A pointer to the USB I/O Protocol instance for the specific USB target.
316   @param  Interface  The index of the report interface on the USB target.
317   @param  ReportId   The identifier of the report to retrieve.
318   @param  Duration   A pointer to the idle rate retrieved from the specified USB target.
319 
320   @retval  EFI_SUCCESS       The request executed successfully.
321   @retval  EFI_TIMEOUT       A timeout occurred executing the request.
322   @retval  EFI_DEVICE_ERROR  The request failed due to a device error.
323 
324 **/
325 EFI_STATUS
326 EFIAPI
UsbGetIdleRequest(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT8 Interface,IN UINT8 ReportId,OUT UINT8 * Duration)327 UsbGetIdleRequest (
328   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
329   IN  UINT8                   Interface,
330   IN  UINT8                   ReportId,
331   OUT UINT8                   *Duration
332   )
333 {
334   UINT32                  Status;
335   EFI_STATUS              Result;
336   EFI_USB_DEVICE_REQUEST  Request;
337 
338   ASSERT (UsbIo != NULL);
339   ASSERT (Duration != NULL);
340   //
341   // Fill Device request packet
342   //
343   Request.RequestType = USB_HID_CLASS_GET_REQ_TYPE;
344   Request.Request = EFI_USB_GET_IDLE_REQUEST;
345   Request.Value   = ReportId;
346   Request.Index   = Interface;
347   Request.Length  = 1;
348 
349   Result = UsbIo->UsbControlTransfer (
350                     UsbIo,
351                     &Request,
352                     EfiUsbDataIn,
353                     PcdGet32 (PcdUsbTransferTimeoutValue),
354                     Duration,
355                     1,
356                     &Status
357                     );
358 
359   return Result;
360 }
361 
362 
363 
364 /**
365   Set the report descriptor of the specified USB HID interface.
366 
367   Submit a USB set HID report request for the USB device specified by UsbIo,
368   Interface, ReportId, and ReportType, and set the report descriptor using the
369   buffer specified by ReportLength and Report.
370   If UsbIo is NULL, then ASSERT().
371   If Report is NULL, then ASSERT().
372 
373   @param  UsbIo         A pointer to the USB I/O Protocol instance for the specific USB target.
374   @param  Interface     The index of the report interface on the USB target.
375   @param  ReportId      The identifier of the report to retrieve.
376   @param  ReportType    The type of report to retrieve.
377   @param  ReportLength  The size, in bytes, of Report.
378   @param  Report        A pointer to the report descriptor buffer to set.
379 
380   @retval  EFI_SUCCESS       The request executed successfully.
381   @retval  EFI_TIMEOUT       A timeout occurred executing the request.
382   @retval  EFI_DEVICE_ERROR  The request failed due to a device error.
383 
384 **/
385 EFI_STATUS
386 EFIAPI
UsbSetReportRequest(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT8 Interface,IN UINT8 ReportId,IN UINT8 ReportType,IN UINT16 ReportLen,IN UINT8 * Report)387 UsbSetReportRequest (
388   IN EFI_USB_IO_PROTOCOL     *UsbIo,
389   IN UINT8                   Interface,
390   IN UINT8                   ReportId,
391   IN UINT8                   ReportType,
392   IN UINT16                  ReportLen,
393   IN UINT8                   *Report
394   )
395 {
396   UINT32                  Status;
397   EFI_STATUS              Result;
398   EFI_USB_DEVICE_REQUEST  Request;
399 
400   ASSERT (UsbIo != NULL);
401   ASSERT (Report != NULL);
402 
403   //
404   // Fill Device request packet
405   //
406   Request.RequestType = USB_HID_CLASS_SET_REQ_TYPE;
407   Request.Request = EFI_USB_SET_REPORT_REQUEST;
408   Request.Value   = (UINT16) ((ReportType << 8) | ReportId);
409   Request.Index   = Interface;
410   Request.Length  = ReportLen;
411 
412   Result = UsbIo->UsbControlTransfer (
413                     UsbIo,
414                     &Request,
415                     EfiUsbDataOut,
416                     PcdGet32 (PcdUsbTransferTimeoutValue),
417                     Report,
418                     ReportLen,
419                     &Status
420                     );
421 
422   return Result;
423 }
424 
425 
426 /**
427   Get the report descriptor of the specified USB HID interface.
428 
429   Submit a USB get HID report request for the USB device specified by UsbIo,
430   Interface, ReportId, and ReportType, and return the report in the buffer
431   specified by Report.
432   If UsbIo is NULL, then ASSERT().
433   If Report is NULL, then ASSERT().
434 
435   @param  UsbIo         A pointer to the USB I/O Protocol instance for the specific USB target.
436   @param  Interface     The index of the report interface on the USB target.
437   @param  ReportId      The identifier of the report to retrieve.
438   @param  ReportType    The type of report to retrieve.
439   @param  ReportLength  The size, in bytes, of Report.
440   @param  Report        A pointer to the buffer to store the report descriptor.
441 
442   @retval  EFI_SUCCESS           The request executed successfully.
443   @retval  EFI_OUT_OF_RESOURCES  The request could not be completed because the
444                                  buffer specified by ReportLength and Report is not
445                                  large enough to hold the result of the request.
446   @retval  EFI_TIMEOUT           A timeout occurred executing the request.
447   @retval  EFI_DEVICE_ERROR      The request failed due to a device error.
448 
449 **/
450 EFI_STATUS
451 EFIAPI
UsbGetReportRequest(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT8 Interface,IN UINT8 ReportId,IN UINT8 ReportType,IN UINT16 ReportLen,OUT UINT8 * Report)452 UsbGetReportRequest (
453   IN  EFI_USB_IO_PROTOCOL     *UsbIo,
454   IN  UINT8                   Interface,
455   IN  UINT8                   ReportId,
456   IN  UINT8                   ReportType,
457   IN  UINT16                  ReportLen,
458   OUT UINT8                   *Report
459   )
460 {
461   UINT32                  Status;
462   EFI_STATUS              Result;
463   EFI_USB_DEVICE_REQUEST  Request;
464 
465   ASSERT (UsbIo != NULL);
466   ASSERT (Report != NULL);
467 
468   //
469   // Fill Device request packet
470   //
471   Request.RequestType = USB_HID_CLASS_GET_REQ_TYPE;
472   Request.Request = EFI_USB_GET_REPORT_REQUEST;
473   Request.Value   = (UINT16) ((ReportType << 8) | ReportId);
474   Request.Index   = Interface;
475   Request.Length  = ReportLen;
476 
477   Result = UsbIo->UsbControlTransfer (
478                     UsbIo,
479                     &Request,
480                     EfiUsbDataIn,
481                     PcdGet32 (PcdUsbTransferTimeoutValue),
482                     Report,
483                     ReportLen,
484                     &Status
485                     );
486 
487   return Result;
488 }
489