枚举usb设备2
1 列出产商及序列号
思路:在USB手册《Universal Serial Bus Specification Revision 2.0》9.6章节有相关的定义,如设备,配置,接口,终结点等信息。下表为USB设备信息的具体定义:
那最后要如何读取这些信息呢?UEFI已经给我们提供了相应的Protocol,那便是EFI_USB_IO_PROTOCOL。首先使用EFI_USB_IO_PROTOCOL.UsbGetDeviceDescriptor()获取产商和序列号的索引值,再用EFI_USB_IO_PROTOCOL.UsbGetStringDescriptor()取得相应的字符串即可。代码如下:
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Protocol/BlockIo.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/DevicePathToText.h>
#include <Protocol/UsbIo.h>
#include <Library/UefiApplicationEntryPoint.h>
#define LANGID_ENGLISH 0x0409
EFI_STATUS
EFIAPI
UsbEnumerate (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE *UsbDeviceHandle;
UINTN UsbDeviceHandleNumber;
EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *Path2Text;
UINTN Index;
EFI_USB_IO_PROTOCOL *UsbDevice;
EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
CHAR16 *StrManufacturer;
CHAR16 *StrProduct;
CHAR16 *StrSerialNumber;
/* Get all usb device handles */
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiUsbIoProtocolGuid,
NULL,
&UsbDeviceHandleNumber,
&UsbDeviceHandle
);
if (EFI_ERROR (Status)) {
Print (L"Unsupported\n\r");
return 0;
}
/* Get device to text instance to convert device path to string */
Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &Path2Text);
if (EFI_ERROR(Status)) {
Print (L"Unsupported\n\r");
return 0;
}
/* List all usb info */
for (Index = 0; Index < UsbDeviceHandleNumber; Index ++) {
Print (L"Usb device number: %d\n\r", Index + 1);
/* Get Usb Io protocol instance */
Status = gBS->HandleProtocol (UsbDeviceHandle[Index], &gEfiUsbIoProtocolGuid, (VOID **) &UsbDevice);
Status = UsbDevice->UsbGetDeviceDescriptor (UsbDevice, &DeviceDescriptor);
if (!EFI_ERROR (Status)) {
/* Manufacturer */
StrManufacturer = NULL;
Status = UsbDevice->UsbGetStringDescriptor (UsbDevice, LANGID_ENGLISH, DeviceDescriptor.StrManufacturer, &StrManufacturer);
if (!EFI_ERROR (Status)) {
Print (L"Manufacturer: %s\n\r", StrManufacturer);
}
/* Product */
StrProduct = NULL;
Status = UsbDevice->UsbGetStringDescriptor (UsbDevice, LANGID_ENGLISH, DeviceDescriptor.StrProduct, &StrProduct);
if (!EFI_ERROR (Status)) {
Print (L"Product: %s\n\r", StrProduct);
}
/* Serial number */
StrSerialNumber = NULL;
Status = UsbDevice->UsbGetStringDescriptor (UsbDevice, LANGID_ENGLISH, DeviceDescriptor.StrSerialNumber, &StrSerialNumber);
if (!EFI_ERROR (Status)) {
Print (L"Serial number: %s\n\r", StrSerialNumber);
}
}
/* List device path */
Status = gBS->HandleProtocol (UsbDeviceHandle[Index], &gEfiDevicePathProtocolGuid, (VOID **) &UsbDevicePath);
if (!EFI_ERROR (Status)) {
Print (L"Device Path: %s\n\r", Path2Text->ConvertDevicePathToText(UsbDevicePath, FALSE, TRUE));
}
Print (L"\n\r");
}
return EFI_SUCCESS;
}
2 最后还有一个问题要解决的,那就是怎么去判断usb设备的类型,如怎么知道某个设备是存储设备,或是键盘鼠标等。此类信息位于USB的Interface Descriptor中。
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Protocol/BlockIo.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/DevicePathToText.h>
#include <Protocol/UsbIo.h>
#include <Library/UefiApplicationEntryPoint.h>
#define LANGID_ENGLISH 0x0409
#define USB_INTERFACE_CLASS_UNKNOW 0x00
#define USB_INTERFACE_CLASS_HID 0x03
#define USB_INTERFACE_CLASS_STORAGE 0x08
#define USB_INTERFACE_CLASS_HUB 0x09
#define USB_INTERFACE_CLASS_VENDOR_DEF 0xFF
#define USB_INTERFACE_HID_PROTOCOL_KB 0x01
#define USB_INTERFACE_HID_PROTOCOL_MS 0x02
EFI_STATUS
EFIAPI
UsbEnumerate (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE *UsbDeviceHandle;
UINTN UsbDeviceHandleNumber;
EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *Path2Text;
UINTN Index;
EFI_USB_IO_PROTOCOL *UsbDevice;
EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
CHAR16 *StrManufacturer;
CHAR16 *StrProduct;
CHAR16 *StrSerialNumber;
EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
/* Get all usb device handles */
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiUsbIoProtocolGuid,
NULL,
&UsbDeviceHandleNumber,
&UsbDeviceHandle
);
if (!EFI_ERROR (Status)) {
Print (L"Usb device number: %d\n\r", UsbDeviceHandleNumber);
}
/* Get device to text instance to convert device path to string */
Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &Path2Text);
if (EFI_ERROR(Status)) {
Print (L"Unsupported\n\r");
return 0;
}
/* List all usb info */
for (Index = 0; Index < UsbDeviceHandleNumber; Index ++) {
Print (L"Usb device number: %d\n\r", Index + 1);
/* Get Usb Io protocol instance */
Status = gBS->HandleProtocol (UsbDeviceHandle[Index], &gEfiUsbIoProtocolGuid, (VOID **) &UsbDevice);
/* Get usb device type */
Status = UsbDevice->UsbGetInterfaceDescriptor (UsbDevice, &InterfaceDescriptor);
if (!EFI_ERROR (Status)) {
Print (L"NO.%d\n\r", Index + 1);
switch (InterfaceDescriptor.InterfaceClass) {
case USB_INTERFACE_CLASS_UNKNOW:
Print (L"Type: Unkown\n\r");
break;
case USB_INTERFACE_CLASS_HID:
if (InterfaceDescriptor.InterfaceProtocol == USB_INTERFACE_HID_PROTOCOL_KB) {
Print (L"Type: Keyboard\n\r");
}
Else if (InterfaceDescriptor.InterfaceProtocol == USB_INTERFACE_HID_PROTOCOL_MS) {
Print (L"Type: Mouse\n\r");
}
break;
case USB_INTERFACE_CLASS_STORAGE:
Print (L"Type: Mass Storage\n\r");
break;
case USB_INTERFACE_CLASS_HUB:
Print (L"Type: Hub\n\r");
break;
default:
Print (L"Type: Unkown\n\r");
break;
}
}
/* Not a device */
else continue;
Status = UsbDevice->UsbGetDeviceDescriptor (UsbDevice, &DeviceDescriptor);
if (!EFI_ERROR (Status)) {
/* Manufacturer */
StrManufacturer = NULL;
Status = UsbDevice->UsbGetStringDescriptor (UsbDevice, LANGID_ENGLISH, DeviceDescriptor.StrManufacturer, &StrManufacturer);
if (!EFI_ERROR (Status)) {
Print (L"Manufacturer: %s\n\r", StrManufacturer);
}
/* Product */
StrProduct = NULL;
Status = UsbDevice->UsbGetStringDescriptor (UsbDevice, LANGID_ENGLISH, DeviceDescriptor.StrProduct, &StrProduct);
if (!EFI_ERROR (Status)) {
Print (L"Product: %s\n\r", StrProduct);
}
/* Serial number */
StrSerialNumber = NULL;
Status = UsbDevice->UsbGetStringDescriptor (UsbDevice, LANGID_ENGLISH, DeviceDescriptor.StrSerialNumber, &StrSerialNumber);
if (!EFI_ERROR (Status)) {
Print (L"Serial number: %s\n\r", StrSerialNumber);
}
}
/* List device path */
Status = gBS->HandleProtocol (UsbDeviceHandle[Index], &gEfiDevicePathProtocolGuid, (VOID **) &UsbDevicePath);
if (!EFI_ERROR (Status)) {
Print (L"Device Path: %s\n\r", Path2Text->ConvertDevicePathToText(UsbDevicePath, FALSE, TRUE));
}
Print (L"\n\r");
}
return EFI_SUCCESS;
}
最后在shell 下面结果: