USB设备的枚举

本文探讨了如何使用Windows API函数(如SetupDiGetClassDevs和SetupDiEnumDeviceInterfaces)来管理USB设备,包括获取设备信息、枚举设备接口及与设备交互的基本流程。重点介绍了函数的参数意义、返回值解释以及实例代码实现。

我最近在做一个操作USB设备的程序,但在打开设备时遇到了问题.步骤如下,

1.调用SetupDiGetClassDevs.这一部正常获得句柄

2.调用SetupDiEnumDeviceInterfaces,枚举设备.3.两次调用SetupDiGetDeviceInterfaceDetail,获取设备详细信息,设备名.

代码例子:

#define  MAX_SLOT_NUM      64
static char  TotalSlotName[MAX_SLOT_NUM][MAX_PATH];
static PSTR  strSCRName[MAX_SLOT_NUM];
static DWORD TotalSlotNum;
static DWORD checkTokenID;
static GUID  usb_guid = CdRomClassGuid;
DWORD CP11Dlg::USBcheck(  )
{


         HDEVINFO info;
	SP_DEVICE_INTERFACE_DATA xifdata;
	DWORD devindex;
	DWORD needed;
	PSP_INTERFACE_DEVICE_DETAIL_DATA detail;
	SP_DEVINFO_DATA did;
	BOOL  reflag = true;	
         DWORD checkTotalNum = 0;
	DWORD dwDataLen=0;

	info = SetupDiGetClassDevs(&usb_guid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); // All devices present on system
     if(info==INVALID_HANDLE_VALUE)
		  {
			  return FALSE;
			  
		  }  
		  xifdata.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);   
		  for(devindex = 0; SetupDiEnumDeviceInterfaces(info, NULL, &usb_guid, devindex, &xifdata);devindex++)
		  {
			  SetupDiGetDeviceInterfaceDetail(info, &xifdata, NULL, 0, &needed, NULL);
			  detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(needed);
			  detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
			  did.cbSize = sizeof(SP_DEVINFO_DATA);
			  SetupDiGetDeviceInterfaceDetail(info, &xifdata, detail, needed, NULL, &did);			              
			  if(_tcsstr(detail->DevicePath, _T("zteic")))
			  {
				  if(checkTotalNum>MAX_SLOT_NUM)
				  {
                     break;
					 reflag=false;
				  }
				  checkTotalNum++;
				  strcpy(TotalSlotName[checkTotalNum-1], detail->DevicePath);	  			 				 		          			 				 
			  }  	  
		  }	
		  writelog(LOG_INFO,"目前KEY总数为:%d\n",checkTotalNum);
		  
          for( int i = 0;i < (int)checkTotalNum; i++)
		  {
			  
              writelog(LOG_INFO,"id:%s\n",TotalSlotName[i]);
			  
		  }
		  free((void *) detail);
		   SetupDiDestroyDeviceInfoList(info);
		  return reflag;
		 
}
关于其他函数

SetupDiGetClassDevs

HDEVINFO

    SetupDiGetClassDevs(

        IN PGUID  ClassGuid,    /* optional */

        IN PCTSTR  Enumerator,    /* optional */

        IN HWND  hwndParent,    /* optional */

        IN DWORD  Flags

        );

 

SetupDiGetClassDevs returns a device information set that contains all installed devices of a specified class.

获取一个指定类别或全部类别的所有已安装设备的信息

 

Parameters

ClassGuid

Supplies a pointer to the class GUID to use when creating the list of devices. If the DIGCF_ALLCLASSES flag is set, this parameter is ignored and the resulting list contains all installed classes.

一个特定类别GUID(需要查询注册表)的指针,如果设置了DIGCF_ALLCLASSES标记,该参数备忽略,将返回所有类别的设备信息表

 

Enumerator

Supplies the name of the key under the Enum registry branch that contains device instances for which information is to be retrieved. If this parameter is not specified, device information is retrieved for all device instances in the entire Enum tree.

过滤梅举的内容:如:PCI则只显示PCI设备,

 

hwndParent

Supplies the handle of the top-level window to be used for any user interface relating to the members of this set.

用于关联到集合成员中的用户接口的顶层窗口句柄

Flags

Supplies control options used in building the device information set. Can be one of the following values:

建立设备信息表的控制选项,可以是下列值

DIGCF_PRESENT

Return only devices that are currently present.(只列出当前存在的设备信息)

 

DIGCF_ALLCLASSES

Return a list of installed devices for all classes. If this flag is set, the ClassGuid parameter is ignored.(列出所有类别的一安装的设备表,如果设置了此值,则指定的类别将备忽略)

 

DIGCF_PROFILE

Return only devices that are a part of the current hardware profile.(只返回当前硬件概况部分)

Return Value

If the function succeeds, it returns a handle to a device information set containing all installed devices matching the specified parameters.

如成功,返回包含所有与指定参数匹配的已经安装设备信息句柄

 

If the function fails, it returns INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.

如失败则返回INVALID_HANDLE_VALUE

 

 

SetupDiEnumDeviceInfo

 (  
m_hDevInfo, //设备句柄,如果熟悉注册表可以从注册表中指定,VC++也支持默认设备:
  //如GUID_DEVCLASS_SMARTCARDREADER表示读卡器GUID
i, //当前设备连接端口号
&m_DeviceInfoData//第i端口连接设备的详细硬件信息
)
通过USB设备的详细信息可以控制连接设备的相关操作,包括
DICS_DISABLE(驱动卸载),
DICS_ENABLE(驱动重装),
DICS_STOP(设备停用),
DICS_START(设备重启),
当然,如果需要与USB设备进行通信,只需要该USB设备的驱动以及他的LIB、DLL、.H文件就可以通过头文件中的驱动函数访问该设备。

<think>好的,用户想了解USB设备枚举的过程或解决方案。我需要先回忆一下相关知识,并结合提供的引用内容来组织回答。 首先,USB设备枚举的步骤。记得USB设备连接主机后,主机通过一系列控制传输来获取设备描述符、分配地址等。这个过程包括检测设备、复位、获取描述符、设置地址等阶段。需要详细但清晰地解释每个步骤。 然后,解决方案部分。用户可能遇到了枚举失败的问题,需要给出排查方法。比如检查硬件连接、电源、描述符是否正确,还有驱动问题。引用中的内容提到重新安装USB设备、使用libusb库、STM32的配置等,可以引用这些内容来支持解决方案。 还要注意生成相关问题。根据用户的问题,可能需要关于描述符结构、调试工具、STM32配置、HID通讯的问题。 引用部分,引用1提到重新安装设备的代码,引用3和4是STM32的枚举示例,引用2是libusb的应用。需要正确对应到解决方案中的各个部分,比如驱动问题对应引用1,嵌入式开发对应引用3和4,通讯库对应引用2。 最后,确保回答结构清晰,分步骤说明枚举过程和解决方案,语言用中文,符合用户要求。检查是否有遗漏的要点,比如常见错误或工具使用。这样用户能全面了解枚举过程,并解决遇到的问题。</think>### USB设备枚举过程详解 USB设备枚举是主机识别新接入设备并建立通信的关键过程,具体分为6个步骤: 1. **设备检测** 主机通过检测$V_{BUS}$电压变化(4.75-5.25V)感知设备连接,此时设备处于未供电状态[^3] 2. **设备上电** 主机通过集线器提供100mA电流(USB2.0标准),设备进入默认状态(地址0) 3. **描述符获取** 主机发送标准请求: - GET_DESCRIPTOR(DEVICE) → 设备描述符 - GET_DESCRIPTOR(CONFIGURATION) → 配置描述符 设备返回数据结构: ```c typedef struct { uint8_t bLength; // 描述符长度 uint16_t bcdUSB; // USB规范版本 uint8_t bDeviceClass; // 设备类代码 // ...其他字段 } USB_DeviceDescriptor; ``` 4. **地址分配** 主机发送SET_ADDRESS请求: $$ wValue = (新地址 << 8) + 0 $$ 设备响应后使用新地址通信 5. **配置选择** 主机通过SET_CONFIGURATION请求激活设备配置,此时设备进入配置完成状态 6. **驱动加载** 系统根据设备类代码加载对应驱动程序(如HID、Mass Storage等) ### 常见枚举问题解决方案 **问题1:设备无法识别** - 检查硬件:示波器测量$D+/D-$信号幅度(3.3V) - 验证描述符:使用USB协议分析仪捕获数据包 - 驱动修复:参考引用[1]代码实现设备枚举 **问题2:枚举超时** - 调整端点0最大包大小(必须为8/16/32/64字节) - 验证设备响应时间(标准要求<5ms) - 使用Wireshark抓包分析时序 **问题3:配置错误** - 检查配置描述符总长度 - 验证接口/端点描述符的bAlternateSetting设置 - 参考引用[4]的STM32配置指南 ### 开发调试工具建议 1. **USBlyzer**:协议分析工具 2. **Bus Hound**:数据捕获软件 3. **libusb**:跨平台调试库(引用[2])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值