]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
check the usage of %d,%x,%ld,%lx and so on in debug print statement.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbDesc.c
... / ...
CommitLineData
1/** @file\r
2\r
3 Manage Usb Descriptor List\r
4\r
5Copyright (c) 2007, Intel Corporation\r
6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "UsbBus.h"\r
17\r
18\r
19/**\r
20 Free the interface setting descriptor.\r
21\r
22 @param Setting The descriptor to free.\r
23\r
24 @return None.\r
25\r
26**/\r
27VOID\r
28UsbFreeInterfaceDesc (\r
29 IN USB_INTERFACE_SETTING *Setting\r
30 )\r
31{\r
32 USB_ENDPOINT_DESC *Ep;\r
33 UINTN Index;\r
34\r
35 if (Setting->Endpoints != NULL) {\r
36 //\r
37 // Each interface setting may have several endpoints, free them first.\r
38 //\r
39 for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {\r
40 Ep = Setting->Endpoints[Index];\r
41\r
42 if (Ep != NULL) {\r
43 gBS->FreePool (Ep);\r
44 }\r
45 }\r
46\r
47 gBS->FreePool (Setting->Endpoints);\r
48 }\r
49\r
50 gBS->FreePool (Setting);\r
51}\r
52\r
53\r
54/**\r
55 Free a configuration descriptor with its interface\r
56 descriptors. It may be initialized partially.\r
57\r
58 @param Config The configuration descriptor to free.\r
59\r
60 @return None.\r
61\r
62**/\r
63VOID\r
64UsbFreeConfigDesc (\r
65 IN USB_CONFIG_DESC *Config\r
66 )\r
67{\r
68 USB_INTERFACE_DESC *Interface;\r
69 UINTN Index;\r
70 UINTN SetIndex;\r
71\r
72 if (Config->Interfaces != NULL) {\r
73 //\r
74 // A configuration may have several interfaces, free the interface\r
75 //\r
76 for (Index = 0; Index < Config->Desc.NumInterfaces; Index++) {\r
77 Interface = Config->Interfaces[Index];\r
78\r
79 if (Interface == NULL) {\r
80 continue;\r
81 }\r
82\r
83 //\r
84 // Each interface may have several settings, free the settings\r
85 //\r
86 for (SetIndex = 0; SetIndex < Interface->NumOfSetting; SetIndex++) {\r
87 if (Interface->Settings[SetIndex] != NULL) {\r
88 UsbFreeInterfaceDesc (Interface->Settings[SetIndex]);\r
89 }\r
90 }\r
91\r
92 gBS->FreePool (Interface);\r
93 }\r
94\r
95 gBS->FreePool (Config->Interfaces);\r
96 }\r
97\r
98 gBS->FreePool (Config);\r
99\r
100}\r
101\r
102\r
103/**\r
104 Free a device descriptor with its configurations.\r
105\r
106 @param DevDesc The device descriptor.\r
107\r
108 @return None.\r
109\r
110**/\r
111VOID\r
112UsbFreeDevDesc (\r
113 IN USB_DEVICE_DESC *DevDesc\r
114 )\r
115{\r
116 UINTN Index;\r
117\r
118 if (DevDesc->Configs != NULL) {\r
119 for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) {\r
120 if (DevDesc->Configs[Index] != NULL) {\r
121 UsbFreeConfigDesc (DevDesc->Configs[Index]);\r
122 }\r
123 }\r
124\r
125 gBS->FreePool (DevDesc->Configs);\r
126 }\r
127\r
128 gBS->FreePool (DevDesc);\r
129}\r
130\r
131\r
132/**\r
133 Create a descriptor.\r
134\r
135 @param DescBuf The buffer of raw descriptor.\r
136 @param Len The lenght of the raw descriptor buffer.\r
137 @param Type The type of descriptor to create.\r
138 @param Consumed Number of bytes consumed.\r
139\r
140 @return Created descriptor or NULL.\r
141\r
142**/\r
143VOID *\r
144UsbCreateDesc (\r
145 IN UINT8 *DescBuf,\r
146 IN INTN Len,\r
147 IN UINT8 Type,\r
148 OUT INTN *Consumed\r
149 )\r
150{\r
151 USB_DESC_HEAD *Head;\r
152 INTN DescLen;\r
153 INTN CtrlLen;\r
154 INTN Offset;\r
155 VOID *Desc;\r
156\r
157 DescLen = 0;\r
158 CtrlLen = 0;\r
159 *Consumed = 0;\r
160\r
161 switch (Type) {\r
162 case USB_DESC_TYPE_DEVICE:\r
163 DescLen = sizeof (EFI_USB_DEVICE_DESCRIPTOR);\r
164 CtrlLen = sizeof (USB_DEVICE_DESC);\r
165 break;\r
166\r
167 case USB_DESC_TYPE_CONFIG:\r
168 DescLen = sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
169 CtrlLen = sizeof (USB_CONFIG_DESC);\r
170 break;\r
171\r
172 case USB_DESC_TYPE_INTERFACE:\r
173 DescLen = sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
174 CtrlLen = sizeof (USB_INTERFACE_SETTING);\r
175 break;\r
176\r
177 case USB_DESC_TYPE_ENDPOINT:\r
178 DescLen = sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
179 CtrlLen = sizeof (USB_ENDPOINT_DESC);\r
180 break;\r
181 }\r
182\r
183 //\r
184 // All the descriptor has a common LTV (Length, Type, Value)\r
185 // format. Skip the descriptor that isn't of this Type\r
186 //\r
187 Offset = 0;\r
188 Head = (USB_DESC_HEAD*)DescBuf;\r
189\r
190 while ((Offset < Len) && (Head->Type != Type)) {\r
191 Offset += Head->Len;\r
192 Head = (USB_DESC_HEAD*)(DescBuf + Offset);\r
193 }\r
194\r
195 if ((Len <= Offset) || (Len < Offset + DescLen) ||\r
196 (Head->Type != Type) || (Head->Len != DescLen)) {\r
197 DEBUG (( EFI_D_ERROR, "UsbCreateDesc: met mal-format descriptor\n"));\r
198 return NULL;\r
199 }\r
200\r
201 Desc = AllocateZeroPool (CtrlLen);\r
202\r
203 if (Desc == NULL) {\r
204 return NULL;\r
205 }\r
206\r
207 CopyMem (Desc, Head, DescLen);\r
208 *Consumed = Offset + Head->Len;\r
209\r
210 return Desc;\r
211}\r
212\r
213\r
214/**\r
215 Parse an interface desciptor and its endpoints.\r
216\r
217 @param DescBuf The buffer of raw descriptor.\r
218 @param Len The lenght of the raw descriptor buffer.\r
219 @param Consumed The number of raw descriptor consumed.\r
220\r
221 @return The create interface setting or NULL if failed.\r
222\r
223**/\r
224USB_INTERFACE_SETTING *\r
225UsbParseInterfaceDesc (\r
226 IN UINT8 *DescBuf,\r
227 IN INTN Len,\r
228 OUT INTN *Consumed\r
229 )\r
230{\r
231 USB_INTERFACE_SETTING *Setting;\r
232 USB_ENDPOINT_DESC *Ep;\r
233 UINTN Index;\r
234 UINTN NumEp;\r
235 INTN Used;\r
236 INTN Offset;\r
237\r
238 *Consumed = 0;\r
239 Setting = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_INTERFACE, &Used);\r
240\r
241 if (Setting == NULL) {\r
242 DEBUG (( EFI_D_ERROR, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));\r
243 return NULL;\r
244 }\r
245\r
246 Offset = Used;\r
247\r
248 //\r
249 // Create an arry to hold the interface's endpoints\r
250 //\r
251 NumEp = Setting->Desc.NumEndpoints;\r
252\r
253 DEBUG (( EFI_D_INFO, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",\r
254 Setting->Desc.InterfaceNumber, Setting->Desc.AlternateSetting, (UINT32)NumEp));\r
255\r
256 if (NumEp == 0) {\r
257 goto ON_EXIT;\r
258 }\r
259\r
260 Setting->Endpoints = AllocateZeroPool (sizeof (USB_ENDPOINT_DESC *) * NumEp);\r
261\r
262 if (Setting->Endpoints == NULL) {\r
263 goto ON_ERROR;\r
264 }\r
265\r
266 //\r
267 // Create the endpoints for this interface\r
268 //\r
269 for (Index = 0; Index < NumEp; Index++) {\r
270 Ep = UsbCreateDesc (DescBuf + Offset, Len - Offset, USB_DESC_TYPE_ENDPOINT, &Used);\r
271\r
272 if (Ep == NULL) {\r
273 DEBUG (( EFI_D_ERROR, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", (UINT32)Index));\r
274 goto ON_ERROR;\r
275 }\r
276\r
277 Setting->Endpoints[Index] = Ep;\r
278 Offset += Used;\r
279 }\r
280\r
281\r
282ON_EXIT:\r
283 *Consumed = Offset;\r
284 return Setting;\r
285\r
286ON_ERROR:\r
287 UsbFreeInterfaceDesc (Setting);\r
288 return NULL;\r
289}\r
290\r
291\r
292/**\r
293 Parse the configuration descriptor and its interfaces.\r
294\r
295 @param DescBuf The buffer of raw descriptor.\r
296 @param Len The lenght of the raw descriptor buffer.\r
297\r
298 @return The created configuration descriptor.\r
299\r
300**/\r
301USB_CONFIG_DESC *\r
302UsbParseConfigDesc (\r
303 IN UINT8 *DescBuf,\r
304 IN INTN Len\r
305 )\r
306{\r
307 USB_CONFIG_DESC *Config;\r
308 USB_INTERFACE_SETTING *Setting;\r
309 USB_INTERFACE_DESC *Interface;\r
310 UINTN Index;\r
311 UINTN NumIf;\r
312 INTN Consumed;\r
313\r
314 ASSERT (DescBuf != NULL);\r
315\r
316 Config = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_CONFIG, &Consumed);\r
317\r
318 if (Config == NULL) {\r
319 return NULL;\r
320 }\r
321\r
322 //\r
323 // Initialize an array of setting for the configuration's interfaces.\r
324 //\r
325 NumIf = Config->Desc.NumInterfaces;\r
326 Config->Interfaces = AllocateZeroPool (sizeof (USB_INTERFACE_DESC *) * NumIf);\r
327\r
328 if (Config->Interfaces == NULL) {\r
329 goto ON_ERROR;\r
330 }\r
331\r
332 DEBUG (( EFI_D_INFO, "UsbParseConfigDesc: config %d has %d interfaces\n",\r
333 Config->Desc.ConfigurationValue, (UINT32)NumIf));\r
334\r
335 for (Index = 0; Index < NumIf; Index++) {\r
336 Interface = AllocateZeroPool (sizeof (USB_INTERFACE_DESC));\r
337\r
338 if (Interface == NULL) {\r
339 goto ON_ERROR;\r
340 }\r
341\r
342 Config->Interfaces[Index] = Interface;\r
343 }\r
344\r
345 //\r
346 // If a configuration has several interfaces, these interfaces are\r
347 // numbered from zero to n. If a interface has several settings,\r
348 // these settings are also number from zero to m. The interface\r
349 // setting must be organized as |interface 0, setting 0|interface 0\r
350 // setting 1|interface 1, setting 0|interface 2, setting 0|. Check\r
351 // USB2.0 spec, page 267.\r
352 //\r
353 DescBuf += Consumed;\r
354 Len -= Consumed;\r
355\r
356 while (Len > 0) {\r
357 Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed);\r
358\r
359 if ((Setting == NULL)) {\r
360 DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: failed to parse interface setting\n"));\r
361 goto ON_ERROR;\r
362\r
363 } else if (Setting->Desc.InterfaceNumber >= NumIf) {\r
364 DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: mal-formated interface descriptor\n"));\r
365\r
366 UsbFreeInterfaceDesc (Setting);\r
367 goto ON_ERROR;\r
368 }\r
369\r
370 //\r
371 // Insert the descriptor to the corresponding set.\r
372 //\r
373 Interface = Config->Interfaces[Setting->Desc.InterfaceNumber];\r
374\r
375 if (Interface->NumOfSetting >= USB_MAX_INTERFACE_SETTING) {\r
376 goto ON_ERROR;\r
377 }\r
378\r
379 Interface->Settings[Interface->NumOfSetting] = Setting;\r
380 Interface->NumOfSetting++;\r
381\r
382 DescBuf += Consumed;\r
383 Len -= Consumed;\r
384 }\r
385\r
386 return Config;\r
387\r
388ON_ERROR:\r
389 UsbFreeConfigDesc (Config);\r
390 return NULL;\r
391}\r
392\r
393\r
394/**\r
395 USB standard control transfer support routine. This\r
396 function is used by USB device. It is possible that\r
397 the device's interfaces are still waiting to be\r
398 enumerated.\r
399\r
400 @param UsbDev The usb device.\r
401 @param Direction The direction of data transfer.\r
402 @param Type Standard / class specific / vendor specific.\r
403 @param Target The receiving target.\r
404 @param Request Which request.\r
405 @param Value The wValue parameter of the request.\r
406 @param Index The wIndex parameter of the request.\r
407 @param Buf The buffer to receive data into / transmit from.\r
408 @param Length The length of the buffer.\r
409\r
410 @retval EFI_SUCCESS The control request is executed.\r
411 @retval EFI_DEVICE_ERROR Failed to execute the control transfer.\r
412\r
413**/\r
414EFI_STATUS\r
415UsbCtrlRequest (\r
416 IN USB_DEVICE *UsbDev,\r
417 IN EFI_USB_DATA_DIRECTION Direction,\r
418 IN UINTN Type,\r
419 IN UINTN Target,\r
420 IN UINTN Request,\r
421 IN UINT16 Value,\r
422 IN UINT16 Index,\r
423 IN OUT VOID *Buf,\r
424 IN UINTN Length\r
425 )\r
426{\r
427 EFI_USB_DEVICE_REQUEST DevReq;\r
428 EFI_STATUS Status;\r
429 UINT32 Result;\r
430 UINTN Len;\r
431\r
432 ASSERT ((UsbDev != NULL) && (UsbDev->Bus != NULL));\r
433\r
434 DevReq.RequestType = USB_REQUEST_TYPE (Direction, Type, Target);\r
435 DevReq.Request = (UINT8) Request;\r
436 DevReq.Value = Value;\r
437 DevReq.Index = Index;\r
438 DevReq.Length = (UINT16) Length;\r
439\r
440 Len = Length;\r
441 Status = UsbHcControlTransfer (\r
442 UsbDev->Bus,\r
443 UsbDev->Address,\r
444 UsbDev->Speed,\r
445 UsbDev->MaxPacket0,\r
446 &DevReq,\r
447 Direction,\r
448 Buf,\r
449 &Len,\r
450 USB_GENERAL_DEVICE_REQUEST_TIMEOUT,\r
451 &UsbDev->Translator,\r
452 &Result\r
453 );\r
454\r
455 return Status;\r
456}\r
457\r
458\r
459/**\r
460 Get the standard descriptors.\r
461\r
462 @param UsbDev The USB device to read descriptor from.\r
463 @param DescType The type of descriptor to read.\r
464 @param DescIndex The index of descriptor to read.\r
465 @param LangId Language ID, only used to get string, otherwise set\r
466 it to 0.\r
467 @param Buf The buffer to hold the descriptor read.\r
468 @param Length The length of the buffer.\r
469\r
470 @retval EFI_SUCCESS The descriptor is read OK.\r
471 @retval Others Failed to retrieve the descriptor.\r
472\r
473**/\r
474EFI_STATUS\r
475UsbCtrlGetDesc (\r
476 IN USB_DEVICE *UsbDev,\r
477 IN UINTN DescType,\r
478 IN UINTN DescIndex,\r
479 IN UINT16 LangId,\r
480 OUT VOID *Buf,\r
481 IN UINTN Length\r
482 )\r
483{\r
484 EFI_STATUS Status;\r
485\r
486 Status = UsbCtrlRequest (\r
487 UsbDev,\r
488 EfiUsbDataIn,\r
489 USB_REQ_TYPE_STANDARD,\r
490 USB_TARGET_DEVICE,\r
491 USB_REQ_GET_DESCRIPTOR,\r
492 (UINT16) ((DescType << 8) | DescIndex),\r
493 LangId,\r
494 Buf,\r
495 Length\r
496 );\r
497\r
498 return Status;\r
499}\r
500\r
501\r
502/**\r
503 Return the max packet size for endpoint zero. This function\r
504 is the first function called to get descriptors during bus\r
505 enumeration.\r
506\r
507 @param UsbDev The usb device.\r
508\r
509 @retval EFI_SUCCESS The max packet size of endpoint zero is retrieved.\r
510 @retval EFI_DEVICE_ERROR Failed to retrieve it.\r
511\r
512**/\r
513EFI_STATUS\r
514UsbGetMaxPacketSize0 (\r
515 IN USB_DEVICE *UsbDev\r
516 )\r
517{\r
518 EFI_USB_DEVICE_DESCRIPTOR DevDesc;\r
519 EFI_STATUS Status;\r
520 UINTN Index;\r
521\r
522\r
523 //\r
524 // Get the first 8 bytes of the device descriptor which contains\r
525 // max packet size for endpoint 0, which is at least 8.\r
526 //\r
527 UsbDev->MaxPacket0 = 8;\r
528\r
529 for (Index = 0; Index < 3; Index++) {\r
530 Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_DEVICE, 0, 0, &DevDesc, 8);\r
531\r
532 if (!EFI_ERROR (Status)) {\r
533 UsbDev->MaxPacket0 = DevDesc.MaxPacketSize0;\r
534 return EFI_SUCCESS;\r
535 }\r
536\r
537 gBS->Stall (USB_RETRY_MAX_PACK_SIZE_STALL);\r
538 }\r
539\r
540 return EFI_DEVICE_ERROR;\r
541}\r
542\r
543\r
544/**\r
545 Get the device descriptor for the device.\r
546\r
547 @param UsbDev The Usb device to retrieve descriptor from.\r
548\r
549 @retval EFI_SUCCESS The device descriptor is returned.\r
550 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
551\r
552**/\r
553EFI_STATUS\r
554UsbGetDevDesc (\r
555 IN USB_DEVICE *UsbDev\r
556 )\r
557{\r
558 USB_DEVICE_DESC *DevDesc;\r
559 EFI_STATUS Status;\r
560\r
561 DevDesc = AllocateZeroPool (sizeof (USB_DEVICE_DESC));\r
562\r
563 if (DevDesc == NULL) {\r
564 return EFI_OUT_OF_RESOURCES;\r
565 }\r
566\r
567 Status = UsbCtrlGetDesc (\r
568 UsbDev,\r
569 USB_DESC_TYPE_DEVICE,\r
570 0,\r
571 0,\r
572 DevDesc,\r
573 sizeof (EFI_USB_DEVICE_DESCRIPTOR)\r
574 );\r
575\r
576 if (EFI_ERROR (Status)) {\r
577 gBS->FreePool (DevDesc);\r
578 } else {\r
579 UsbDev->DevDesc = DevDesc;\r
580 }\r
581\r
582 return Status;\r
583}\r
584\r
585\r
586/**\r
587 Retrieve the indexed string for the language. It requires two\r
588 steps to get a string, first to get the string's length. Then\r
589 the string itself.\r
590\r
591 @param UsbDev The usb device.\r
592 @param Index The index the string to retrieve.\r
593 @param LangId Language ID.\r
594\r
595 @return The created string descriptor or NULL.\r
596\r
597**/\r
598EFI_USB_STRING_DESCRIPTOR *\r
599UsbGetOneString (\r
600 IN USB_DEVICE *UsbDev,\r
601 IN UINT8 Index,\r
602 IN UINT16 LangId\r
603 )\r
604{\r
605 EFI_USB_STRING_DESCRIPTOR Desc;\r
606 EFI_STATUS Status;\r
607 UINT8 *Buf;\r
608\r
609 //\r
610 // First get two bytes which contains the string length.\r
611 //\r
612 Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 2);\r
613\r
614 if (EFI_ERROR (Status)) {\r
615 return NULL;\r
616 }\r
617\r
618 Buf = AllocateZeroPool (Desc.Length);\r
619\r
620 if (Buf == NULL) {\r
621 return NULL;\r
622 }\r
623\r
624 Status = UsbCtrlGetDesc (\r
625 UsbDev,\r
626 USB_DESC_TYPE_STRING,\r
627 Index,\r
628 LangId,\r
629 Buf,\r
630 Desc.Length\r
631 );\r
632\r
633 if (EFI_ERROR (Status)) {\r
634 gBS->FreePool (Buf);\r
635 return NULL;\r
636 }\r
637\r
638 return (EFI_USB_STRING_DESCRIPTOR *) Buf;\r
639}\r
640\r
641\r
642/**\r
643 Build the language ID table for string descriptors.\r
644\r
645 @param UsbDev The Usb device.\r
646\r
647 @retval EFI_UNSUPPORTED This device doesn't support string table.\r
648\r
649**/\r
650EFI_STATUS\r
651UsbBuildLangTable (\r
652 IN USB_DEVICE *UsbDev\r
653 )\r
654{\r
655 EFI_USB_STRING_DESCRIPTOR *Desc;\r
656 EFI_STATUS Status;\r
657 UINTN Index;\r
658 UINTN Max;\r
659 UINT16 *Point;\r
660\r
661 //\r
662 // The string of language ID zero returns the supported languages\r
663 //\r
664 Desc = UsbGetOneString (UsbDev, 0, 0);\r
665\r
666 if (Desc == NULL) {\r
667 return EFI_UNSUPPORTED;\r
668 }\r
669\r
670 if (Desc->Length < 4) {\r
671 Status = EFI_UNSUPPORTED;\r
672 goto ON_EXIT;\r
673 }\r
674\r
675 Status = EFI_SUCCESS;\r
676\r
677 Max = (Desc->Length - 2) / 2;\r
678 Max = (Max < USB_MAX_LANG_ID ? Max : USB_MAX_LANG_ID);\r
679\r
680 Point = Desc->String;\r
681 for (Index = 0; Index < Max; Index++) {\r
682 UsbDev->LangId[Index] = *Point;\r
683 Point++;\r
684 }\r
685\r
686 UsbDev->TotalLangId = (UINT16)Max;\r
687\r
688ON_EXIT:\r
689 gBS->FreePool (Desc);\r
690 return Status;\r
691}\r
692\r
693\r
694/**\r
695 Retrieve the indexed configure for the device. USB device\r
696 returns the configuration togetther with the interfaces for\r
697 this configuration. Configuration descriptor is also of\r
698 variable length.\r
699\r
700 @param UsbDev The Usb interface.\r
701 @param Index The index of the configuration.\r
702\r
703 @return The created configuration descriptor.\r
704\r
705**/\r
706EFI_USB_CONFIG_DESCRIPTOR *\r
707UsbGetOneConfig (\r
708 IN USB_DEVICE *UsbDev,\r
709 IN UINT8 Index\r
710 )\r
711{\r
712 EFI_USB_CONFIG_DESCRIPTOR Desc;\r
713 EFI_STATUS Status;\r
714 VOID *Buf;\r
715\r
716 //\r
717 // First get four bytes which contains the total length\r
718 // for this configuration.\r
719 //\r
720 Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_CONFIG, Index, 0, &Desc, 8);\r
721\r
722 if (EFI_ERROR (Status)) {\r
723 DEBUG (( EFI_D_ERROR, "UsbGetOneConfig: failed to get descript length(%d) %r\n",\r
724 Desc.TotalLength, Status));\r
725\r
726 return NULL;\r
727 }\r
728\r
729 DEBUG (( EFI_D_INFO, "UsbGetOneConfig: total length is %d\n", Desc.TotalLength));\r
730\r
731 Buf = AllocateZeroPool (Desc.TotalLength);\r
732\r
733 if (Buf == NULL) {\r
734 return NULL;\r
735 }\r
736\r
737 Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_CONFIG, Index, 0, Buf, Desc.TotalLength);\r
738\r
739 if (EFI_ERROR (Status)) {\r
740 DEBUG (( EFI_D_ERROR, "UsbGetOneConfig: failed to get full descript %r\n", Status));\r
741\r
742 gBS->FreePool (Buf);\r
743 return NULL;\r
744 }\r
745\r
746 return Buf;\r
747}\r
748\r
749\r
750/**\r
751 Build the whole array of descriptors. This function must\r
752 be called after UsbGetMaxPacketSize0 returns the max packet\r
753 size correctly for endpoint 0.\r
754\r
755 @param UsbDev The Usb device.\r
756\r
757 @retval EFI_SUCCESS The descriptor table is build.\r
758 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor.\r
759\r
760**/\r
761EFI_STATUS\r
762UsbBuildDescTable (\r
763 IN USB_DEVICE *UsbDev\r
764 )\r
765{\r
766 EFI_USB_CONFIG_DESCRIPTOR *Config;\r
767 USB_DEVICE_DESC *DevDesc;\r
768 USB_CONFIG_DESC *ConfigDesc;\r
769 UINT8 NumConfig;\r
770 EFI_STATUS Status;\r
771 UINT8 Index;\r
772\r
773 //\r
774 // Get the device descriptor, then allocate the configure\r
775 // descriptor pointer array to hold configurations.\r
776 //\r
777 Status = UsbGetDevDesc (UsbDev);\r
778\r
779 if (EFI_ERROR (Status)) {\r
780 DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status));\r
781 return Status;\r
782 }\r
783\r
784 DevDesc = UsbDev->DevDesc;\r
785 NumConfig = DevDesc->Desc.NumConfigurations;\r
786 DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));\r
787\r
788 if (DevDesc->Configs == NULL) {\r
789 return EFI_OUT_OF_RESOURCES;\r
790 }\r
791\r
792 DEBUG (( EFI_D_INFO, "UsbBuildDescTable: device has %d configures\n", NumConfig));\r
793\r
794 //\r
795 // Read each configurations, then parse them\r
796 //\r
797 for (Index = 0; Index < NumConfig; Index++) {\r
798 Config = UsbGetOneConfig (UsbDev, Index);\r
799\r
800 if (Config == NULL) {\r
801 DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to get configure (index %d)\n", Index));\r
802\r
803 //\r
804 // If we can get the default descriptor, it is likely that the\r
805 // device is still operational.\r
806 //\r
807 if (Index == 0) {\r
808 return EFI_DEVICE_ERROR;\r
809 }\r
810\r
811 break;\r
812 }\r
813\r
814 ConfigDesc = UsbParseConfigDesc ((UINT8 *) Config, Config->TotalLength);\r
815\r
816 gBS->FreePool (Config);\r
817\r
818 if (ConfigDesc == NULL) {\r
819 DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index));\r
820\r
821 //\r
822 // If we can get the default descriptor, it is likely that the\r
823 // device is still operational.\r
824 //\r
825 if (Index == 0) {\r
826 return EFI_DEVICE_ERROR;\r
827 }\r
828\r
829 break;\r
830 }\r
831\r
832 DevDesc->Configs[Index] = ConfigDesc;\r
833 }\r
834\r
835 //\r
836 // Don't return error even this function failed because\r
837 // it is possible for the device to not support strings.\r
838 //\r
839 Status = UsbBuildLangTable (UsbDev);\r
840\r
841 if (EFI_ERROR (Status)) {\r
842 DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: get language ID table %r\n", Status));\r
843 }\r
844\r
845 return EFI_SUCCESS;\r
846}\r
847\r
848\r
849/**\r
850 Set the device's address.\r
851\r
852 @param UsbDev The device to set address to.\r
853 @param Address The address to set.\r
854\r
855 @retval EFI_SUCCESS The device is set to the address.\r
856 @retval Others Failed to set the device address.\r
857\r
858**/\r
859EFI_STATUS\r
860UsbSetAddress (\r
861 IN USB_DEVICE *UsbDev,\r
862 IN UINT8 Address\r
863 )\r
864{\r
865 EFI_STATUS Status;\r
866\r
867 Status = UsbCtrlRequest (\r
868 UsbDev,\r
869 EfiUsbNoData,\r
870 USB_REQ_TYPE_STANDARD,\r
871 USB_TARGET_DEVICE,\r
872 USB_REQ_SET_ADDRESS,\r
873 Address,\r
874 0,\r
875 NULL,\r
876 0\r
877 );\r
878\r
879 return Status;\r
880}\r
881\r
882\r
883/**\r
884 Set the device's configuration. This function changes\r
885 the device's internal state. UsbSelectConfig changes\r
886 the Usb bus's internal state.\r
887\r
888 @param UsbDev The USB device to set configure to.\r
889 @param ConfigIndex The configure index to set.\r
890\r
891 @retval EFI_SUCCESS The device is configured now.\r
892 @retval Others Failed to set the device configure.\r
893\r
894**/\r
895EFI_STATUS\r
896UsbSetConfig (\r
897 IN USB_DEVICE *UsbDev,\r
898 IN UINT8 ConfigIndex\r
899 )\r
900{\r
901 EFI_STATUS Status;\r
902\r
903 Status = UsbCtrlRequest (\r
904 UsbDev,\r
905 EfiUsbNoData,\r
906 USB_REQ_TYPE_STANDARD,\r
907 USB_TARGET_DEVICE,\r
908 USB_REQ_SET_CONFIG,\r
909 ConfigIndex,\r
910 0,\r
911 NULL,\r
912 0\r
913 );\r
914\r
915 return Status;\r
916}\r
917\r
918\r
919/**\r
920 Usb UsbIo interface to clear the feature. This is should\r
921 only be used by HUB which is considered a device driver\r
922 on top of the UsbIo interface.\r
923\r
924 @param UsbIo The UsbIo interface.\r
925 @param Target The target of the transfer: endpoint/device.\r
926 @param Feature The feature to clear.\r
927 @param Index The wIndex parameter.\r
928\r
929 @retval EFI_SUCCESS The device feature is cleared.\r
930 @retval Others Failed to clear the feature.\r
931\r
932**/\r
933EFI_STATUS\r
934UsbIoClearFeature (\r
935 IN EFI_USB_IO_PROTOCOL *UsbIo,\r
936 IN UINTN Target,\r
937 IN UINT16 Feature,\r
938 IN UINT16 Index\r
939 )\r
940{\r
941 EFI_USB_DEVICE_REQUEST DevReq;\r
942 UINT32 UsbResult;\r
943 EFI_STATUS Status;\r
944\r
945 DevReq.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, Target);\r
946 DevReq.Request = USB_REQ_CLEAR_FEATURE;\r
947 DevReq.Value = Feature;\r
948 DevReq.Index = Index;\r
949 DevReq.Length = 0;\r
950\r
951 Status = UsbIo->UsbControlTransfer (\r
952 UsbIo,\r
953 &DevReq,\r
954 EfiUsbNoData,\r
955 USB_CLEAR_FEATURE_REQUEST_TIMEOUT,\r
956 NULL,\r
957 0,\r
958 &UsbResult\r
959 );\r
960\r
961 return Status;\r
962}\r