转载于http://www.misssir.cn/art/_show.aspx?art=44 摘要: 从主控开始遍历,先是RootHub,然后每个端口,端口连接的设备类型、描述符,如果是Hub则继续向下遍历。代码已贴出来,如果您看到附件中的样例,会不会感觉和DDK中的usbview很像呢? |
USB View是DDK中的示例程序,以前我也看过,感觉有点乱,这些天我有的是时间,就模仿它用VC++重新写了一个。全部代码如下:
//这里没有考虑释放句柄的问题,实际应用的时候要添上 //--------------------------------------------------------------------------
//USB设备在Windows中的显示名字 char* GetUsbDeviceLabel(char* key_name) { HDEVINFO di = SetupDiGetClassDevs(&GUID_CLASS_USB_DEVICE, 0, 0, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
if(di == INVALID_HANDLE_VALUE) { MyPrintf("没有找到"); return 0; }
for(int i = 0; ; i++) { BYTE tmp_buf1[513];
//主控的描述字符串 SP_DEVINFO_DATA DevInfoData; DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if(! SetupDiEnumDeviceInfo(di, i, &DevInfoData)) break;
if(! SetupDiGetDeviceRegistryProperty(di, &DevInfoData, SPDRP_DRIVER, 0, tmp_buf1, 513, 0)) continue;
if(strcmp(key_name, (char*)tmp_buf1) != 0) continue;
if(SetupDiGetDeviceRegistryProperty(di, &DevInfoData, SPDRP_DEVICEDESC, 0, tmp_buf1, 513, 0)) { strcpy(key_name, (char*)tmp_buf1); return key_name; } else { return 0; } } return 0; }
void GetPortDevDescString(HANDLE hub, int port_idx, USB_DEVICE_DESCRIPTOR* dev_desc) { //读语言的种类 BYTE tmp_buf1[513] = {0}; DWORD data_len; USB_DESCRIPTOR_REQUEST* str_req = (USB_DESCRIPTOR_REQUEST*)tmp_buf1; USB_STRING_DESCRIPTOR* str_desc = (USB_STRING_DESCRIPTOR*)(tmp_buf1 + sizeof(USB_DESCRIPTOR_REQUEST) - 1); int LanIDs_num = 0; WORD* LanIDs = 0; int i;
str_req->ConnectionIndex = port_idx; str_req->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) | 0; str_req->SetupPacket.wIndex = 0; str_req->SetupPacket.wLength = (USHORT)(513 - sizeof(USB_DESCRIPTOR_REQUEST) + 1);
if(! DeviceIoControl(hub, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, str_req, 513, str_req, 513, &data_len, 0)) { LanIDs_num = 0; LanIDs = 0; } else { LanIDs_num = (str_desc->bLength - 2) / 2; LanIDs = str_desc->bString; }
//读语言 BYTE tmp_buf2[513] = {0}; str_req = (USB_DESCRIPTOR_REQUEST*)tmp_buf2; str_desc = (USB_STRING_DESCRIPTOR*)(tmp_buf2 + sizeof(USB_DESCRIPTOR_REQUEST) - 1);
//输出 MyPrintf("Device Descriptor:"); MyPrintf("bcdUSB: 0x%04X", dev_desc->bcdUSB); MyPrintf("bDeviceClass: 0x%02X", dev_desc->bDeviceClass); MyPrintf("bDeviceSubClass: 0x%02X", dev_desc->bDeviceSubClass); MyPrintf("bDeviceProtocol: 0x%02X", dev_desc->bDeviceProtocol); MyPrintf("bMaxPacketSize0: 0x%02X (%d)", dev_desc->bMaxPacketSize0, dev_desc->bMaxPacketSize0); MyPrintf("idVendor: 0x%04X", dev_desc->idVendor); MyPrintf("idProduct: 0x%04X", dev_desc->idProduct); MyPrintf("bcdDevice: 0x%04X", dev_desc->bcdDevice); MyPrintf("iManufacturer: 0x%02X", dev_desc->iManufacturer);
if(dev_desc->iManufacturer != 0) { for (i=0; i< LanIDs_num; i++) { str_req->ConnectionIndex = port_idx; str_req->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) | dev_desc->iManufacturer; str_req->SetupPacket.wIndex = LanIDs[i]; str_req->SetupPacket.wLength = (USHORT)(513 - sizeof(USB_DESCRIPTOR_REQUEST) + 1);
if(! DeviceIoControl(hub, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, str_req, 513, str_req, 513, &data_len, 0)) MyPrintf("0x%04X: 失败", LanIDs[i]); else MyPrintf("0x%04X: \"%S\"", LanIDs[i], str_desc->bString); } }
MyPrintf("iProduct: 0x%02X", dev_desc->iProduct);
if(dev_desc->iProduct != 0) { for (i=0; i< LanIDs_num; i++) { str_req->ConnectionIndex = port_idx; str_req->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) | dev_desc->iProduct; str_req->SetupPacket.wIndex = LanIDs[i]; str_req->SetupPacket.wLength = (USHORT)(513 - sizeof(USB_DESCRIPTOR_REQUEST) + 1);
if(! DeviceIoControl(hub, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, str_req, 513, str_req, 513, &data_len, 0)) MyPrintf("0x%04X: 失败", LanIDs[i]); else MyPrintf("0x%04X: \"%S\"", LanIDs[i], str_desc->bString); } }
MyPrintf("iSerialNumber:: 0x%02X", dev_desc->iSerialNumber);
if(dev_desc->iSerialNumber != 0) { for (i=0; i< LanIDs_num; i++) { memset(str_req, 0, 513); str_req->ConnectionIndex = port_idx; str_req->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) | dev_desc->iSerialNumber; str_req->SetupPacket.wIndex = LanIDs[i]; str_req->SetupPacket.wLength = (USHORT)(513 - sizeof(USB_DESCRIPTOR_REQUEST) + 1);
if(! DeviceIoControl(hub, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, str_req, 513, str_req, 513, &data_len, 0)) MyPrintf("0x%04X: 失败", LanIDs[i]); else MyPrintf("0x%04X: \"%S\"", LanIDs[i], str_desc->bString); } }
MyPrintf("bNumConfigurations: 0x%02X", dev_desc->bNumConfigurations); MyPrintf(""); }
void GetEndpoint(int pip_num, USB_PIPE_INFO* pip_list) { for(int i = 0; i < pip_num; i++) { USB_ENDPOINT_DESCRIPTOR* ep_desc = &(pip_list[i].EndpointDescriptor); MyPrintf("Endpoint Descriptor:");
if(USB_ENDPOINT_DIRECTION_IN(ep_desc->bEndpointAddress)) MyPrintf("bEndpointAddress: 0x%02X IN", ep_desc->bEndpointAddress); else MyPrintf("bEndpointAddress: 0x%02X OUT", ep_desc->bEndpointAddress);
switch(ep_desc->bmAttributes & 0x03) { case 0x00: MyPrintf("Transfer Type: Control"); break; case 0x01: MyPrintf("Transfer Type: Isochronous"); break; case 0x02: MyPrintf("Transfer Type: Bulk"); break; case 0x03: MyPrintf("Transfer Type: Interrupt"); break; } MyPrintf("wMaxPacketSize: 0x%04X (%d)", ep_desc->wMaxPacketSize, ep_desc->wMaxPacketSize);
if(ep_desc->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)) { MyPrintf("bInterval: 0x%02X", ep_desc->bInterval); } else { USB_ENDPOINT_DESCRIPTOR2* ep_desc2 = (USB_ENDPOINT_DESCRIPTOR2*)ep_desc; MyPrintf("wInterval: 0x%04X", ep_desc2->wInterval); MyPrintf("bSyncAddress: 0x%02X", ep_desc2->bSyncAddress); }
MyPrintf(""); } }
void GetPortConfDescString(USB_CONFIGURATION_DESCRIPTOR* conf_desc) { BYTE* desc_end = (BYTE*)conf_desc + conf_desc->wTotalLength; BYTE* desc_start = (BYTE*)conf_desc;
while((desc_start + sizeof(USB_COMMON_DESCRIPTOR) < desc_end) && (desc_start + ((USB_COMMON_DESCRIPTOR*)desc_start)->bLength <= desc_end)) { BYTE type = ((USB_COMMON_DESCRIPTOR*)desc_start)->bDescriptorType;
if(type == USB_CONFIGURATION_DESCRIPTOR_TYPE) { USB_CONFIGURATION_DESCRIPTOR* conf2 = (USB_CONFIGURATION_DESCRIPTOR*)desc_start;
MyPrintf("Configuration Descriptor:"); MyPrintf("wTotalLength: 0x%04X", conf2->wTotalLength); MyPrintf("bNumInterfaces: 0x%02X", conf2->bNumInterfaces); MyPrintf("bConfigurationValue: 0x%02X", conf2->bConfigurationValue); MyPrintf("iConfiguration: 0x%02X", conf2->iConfiguration);
char power[100] = {0}; if (conf_desc->bmAttributes & 0x80) strcat(power, "Bus Powered "); if (conf_desc->bmAttributes & 0x40) strcat(power, "Self Powered "); if (conf_desc->bmAttributes & 0x20) strcat(power, "Remote Wakeup");
MyPrintf("bmAttributes: 0x%02X (%s)", conf2->bmAttributes, power); MyPrintf("MaxPower: 0x%02X (%d mA)", conf2->MaxPower, conf_desc->MaxPower * 2);
} else if(type == USB_INTERFACE_DESCRIPTOR_TYPE) { USB_INTERFACE_DESCRIPTOR* intf2 = (USB_INTERFACE_DESCRIPTOR*)desc_start; char* str2;
MyPrintf("Interface Descriptor:"); MyPrintf("bInterfaceNumber: 0x%02X", intf2->bInterfaceNumber); MyPrintf("bAlternateSetting: 0x%02X", intf2->bAlternateSetting); MyPrintf("bNumEndpoints: 0x%02X", intf2->bNumEndpoints);
str2 = ""; switch(intf2->bInterfaceClass) { case USB_DEVICE_CLASS_AUDIO: str2 = "(Audio)"; break; case USB_DEVICE_CLASS_HUMAN_INTERFACE: str2 = "(HID)"; break; case USB_DEVICE_CLASS_HUB: str2 = "(Hub)"; break; } MyPrintf("bInterfaceClass: 0x%02X %s", intf2->bInterfaceClass, str2);
str2 = ""; if(intf2->bInterfaceClass == USB_DEVICE_CLASS_AUDIO) { switch (intf2->bInterfaceSubClass) { case USB_AUDIO_SUBCLASS_AUDIOCONTROL: str2 = " (Audio Control)"; break; case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: str2 = " (Audio Streaming)"; break; case USB_AUDIO_SUBCLASS_MIDISTREAMING: str2 = " (MIDI Streaming)"; break; } } MyPrintf("bInterfaceSubClass: 0x%02X %s", intf2->bInterfaceSubClass, str2); MyPrintf("bInterfaceProtocol: 0x%02X", intf2->bInterfaceProtocol); MyPrintf("iInterface: 0x%02X", intf2->iInterface);
if(intf2->bLength == sizeof(USB_INTERFACE_DESCRIPTOR2)) { USB_INTERFACE_DESCRIPTOR2* intf3 = (PUSB_INTERFACE_DESCRIPTOR2)intf2; MyPrintf("wNumClasses: 0x%04X", intf3->wNumClasses); } } else if(type == USB_ENDPOINT_DESCRIPTOR_TYPE) { USB_ENDPOINT_DESCRIPTOR* end2 = (USB_ENDPOINT_DESCRIPTOR*)desc_start; MyPrintf("Endpoint Descriptor:");
if (USB_ENDPOINT_DIRECTION_IN(end2->bEndpointAddress)) MyPrintf("bEndpointAddress: 0x%02X IN", end2->bEndpointAddress); else MyPrintf("bEndpointAddress: 0x%02X OUT", end2->bEndpointAddress);
switch (end2->bmAttributes & 0x03) { case 0x00: MyPrintf("Transfer Type: Control"); break; case 0x01: MyPrintf("Transfer Type: Isochronous"); break; case 0x02: MyPrintf("Transfer Type: Bulk"); break; case 0x03: MyPrintf("Transfer Type: Interrupt"); break; } MyPrintf("wMaxPacketSize: 0x%04X (%d)", end2->wMaxPacketSize, end2->wMaxPacketSize);
if (end2->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)) { MyPrintf("bInterval: 0x%02X", end2->bInterval); } else { USB_ENDPOINT_DESCRIPTOR2* end3 = (USB_ENDPOINT_DESCRIPTOR2*)end2; MyPrintf("wInterval: 0x%04X", end3->wInterval); MyPrintf("bSyncAddress: 0x%02X", end3->bSyncAddress); } } else if(type == USB_HID_DESCRIPTOR_TYPE) { USB_HID_DESCRIPTOR* hid2 = (USB_HID_DESCRIPTOR*)desc_start; MyPrintf("HID Descriptor:"); MyPrintf("bcdHID: 0x%04X", hid2->bcdHID); MyPrintf("bCountryCode: 0x%02X", hid2->bCountryCode); MyPrintf("bNumDescriptors: 0x%02X", hid2->bNumDescriptors); for(int i = 0; i < hid2->bNumDescriptors; i++) { MyPrintf("bDescriptorType: 0x%02X", hid2->OptionalDescriptors[i].bDescriptorType); MyPrintf("wDescriptorLength: 0x%04X", hid2->OptionalDescriptors[i].wDescriptorLength); } } else { MyPrintf("未知的描述符"); } desc_start += ((USB_COMMON_DESCRIPTOR*)desc_start)->bLength; MyPrintf(""); } }
bool GetHubPort(HANDLE hub, int port_idx) { BYTE tmp_buf1[513] = {0}; BYTE tmp_buf2[513] = {0}; DWORD data_len;
USB_NODE_CONNECTION_INFORMATION_EX* conn_info = (USB_NODE_CONNECTION_INFORMATION_EX*)tmp_buf1; conn_info->ConnectionIndex = port_idx;
if(! DeviceIoControl(hub, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, conn_info, 513, conn_info, 513, &data_len, 0)) { MyPrintf("端口%d连接失败", port_idx); return false; } if (conn_info->ConnectionStatus == NoDeviceConnected) { MyPrintf("[Port%d]NoDeviceConnected", port_idx); } else { USB_NODE_CONNECTION_DRIVERKEY_NAME* key_name = (USB_NODE_CONNECTION_DRIVERKEY_NAME*)tmp_buf2; key_name->ConnectionIndex = port_idx;
if(! DeviceIoControl(hub, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, key_name, 513, key_name, 513, &data_len, 0)) { MyPrintf("[Port%d]DeviceConnected: 失败 \n", port_idx); } else { char* label = GetUsbDeviceLabel(WideStrToMultiStr(key_name->DriverKeyName)); if(label != 0) MyPrintf("[Port%d]DeviceConnected: %s \n", port_idx, label); else MyPrintf("[Port%d]DeviceConnected: 失败 \n", port_idx); } gLevel++;
//读设备的字符串 GetPortDevDescString(hub, port_idx, &(conn_info->DeviceDescriptor));
//连接状态信息 MyPrintf("ConnectionStatus: %s", gHubPortConn[conn_info->ConnectionStatus]); MyPrintf("Current Config Value: 0x%02X", conn_info->CurrentConfigurationValue); switch(conn_info->Speed) { case UsbLowSpeed: MyPrintf("Device Bus Speed: Low"); break; case UsbFullSpeed: MyPrintf("Device Bus Speed: Full"); break; case UsbHighSpeed: MyPrintf("Device Bus Speed: High"); break; default: MyPrintf("Device Bus Speed: Unknown"); } MyPrintf("Device Address: 0x%02X", conn_info->DeviceAddress); MyPrintf("Open Pipes: %2d", conn_info->NumberOfOpenPipes); MyPrintf("");
//端点描述符 GetEndpoint(conn_info->NumberOfOpenPipes, conn_info->PipeList);
//配置描述符 if(conn_info->ConnectionStatus == DeviceConnected) { USB_DESCRIPTOR_REQUEST* conf_req = (USB_DESCRIPTOR_REQUEST*)tmp_buf2; USB_CONFIGURATION_DESCRIPTOR* conf_desc = (USB_CONFIGURATION_DESCRIPTOR*)(tmp_buf2 + sizeof(USB_DESCRIPTOR_REQUEST) - 1);
conf_req->ConnectionIndex = port_idx; conf_req->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | 0; conf_req->SetupPacket.wIndex = 0; conf_req->SetupPacket.wLength = (USHORT)(513 - sizeof(USB_DESCRIPTOR_REQUEST) + 1);
//读配置描述符等 if(DeviceIoControl(hub, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, conf_req, 513, conf_req, 513, &data_len, 0)) GetPortConfDescString(conf_desc); else MyPrintf("读配置描述符失败 \n"); }
if(conn_info->DeviceIsHub) { USB_NODE_CONNECTION_NAME* hub_name = (USB_NODE_CONNECTION_NAME*)tmp_buf2; hub_name->ConnectionIndex = port_idx;
if(! DeviceIoControl(hub, IOCTL_USB_GET_NODE_CONNECTION_NAME, 0, 0, hub_name, 513, &data_len, 0)) { MyPrintf("不能得到连接的Hub的名字"); return false; } else { if(! GetHub(WideStrToMultiStr(hub_name->NodeName))) return false; } } gLevel--; } return true; }
bool GetHub(char* hub_name) { gLevel++; MyPrintf("Root Hub: %s", hub_name);
BYTE tmp_buf1[513] = {0}; char* hub_path = (char*)tmp_buf1; strcat(hub_path, "\\\\.\\"); strcat(hub_path, hub_name);
HANDLE hub = CreateFile(hub_path, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if(hub == INVALID_HANDLE_VALUE) { MyPrintf("打开Hub失败"); return false; }
USB_NODE_INFORMATION* hub_info = (USB_NODE_INFORMATION*)tmp_buf1; USB_HUB_DESCRIPTOR* hub_desc = &(hub_info->u.HubInformation.HubDescriptor); DWORD data_len; if(! DeviceIoControl(hub, IOCTL_USB_GET_NODE_INFORMATION, 0, 0, hub_info, 513, &data_len, 0)) { MyPrintf("获得端口信息失败"); return false; }
if(hub_info->u.HubInformation.HubIsBusPowered) MyPrintf("Hub Power: Bus Power"); else MyPrintf("Hub Power: Self Power");
MyPrintf("Number of Ports: %d", hub_desc->bNumberOfPorts);
switch(hub_desc->wHubCharacteristics & 0x0003) { case 0x0000: MyPrintf("Power switching: Ganged"); break; case 0x0001: MyPrintf("Power switching: Individual"); break; case 0x0002: case 0x0003: MyPrintf("Power switching: None"); break; } switch (hub_desc->wHubCharacteristics & 0x0004) { case 0x0000: MyPrintf("Compound device: No"); break; case 0x0004: MyPrintf("Compound device: Yes"); break; } switch (hub_desc->wHubCharacteristics & 0x0018) { case 0x0000: MyPrintf("Over-current Protection: Global"); break; case 0x0008: MyPrintf("Over-current Protection: Individual"); break; case 0x0010: case 0x0018: MyPrintf("No Over-current Protection (Bus Power Only)"); break; } MyPrintf("");
for(int port_idx = 1; port_idx <= hub_desc->bNumberOfPorts; port_idx++) { if(! GetHubPort(hub, port_idx)) return false; }
gLevel--; return true; }
bool GetHostControll() { gLevel++; HDEVINFO di = SetupDiGetClassDevs(&GUID_CLASS_USB_HOST_CONTROLLER, 0, 0, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
if(di == INVALID_HANDLE_VALUE) { MyPrintf("没有找到主控类的设备"); return false; }
for(int i = 0; ; i++) { BYTE tmp_buf1[513]; DWORD data_len;
//枚举类别中每一个主控 SP_DEVICE_INTERFACE_DATA ifdata; ifdata.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
if(! SetupDiEnumDeviceInterfaces(di, 0, &GUID_CLASS_USB_HOST_CONTROLLER, i, &ifdata)) { MyPrintf("USB主控类中再没有其它设备了 \n"); break; }
//主控的描述字符串 SP_DEVINFO_DATA DevInfoData; DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if(SetupDiEnumDeviceInfo(di, i, &DevInfoData)) { if(SetupDiGetDeviceRegistryProperty(di, &DevInfoData, SPDRP_DEVICEDESC, 0, tmp_buf1, 513, 0)) { MyPrintf("%s", (char*)tmp_buf1); } if(SetupDiGetDeviceRegistryProperty(di, &DevInfoData, SPDRP_HARDWAREID, 0, tmp_buf1, 513, 0)) { MyPrintf("%s", (char*)tmp_buf1); } }
//主控的路径 SP_DEVICE_INTERFACE_DETAIL_DATA* ifdetail = (SP_DEVICE_INTERFACE_DETAIL_DATA*)tmp_buf1; ifdetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if(! SetupDiGetDeviceInterfaceDetail(di, &ifdata, ifdetail, 513, 0, 0)) { MyPrintf("获得主控的设备路径失败"); return false; }
//打开主控 HANDLE host = CreateFile(ifdetail->DevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if(host == INVALID_HANDLE_VALUE) { MyPrintf("打开主控失败"); return false; }
USB_HCD_DRIVERKEY_NAME* key_name = (USB_HCD_DRIVERKEY_NAME*)tmp_buf1;
if(! DeviceIoControl(host, IOCTL_GET_HCD_DRIVERKEY_NAME, 0, 0, key_name, 513, &data_len, 0)) MyPrintf("DriverKey: 失败"); else MyPrintf("DriverKey: %S", key_name->DriverKeyName);
MyPrintf(""); MyPrintf("RootHub \n");
//根Hub的名字(路径) USB_ROOT_HUB_NAME* hub_name = (USB_ROOT_HUB_NAME*)tmp_buf1; if(! DeviceIoControl(host, IOCTL_USB_GET_ROOT_HUB_NAME, 0, 0, hub_name, 513, &data_len, 0)) { MyPrintf("根Hub名字失败"); return false; } else { //枚举Hub下面的设备 if(! GetHub(WideStrToMultiStr(hub_name->RootHubName))) return false; } MyPrintf(""); }
gLevel--; return true; }
void main() { gLevel = 0; MyPrintf("My Computer \n");
if(GetHostControll()) MyPrintf("遍历成功"); else MyPrintf("遍历失败"); } |