枚举USB设备(代码)
来源:互联网 发布:手机淘宝外卖 编辑:程序博客网 时间:2024/05/01 05:25
枚举USB设备(代码)
转载于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("遍历失败");
}
- 枚举USB设备(代码)
- 枚举所有USB设备代码
- USB设备枚举
- 枚举USB设备
- MFC 枚举USB设备
- USB设备枚举[转载]
- 枚举usb设备
- USB设备枚举过程
- USB设备的枚举
- usb设备枚举过程
- USB设备枚举过程
- USB设备枚举[转载]
- [vc++]枚举USB设备
- USB设备枚举过程
- USB设备枚举/
- 枚举 USB 复合设备
- USB设备枚举过程
- USB设备枚举过程
- Java 垃圾回收 GC
- 浏览器的工作原理:新式网络浏览器幕后揭秘
- 网站开发要知道的事——关于post和get的区别
- JNI 处理数组
- rc.local自启动学习
- 枚举USB设备(代码)
- Linux下使用valgrind做内存泄露检测及绘制函数调用图
- AsyncTask onPostExecute 未执行原因
- Vaadin入门(1)
- oracle取当年天数与当月天数及指定月的天数
- Linux设备驱动学习笔记
- C++四种cast操作符
- Php解析xml
- JAVA_NET_DEMO