]> git.proxmox.com Git - mirror_edk2.git/blame - 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
e237e7ae 1/** @file\r
2\r
8616fc4c 3 Manage Usb Descriptor List\r
4\r
e237e7ae 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
e237e7ae 14**/\r
15\r
16#include "UsbBus.h"\r
17\r
18\r
19/**\r
8616fc4c 20 Free the interface setting descriptor.\r
e237e7ae 21\r
8616fc4c 22 @param Setting The descriptor to free.\r
e237e7ae 23\r
8616fc4c 24 @return None.\r
e237e7ae 25\r
26**/\r
e237e7ae 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
e237e7ae 54/**\r
55 Free a configuration descriptor with its interface\r
8616fc4c 56 descriptors. It may be initialized partially.\r
e237e7ae 57\r
8616fc4c 58 @param Config The configuration descriptor to free.\r
e237e7ae 59\r
8616fc4c 60 @return None.\r
e237e7ae 61\r
62**/\r
e237e7ae 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
e237e7ae 103/**\r
8616fc4c 104 Free a device descriptor with its configurations.\r
e237e7ae 105\r
8616fc4c 106 @param DevDesc The device descriptor.\r
e237e7ae 107\r
8616fc4c 108 @return None.\r
e237e7ae 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
8616fc4c 133 Create a descriptor.\r
e237e7ae 134\r
8616fc4c 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
e237e7ae 139\r
8616fc4c 140 @return Created descriptor or NULL.\r
e237e7ae 141\r
142**/\r
e237e7ae 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
d2577026 197 DEBUG (( EFI_D_ERROR, "UsbCreateDesc: met mal-format descriptor\n"));\r
e237e7ae 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
8616fc4c 215 Parse an interface desciptor and its endpoints.\r
e237e7ae 216\r
8616fc4c 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
e237e7ae 220\r
8616fc4c 221 @return The create interface setting or NULL if failed.\r
e237e7ae 222\r
223**/\r
e237e7ae 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
d2577026 242 DEBUG (( EFI_D_ERROR, "UsbParseInterfaceDesc: failed to create interface descriptor\n"));\r
e237e7ae 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
d2577026 253 DEBUG (( EFI_D_INFO, "UsbParseInterfaceDesc: interface %d(setting %d) has %d endpoints\n",\r
7df7393f 254 Setting->Desc.InterfaceNumber, Setting->Desc.AlternateSetting, (UINT32)NumEp));\r
e237e7ae 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
7df7393f 273 DEBUG (( EFI_D_ERROR, "UsbParseInterfaceDesc: failed to create endpoint(index %d)\n", (UINT32)Index));\r
e237e7ae 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
8616fc4c 295 @param DescBuf The buffer of raw descriptor.\r
296 @param Len The lenght of the raw descriptor buffer.\r
e237e7ae 297\r
8616fc4c 298 @return The created configuration descriptor.\r
e237e7ae 299\r
300**/\r
e237e7ae 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
d2577026 332 DEBUG (( EFI_D_INFO, "UsbParseConfigDesc: config %d has %d interfaces\n",\r
7df7393f 333 Config->Desc.ConfigurationValue, (UINT32)NumIf));\r
e237e7ae 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
d2577026 360 DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: failed to parse interface setting\n"));\r
e237e7ae 361 goto ON_ERROR;\r
362\r
363 } else if (Setting->Desc.InterfaceNumber >= NumIf) {\r
d2577026 364 DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: mal-formated interface descriptor\n"));\r
e237e7ae 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
e237e7ae 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
8616fc4c 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
e237e7ae 409\r
8616fc4c 410 @retval EFI_SUCCESS The control request is executed.\r
411 @retval EFI_DEVICE_ERROR Failed to execute the control transfer.\r
e237e7ae 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
41e8ff27 450 USB_GENERAL_DEVICE_REQUEST_TIMEOUT,\r
e237e7ae 451 &UsbDev->Translator,\r
452 &Result\r
453 );\r
454\r
455 return Status;\r
456}\r
457\r
458\r
e237e7ae 459/**\r
460 Get the standard descriptors.\r
461\r
8616fc4c 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
e237e7ae 465 @param LangId Language ID, only used to get string, otherwise set\r
8616fc4c 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
e237e7ae 469\r
8616fc4c 470 @retval EFI_SUCCESS The descriptor is read OK.\r
471 @retval Others Failed to retrieve the descriptor.\r
e237e7ae 472\r
473**/\r
e237e7ae 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
e237e7ae 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
8616fc4c 507 @param UsbDev The usb device.\r
e237e7ae 508\r
8616fc4c 509 @retval EFI_SUCCESS The max packet size of endpoint zero is retrieved.\r
510 @retval EFI_DEVICE_ERROR Failed to retrieve it.\r
e237e7ae 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
41e8ff27 537 gBS->Stall (USB_RETRY_MAX_PACK_SIZE_STALL);\r
e237e7ae 538 }\r
539\r
540 return EFI_DEVICE_ERROR;\r
541}\r
542\r
543\r
e237e7ae 544/**\r
545 Get the device descriptor for the device.\r
546\r
8616fc4c 547 @param UsbDev The Usb device to retrieve descriptor from.\r
e237e7ae 548\r
8616fc4c 549 @retval EFI_SUCCESS The device descriptor is returned.\r
550 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
e237e7ae 551\r
552**/\r
e237e7ae 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
e237e7ae 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
8616fc4c 591 @param UsbDev The usb device.\r
592 @param Index The index the string to retrieve.\r
593 @param LangId Language ID.\r
e237e7ae 594\r
8616fc4c 595 @return The created string descriptor or NULL.\r
e237e7ae 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
e237e7ae 642/**\r
8616fc4c 643 Build the language ID table for string descriptors.\r
e237e7ae 644\r
8616fc4c 645 @param UsbDev The Usb device.\r
e237e7ae 646\r
8616fc4c 647 @retval EFI_UNSUPPORTED This device doesn't support string table.\r
e237e7ae 648\r
649**/\r
e237e7ae 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
e237e7ae 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
8616fc4c 698 variable length.\r
e237e7ae 699\r
8616fc4c 700 @param UsbDev The Usb interface.\r
701 @param Index The index of the configuration.\r
e237e7ae 702\r
8616fc4c 703 @return The created configuration descriptor.\r
e237e7ae 704\r
705**/\r
e237e7ae 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
d2577026 723 DEBUG (( EFI_D_ERROR, "UsbGetOneConfig: failed to get descript length(%d) %r\n",\r
7df7393f 724 Desc.TotalLength, Status));\r
e237e7ae 725\r
726 return NULL;\r
727 }\r
728\r
d2577026 729 DEBUG (( EFI_D_INFO, "UsbGetOneConfig: total length is %d\n", Desc.TotalLength));\r
e237e7ae 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
d2577026 740 DEBUG (( EFI_D_ERROR, "UsbGetOneConfig: failed to get full descript %r\n", Status));\r
e237e7ae 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
e237e7ae 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
8616fc4c 755 @param UsbDev The Usb device.\r
e237e7ae 756\r
8616fc4c 757 @retval EFI_SUCCESS The descriptor table is build.\r
758 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the descriptor.\r
e237e7ae 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
d2577026 780 DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to get device descriptor - %r\n", Status));\r
e237e7ae 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
d2577026 792 DEBUG (( EFI_D_INFO, "UsbBuildDescTable: device has %d configures\n", NumConfig));\r
e237e7ae 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
d2577026 801 DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to get configure (index %d)\n", Index));\r
e237e7ae 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
d2577026 819 DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: failed to parse configure (index %d)\n", Index));\r
e237e7ae 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
d2577026 842 DEBUG (( EFI_D_ERROR, "UsbBuildDescTable: get language ID table %r\n", Status));\r
e237e7ae 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
8616fc4c 852 @param UsbDev The device to set address to.\r
853 @param Address The address to set.\r
e237e7ae 854\r
8616fc4c 855 @retval EFI_SUCCESS The device is set to the address.\r
856 @retval Others Failed to set the device address.\r
e237e7ae 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
8616fc4c 888 @param UsbDev The USB device to set configure to.\r
889 @param ConfigIndex The configure index to set.\r
e237e7ae 890\r
8616fc4c 891 @retval EFI_SUCCESS The device is configured now.\r
892 @retval Others Failed to set the device configure.\r
e237e7ae 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
e237e7ae 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
8616fc4c 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
e237e7ae 928\r
8616fc4c 929 @retval EFI_SUCCESS The device feature is cleared.\r
930 @retval Others Failed to clear the feature.\r
e237e7ae 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
41e8ff27 955 USB_CLEAR_FEATURE_REQUEST_TIMEOUT,\r
e237e7ae 956 NULL,\r
957 0,\r
958 &UsbResult\r
959 );\r
960\r
961 return Status;\r
962}\r