/* Retrieve the indexed string for the language. It requires two steps to get a string, first to get the string's length. Then the string itself. */
EFI_USB_STRING_DESCRIPTOR* UsbGetOneString(IN USB_DEVICE *UsbDev, IN UINT8 Index, IN UINT16 LangId)
/* Retrieve the indexed string for the language. It requires two steps to get a string, first to get the string's length. Then the string itself. */
EFI_USB_STRING_DESCRIPTOR* UsbGetOneString(IN USB_DEVICE *UsbDev, IN UINT8 Index, IN UINT16 LangId)
{
  EFI_USB_STRING_DESCRIPTOR  Desc;
  EFI_STATUS                 Status;
  UINT8                      *Buf;
  Status = UsbCtrlGetDesc (UsbDev, USB_DESC_TYPE_STRING, Index, LangId, &Desc, 2);
  if (EFI_ERROR (Status) ||
      (Desc.Length < OFFSET_OF (EFI_USB_STRING_DESCRIPTOR, Length) + sizeof (Desc.Length)) ||
      (Desc.Length % 2 != 0)
      )
  {
    return NULL;
  }
  Buf = AllocateZeroPool (Desc.Length);
  if (Buf == NULL) {
    return NULL;
  }
  Status = UsbCtrlGetDesc (
             UsbDev,
             USB_DESC_TYPE_STRING,
             Index,
             LangId,
             Buf,
             Desc.Length
             );
  if (EFI_ERROR (Status)) {
    FreePool (Buf);
    return NULL;
  }
  return (EFI_USB_STRING_DESCRIPTOR *)Buf;
}