]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/UefiUsbLib/UsbDxeLib.c
MdePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdePkg / Library / UefiUsbLib / UsbDxeLib.c
1 /** @file
2
3 The library provides the USB Standard Device Requests defined
4 in Usb specification 9.4 section.
5
6 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "UefiUsbLibInternal.h"
12
13
14 /**
15 Get the descriptor of the specified USB device.
16
17 Submit a USB get descriptor request for the USB device specified by UsbIo, Value,
18 and Index, and return the descriptor in the buffer specified by Descriptor.
19 The status of the transfer is returned in Status.
20 If UsbIo is NULL, then ASSERT().
21 If Descriptor is NULL, then ASSERT().
22 If Status is NULL, then ASSERT().
23
24 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
25 @param Value The device request value.
26 @param Index The device request index.
27 @param DescriptorLength The size, in bytes, of Descriptor.
28 @param Descriptor A pointer to the descriptor buffer to get.
29 @param Status A pointer to the status of the transfer.
30
31 @retval EFI_SUCCESS The request executed successfully.
32 @retval EFI_OUT_OF_RESOURCES The request could not be completed because the
33 buffer specified by DescriptorLength and Descriptor
34 is not large enough to hold the result of the request.
35 @retval EFI_TIMEOUT A timeout occurred executing the request.
36 @retval EFI_DEVICE_ERROR The request failed due to a device error. The transfer
37 status is returned in Status.
38
39 **/
40 EFI_STATUS
41 EFIAPI
42 UsbGetDescriptor (
43 IN EFI_USB_IO_PROTOCOL *UsbIo,
44 IN UINT16 Value,
45 IN UINT16 Index,
46 IN UINT16 DescriptorLength,
47 OUT VOID *Descriptor,
48 OUT UINT32 *Status
49 )
50 {
51 EFI_USB_DEVICE_REQUEST DevReq;
52
53 ASSERT (UsbIo != NULL);
54 ASSERT (Descriptor != NULL);
55 ASSERT (Status != NULL);
56
57 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
58
59 DevReq.RequestType = USB_DEV_GET_DESCRIPTOR_REQ_TYPE;
60 DevReq.Request = USB_REQ_GET_DESCRIPTOR;
61 DevReq.Value = Value;
62 DevReq.Index = Index;
63 DevReq.Length = DescriptorLength;
64
65 return UsbIo->UsbControlTransfer (
66 UsbIo,
67 &DevReq,
68 EfiUsbDataIn,
69 PcdGet32 (PcdUsbTransferTimeoutValue),
70 Descriptor,
71 DescriptorLength,
72 Status
73 );
74 }
75
76
77 /**
78 Set the descriptor of the specified USB device.
79
80 Submit a USB set descriptor request for the USB device specified by UsbIo,
81 Value, and Index, and set the descriptor using the buffer specified by DesriptorLength
82 and Descriptor. The status of the transfer is returned in Status.
83 If UsbIo is NULL, then ASSERT().
84 If Descriptor is NULL, then ASSERT().
85 If Status is NULL, then ASSERT().
86
87 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
88 @param Value The device request value.
89 @param Index The device request index.
90 @param DescriptorLength The size, in bytes, of Descriptor.
91 @param Descriptor A pointer to the descriptor buffer to set.
92 @param Status A pointer to the status of the transfer.
93
94 @retval EFI_SUCCESS The request executed successfully.
95 @retval EFI_TIMEOUT A timeout occurred executing the request.
96 @retval EFI_DEVICE_ERROR The request failed due to a device error.
97 The transfer status is returned in Status.
98
99 **/
100 EFI_STATUS
101 EFIAPI
102 UsbSetDescriptor (
103 IN EFI_USB_IO_PROTOCOL *UsbIo,
104 IN UINT16 Value,
105 IN UINT16 Index,
106 IN UINT16 DescriptorLength,
107 IN VOID *Descriptor,
108 OUT UINT32 *Status
109 )
110 {
111 EFI_USB_DEVICE_REQUEST DevReq;
112
113 ASSERT (UsbIo != NULL);
114 ASSERT (Descriptor != NULL);
115 ASSERT (Status != NULL);
116
117 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
118
119 DevReq.RequestType = USB_DEV_SET_DESCRIPTOR_REQ_TYPE;
120 DevReq.Request = USB_REQ_SET_DESCRIPTOR;
121 DevReq.Value = Value;
122 DevReq.Index = Index;
123 DevReq.Length = DescriptorLength;
124
125 return UsbIo->UsbControlTransfer (
126 UsbIo,
127 &DevReq,
128 EfiUsbDataOut,
129 PcdGet32 (PcdUsbTransferTimeoutValue),
130 Descriptor,
131 DescriptorLength,
132 Status
133 );
134 }
135
136
137 /**
138 Get the interface setting of the specified USB device.
139
140 Submit a USB get interface request for the USB device specified by UsbIo,
141 and Interface, and place the result in the buffer specified by AlternateSetting.
142 The status of the transfer is returned in Status.
143 If UsbIo is NULL, then ASSERT().
144 If AlternateSetting is NULL, then ASSERT().
145 If Status is NULL, then ASSERT().
146
147 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
148 @param Interface The interface index value.
149 @param AlternateSetting A pointer to the alternate setting to be retrieved.
150 @param Status A pointer to the status of the transfer.
151
152 @retval EFI_SUCCESS The request executed successfully.
153 @retval EFI_TIMEOUT A timeout occurred executing the request.
154 @retval EFI_DEVICE_ERROR The request failed due to a device error.
155 The transfer status is returned in Status.
156
157 **/
158 EFI_STATUS
159 EFIAPI
160 UsbGetInterface (
161 IN EFI_USB_IO_PROTOCOL *UsbIo,
162 IN UINT16 Interface,
163 OUT UINT16 *AlternateSetting,
164 OUT UINT32 *Status
165 )
166 {
167 EFI_USB_DEVICE_REQUEST DevReq;
168
169 ASSERT (UsbIo != NULL);
170 ASSERT (AlternateSetting != NULL);
171 ASSERT (Status != NULL);
172
173 *AlternateSetting = 0;
174
175 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
176
177 DevReq.RequestType = USB_DEV_GET_INTERFACE_REQ_TYPE;
178 DevReq.Request = USB_REQ_GET_INTERFACE;
179 DevReq.Index = Interface;
180 DevReq.Length = 1;
181
182 return UsbIo->UsbControlTransfer (
183 UsbIo,
184 &DevReq,
185 EfiUsbDataIn,
186 PcdGet32 (PcdUsbTransferTimeoutValue),
187 AlternateSetting,
188 1,
189 Status
190 );
191 }
192
193
194 /**
195 Set the interface setting of the specified USB device.
196
197 Submit a USB set interface request for the USB device specified by UsbIo, and
198 Interface, and set the alternate setting to the value specified by AlternateSetting.
199 The status of the transfer is returned in Status.
200 If UsbIo is NULL, then ASSERT().
201 If Status is NULL, then ASSERT().
202
203 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
204 @param Interface The interface index value.
205 @param AlternateSetting The alternate setting to be set.
206 @param Status A pointer to the status of the transfer.
207
208 @retval EFI_SUCCESS The request executed successfully.
209 @retval EFI_TIMEOUT A timeout occurred executing the request.
210 @retval EFI_SUCCESS The request failed due to a device error.
211 The transfer status is returned in Status.
212
213 **/
214 EFI_STATUS
215 EFIAPI
216 UsbSetInterface (
217 IN EFI_USB_IO_PROTOCOL *UsbIo,
218 IN UINT16 Interface,
219 IN UINT16 AlternateSetting,
220 OUT UINT32 *Status
221 )
222 {
223 EFI_USB_DEVICE_REQUEST DevReq;
224
225 ASSERT (UsbIo != NULL);
226 ASSERT (Status != NULL);
227
228 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
229
230 DevReq.RequestType = USB_DEV_SET_INTERFACE_REQ_TYPE;
231 DevReq.Request = USB_REQ_SET_INTERFACE;
232 DevReq.Value = AlternateSetting;
233 DevReq.Index = Interface;
234
235 return UsbIo->UsbControlTransfer (
236 UsbIo,
237 &DevReq,
238 EfiUsbNoData,
239 PcdGet32 (PcdUsbTransferTimeoutValue),
240 NULL,
241 0,
242 Status
243 );
244 }
245
246
247 /**
248 Get the device configuration.
249
250 Submit a USB get configuration request for the USB device specified by UsbIo
251 and place the result in the buffer specified by ConfigurationValue. The status
252 of the transfer is returned in Status.
253 If UsbIo is NULL, then ASSERT().
254 If ConfigurationValue is NULL, then ASSERT().
255 If Status is NULL, then ASSERT().
256
257 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
258 @param ConfigurationValue A pointer to the device configuration to be retrieved.
259 @param Status A pointer to the status of the transfer.
260
261 @retval EFI_SUCCESS The request executed successfully.
262 @retval EFI_TIMEOUT A timeout occurred executing the request.
263 @retval EFI_DEVICE_ERROR The request failed due to a device error.
264 The transfer status is returned in Status.
265
266 **/
267 EFI_STATUS
268 EFIAPI
269 UsbGetConfiguration (
270 IN EFI_USB_IO_PROTOCOL *UsbIo,
271 OUT UINT16 *ConfigurationValue,
272 OUT UINT32 *Status
273 )
274 {
275 EFI_USB_DEVICE_REQUEST DevReq;
276
277 ASSERT (UsbIo != NULL);
278 ASSERT (ConfigurationValue != NULL);
279 ASSERT (Status != NULL);
280
281 *ConfigurationValue = 0;
282
283 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
284
285 DevReq.RequestType = USB_DEV_GET_CONFIGURATION_REQ_TYPE;
286 DevReq.Request = USB_REQ_GET_CONFIG;
287 DevReq.Length = 1;
288
289 return UsbIo->UsbControlTransfer (
290 UsbIo,
291 &DevReq,
292 EfiUsbDataIn,
293 PcdGet32 (PcdUsbTransferTimeoutValue),
294 ConfigurationValue,
295 1,
296 Status
297 );
298 }
299
300
301 /**
302 Set the device configuration.
303
304 Submit a USB set configuration request for the USB device specified by UsbIo
305 and set the device configuration to the value specified by ConfigurationValue.
306 The status of the transfer is returned in Status.
307 If UsbIo is NULL, then ASSERT().
308 If Status is NULL, then ASSERT().
309
310 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
311 @param ConfigurationValue The device configuration value to be set.
312 @param Status A pointer to the status of the transfer.
313
314 @retval EFI_SUCCESS The request executed successfully.
315 @retval EFI_TIMEOUT A timeout occurred executing the request.
316 @retval EFI_DEVICE_ERROR The request failed due to a device error.
317 The transfer status is returned in Status.
318
319 **/
320 EFI_STATUS
321 EFIAPI
322 UsbSetConfiguration (
323 IN EFI_USB_IO_PROTOCOL *UsbIo,
324 IN UINT16 ConfigurationValue,
325 OUT UINT32 *Status
326 )
327 {
328 EFI_USB_DEVICE_REQUEST DevReq;
329
330 ASSERT (UsbIo != NULL);
331 ASSERT (Status != NULL);
332
333 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
334
335 DevReq.RequestType = USB_DEV_SET_CONFIGURATION_REQ_TYPE;
336 DevReq.Request = USB_REQ_SET_CONFIG;
337 DevReq.Value = ConfigurationValue;
338
339 return UsbIo->UsbControlTransfer (
340 UsbIo,
341 &DevReq,
342 EfiUsbNoData,
343 PcdGet32 (PcdUsbTransferTimeoutValue),
344 NULL,
345 0,
346 Status
347 );
348 }
349
350
351 /**
352 Set the specified feature of the specified device.
353
354 Submit a USB set device feature request for the USB device specified by UsbIo,
355 Recipient, and Target to the value specified by Value. The status of the
356 transfer is returned in Status.
357 If UsbIo is NULL, then ASSERT().
358 If Status is NULL, then ASSERT().
359
360 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
361 @param Recipient The USB data recipient type (i.e. Device, Interface, Endpoint).
362 Type USB_TYPES_DEFINITION is defined in the MDE Package Industry
363 Standard include file Usb.h.
364 @param Value The value of the feature to be set.
365 @param Target The index of the device to be set.
366 @param Status A pointer to the status of the transfer.
367
368 @retval EFI_SUCCESS The request executed successfully.
369 @retval EFI_TIMEOUT A timeout occurred executing the request.
370 @retval EFI_DEVICE_ERROR The request failed due to a device error.
371 The transfer status is returned in Status.
372
373 **/
374 EFI_STATUS
375 EFIAPI
376 UsbSetFeature (
377 IN EFI_USB_IO_PROTOCOL *UsbIo,
378 IN USB_TYPES_DEFINITION Recipient,
379 IN UINT16 Value,
380 IN UINT16 Target,
381 OUT UINT32 *Status
382 )
383 {
384 EFI_USB_DEVICE_REQUEST DevReq;
385
386 ASSERT (UsbIo != NULL);
387 ASSERT (Status != NULL);
388
389 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
390
391 switch (Recipient) {
392
393 case USB_TARGET_DEVICE:
394 DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_D;
395 break;
396
397 case USB_TARGET_INTERFACE:
398 DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_I;
399 break;
400
401 case USB_TARGET_ENDPOINT:
402 DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_E;
403 break;
404
405 default:
406 break;
407 }
408 //
409 // Fill device request, see USB1.1 spec
410 //
411 DevReq.Request = USB_REQ_SET_FEATURE;
412 DevReq.Value = Value;
413 DevReq.Index = Target;
414
415
416 return UsbIo->UsbControlTransfer (
417 UsbIo,
418 &DevReq,
419 EfiUsbNoData,
420 PcdGet32 (PcdUsbTransferTimeoutValue),
421 NULL,
422 0,
423 Status
424 );
425 }
426
427
428 /**
429 Clear the specified feature of the specified device.
430
431 Submit a USB clear device feature request for the USB device specified by UsbIo,
432 Recipient, and Target to the value specified by Value. The status of the transfer
433 is returned in Status.
434 If UsbIo is NULL, then ASSERT().
435 If Status is NULL, then ASSERT().
436
437 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
438 @param Recipient The USB data recipient type (i.e. Device, Interface, Endpoint).
439 Type USB_TYPES_DEFINITION is defined in the MDE Package Industry Standard
440 include file Usb.h.
441 @param Value The value of the feature to be cleared.
442 @param Target The index of the device to be cleared.
443 @param Status A pointer to the status of the transfer.
444
445 @retval EFI_SUCCESS The request executed successfully.
446 @retval EFI_TIMEOUT A timeout occurred executing the request.
447 @retval EFI_DEVICE_ERROR The request failed due to a device error.
448 The transfer status is returned in Status.
449
450 **/
451 EFI_STATUS
452 EFIAPI
453 UsbClearFeature (
454 IN EFI_USB_IO_PROTOCOL *UsbIo,
455 IN USB_TYPES_DEFINITION Recipient,
456 IN UINT16 Value,
457 IN UINT16 Target,
458 OUT UINT32 *Status
459 )
460 {
461 EFI_USB_DEVICE_REQUEST DevReq;
462
463 ASSERT (UsbIo != NULL);
464 ASSERT (Status != NULL);
465
466
467 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
468
469 switch (Recipient) {
470
471 case USB_TARGET_DEVICE:
472 DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_D;
473 break;
474
475 case USB_TARGET_INTERFACE:
476 DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_I;
477 break;
478
479 case USB_TARGET_ENDPOINT:
480 DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_E;
481 break;
482
483 default:
484 break;
485 }
486 //
487 // Fill device request, see USB1.1 spec
488 //
489 DevReq.Request = USB_REQ_CLEAR_FEATURE;
490 DevReq.Value = Value;
491 DevReq.Index = Target;
492
493
494 return UsbIo->UsbControlTransfer (
495 UsbIo,
496 &DevReq,
497 EfiUsbNoData,
498 PcdGet32 (PcdUsbTransferTimeoutValue),
499 NULL,
500 0,
501 Status
502 );
503 }
504
505
506 /**
507 Get the status of the specified device.
508
509 Submit a USB device get status request for the USB device specified by UsbIo,
510 Recipient, and Target and place the result in the buffer specified by DeviceStatus.
511 The status of the transfer is returned in Status.
512 If UsbIo is NULL, then ASSERT().
513 If DeviceStatus is NULL, then ASSERT().
514 If Status is NULL, then ASSERT().
515
516 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
517 @param Recipient The USB data recipient type (i.e. Device, Interface, Endpoint).
518 Type USB_TYPES_DEFINITION is defined in the MDE Package Industry Standard
519 include file Usb.h.
520 @param Target The index of the device to be get the status of.
521 @param DeviceStatus A pointer to the device status to be retrieved.
522 @param Status A pointer to the status of the transfer.
523
524 @retval EFI_SUCCESS The request executed successfully.
525 @retval EFI_TIMEOUT A timeout occurred executing the request.
526 @retval EFI_DEVICE_ERROR The request failed due to a device error.
527 The transfer status is returned in Status.
528
529 **/
530 EFI_STATUS
531 EFIAPI
532 UsbGetStatus (
533 IN EFI_USB_IO_PROTOCOL *UsbIo,
534 IN USB_TYPES_DEFINITION Recipient,
535 IN UINT16 Target,
536 OUT UINT16 *DeviceStatus,
537 OUT UINT32 *Status
538 )
539 {
540 EFI_USB_DEVICE_REQUEST DevReq;
541
542 ASSERT (UsbIo != NULL);
543 ASSERT (DeviceStatus != NULL);
544 ASSERT (Status != NULL);
545
546 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
547
548 switch (Recipient) {
549
550 case USB_TARGET_DEVICE:
551 DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_D;
552 break;
553
554 case USB_TARGET_INTERFACE:
555 DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_I;
556 break;
557
558 case USB_TARGET_ENDPOINT:
559 DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_E;
560 break;
561
562 default:
563 break;
564 }
565 //
566 // Fill device request, see USB1.1 spec
567 //
568 DevReq.Request = USB_REQ_GET_STATUS;
569 DevReq.Value = 0;
570 DevReq.Index = Target;
571 DevReq.Length = 2;
572
573 return UsbIo->UsbControlTransfer (
574 UsbIo,
575 &DevReq,
576 EfiUsbDataIn,
577 PcdGet32 (PcdUsbTransferTimeoutValue),
578 DeviceStatus,
579 2,
580 Status
581 );
582 }
583
584
585 /**
586 Clear halt feature of the specified usb endpoint.
587
588 Retrieve the USB endpoint descriptor specified by UsbIo and EndPoint.
589 If the USB endpoint descriptor can not be retrieved, then return EFI_NOT_FOUND.
590 If the endpoint descriptor is found, then clear the halt feature of this USB endpoint.
591 The status of the transfer is returned in Status.
592 If UsbIo is NULL, then ASSERT().
593 If Status is NULL, then ASSERT().
594
595 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target.
596 @param Endpoint The endpoint address.
597 @param Status A pointer to the status of the transfer.
598
599 @retval EFI_SUCCESS The request executed successfully.
600 @retval EFI_TIMEOUT A timeout occurred executing the request.
601 @retval EFI_DEVICE_ERROR The request failed due to a device error.
602 The transfer status is returned in Status.
603 @retval EFI_NOT_FOUND The specified USB endpoint descriptor can not be found
604
605 **/
606 EFI_STATUS
607 EFIAPI
608 UsbClearEndpointHalt (
609 IN EFI_USB_IO_PROTOCOL *UsbIo,
610 IN UINT8 Endpoint,
611 OUT UINT32 *Status
612 )
613 {
614 EFI_STATUS Result;
615 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
616 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
617 UINT8 Index;
618
619 ASSERT (UsbIo != NULL);
620 ASSERT (Status != NULL);
621
622 ZeroMem (&EndpointDescriptor, sizeof (EFI_USB_ENDPOINT_DESCRIPTOR));
623 //
624 // First search the endpoint descriptor for that endpoint addr
625 //
626 Result = UsbIo->UsbGetInterfaceDescriptor (
627 UsbIo,
628 &InterfaceDescriptor
629 );
630 if (EFI_ERROR (Result)) {
631 return Result;
632 }
633
634 for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) {
635 Result = UsbIo->UsbGetEndpointDescriptor (
636 UsbIo,
637 Index,
638 &EndpointDescriptor
639 );
640 if (EFI_ERROR (Result)) {
641 continue;
642 }
643
644 if (EndpointDescriptor.EndpointAddress == Endpoint) {
645 break;
646 }
647 }
648
649 if (Index == InterfaceDescriptor.NumEndpoints) {
650 //
651 // No such endpoint
652 //
653 return EFI_NOT_FOUND;
654 }
655
656 Result = UsbClearFeature (
657 UsbIo,
658 USB_TARGET_ENDPOINT,
659 USB_FEATURE_ENDPOINT_HALT,
660 EndpointDescriptor.EndpointAddress,
661 Status
662 );
663
664 return Result;
665 }