static NTSTATUS UsbChief_SelectInterfaces(IN WDFDEVICE Device) { WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; NTSTATUS Status; PDEVICE_CONTEXT pDeviceContext; PAGED_CODE(); pDeviceContext = GetDeviceContext(Device); WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams); Status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->WdfUsbTargetDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams); if (NT_SUCCESS(Status) && WdfUsbTargetDeviceGetNumInterfaces(pDeviceContext->WdfUsbTargetDevice) > 0) { pDeviceContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; pDeviceContext->NumberConfiguredPipes = configParams.Types.SingleInterface.NumberConfiguredPipes; } return Status; }
/*++ Routine Description: This helper routine selects the configuration, interface and creates a context for every pipe (end point) in that interface. Arguments: Device - Handle to a framework device Return Value: NT status value --*/ NTSTATUS SelectInterfaces(IN WDFDEVICE Device) { WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; NTSTATUS status; PDEVICE_CONTEXT pDeviceContext; UCHAR numInterfaces; PAGED_CODE(); pDeviceContext = GetDeviceContext(Device); numInterfaces = WdfUsbTargetDeviceGetNumInterfaces(pDeviceContext->WdfUsbTargetDevice); if (numInterfaces == 1) { // The device has only 1 interface. PSDrv_DbgPrint(3, ("Device has a single interface!\n")); WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams); status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->WdfUsbTargetDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams); if (NT_SUCCESS(status) && numInterfaces > 0) { pDeviceContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; pDeviceContext->NumberConfiguredPipes = configParams.Types.SingleInterface.NumberConfiguredPipes; } } else { // The device has more then one interface... PSDrv_DbgPrint(3, ("Device has multiple interfaces (%d) - this is not supported yet!\n", numInterfaces)); status = STATUS_NOT_SUPPORTED; } pDeviceContext->nCurrIf = 0; pDeviceContext->nCurrAltIf = 0; return status; }
// 设备配置 // 按照WDF框架,设备配置选项默认为1;如存在多个配置选项,需要切换选择的话,会比较麻烦。 // 一种办法是:使用初始化宏:WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_INTERFACES_DESCRIPTORS // 使用这个宏,需要首先获取配置描述符,和相关接口描述符。 // 另一种办法是:使用WDM方法,先构建一个配置选择的URB,然后要么自己调用IRP发送到总线驱动, // 要么使用WDF方法调用WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_URB初始化宏。 // NTSTATUS DrvClass::ConfigureUsbDevice() { WDF_USB_DEVICE_SELECT_CONFIG_PARAMS usbConfig; WDF_USB_INTERFACE_SELECT_SETTING_PARAMS interfaceSelectSetting; KDBG(DPFLTR_INFO_LEVEL, "[ConfigureUsbDevice]"); // 创建Usb设备对象。 // USB设备对象是我们进行USB操作的起点。大部分的USB接口函数,都是针对它进行的。 // USB设备对象被创建后,由驱动自己维护;框架本身不处理它,也不保持它。 NTSTATUS status = WdfUsbTargetDeviceCreate(m_hDevice, WDF_NO_OBJECT_ATTRIBUTES, &m_hUsbDevice); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_INFO_LEVEL, "WdfUsbTargetDeviceCreate failed with status 0x%08x\n", status); return status; } // 接口配置 // WDF提供了多种接口配置的初始化宏,分别针对单一接口、多接口的USB设备, // 初始化宏还提供了在多个配置间进行切换的途径,正如上面所讲过的。 // 在选择默认配置的情况下,设备配置将无比简单,简单到令长期受折磨的内核程序员大跌眼镜; // 因为WDM上百行的代码逻辑,这里只要两三行就够了。 UCHAR numInterfaces = WdfUsbTargetDeviceGetNumInterfaces(m_hUsbDevice); if(1 == numInterfaces) { KDBG(DPFLTR_INFO_LEVEL, "There is one interface.", status); WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&usbConfig); } else// 多接口 { KDBG(DPFLTR_INFO_LEVEL, "There are %d interfaces.", numInterfaces); PWDF_USB_INTERFACE_SETTING_PAIR settingPairs = (WDF_USB_INTERFACE_SETTING_PAIR*) ExAllocatePoolWithTag(PagedPool, sizeof(WDF_USB_INTERFACE_SETTING_PAIR) * numInterfaces, POOLTAG); if (settingPairs == NULL) return STATUS_INSUFFICIENT_RESOURCES; int nNum = InitSettingPairs(m_hUsbDevice, settingPairs, numInterfaces); WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES(&usbConfig, nNum, settingPairs); } status = WdfUsbTargetDeviceSelectConfig(m_hUsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &usbConfig); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_INFO_LEVEL, "WdfUsbTargetDeviceSelectConfig failed with status 0x%08x\n", status); return status; } // 保存接口 if(1 == numInterfaces) { m_hUsbInterface = usbConfig.Types.SingleInterface.ConfiguredUsbInterface; // 使用SINGLE_INTERFACE接口配置宏,接口的AltSetting值默认为0。 // 下面两行代码演示了如何手动修改某接口的AltSetting值(此处为1). WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&interfaceSelectSetting, 1); status = WdfUsbInterfaceSelectSetting(m_hUsbInterface, WDF_NO_OBJECT_ATTRIBUTES, &interfaceSelectSetting); } else { int i; m_hUsbInterface = usbConfig.Types.MultiInterface.Pairs[0].UsbInterface; for(i = 0; i < numInterfaces; i++) m_hMulInterfaces[i] = usbConfig.Types.MultiInterface.Pairs[i].UsbInterface; } return status; }
NTSTATUS CySelectInterfaces( __in WDFDEVICE Device ) { NTSTATUS NTStatus; PDEVICE_CONTEXT pDeviceContext; BYTE altSettings; PAGED_CODE(); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"Start CySelectInterfaces\n"); pDeviceContext = CyGetDeviceContext(Device); pDeviceContext->ucNumberOfInterface = WdfUsbTargetDeviceGetNumInterfaces(pDeviceContext->CyUsbDevice); /*if(pDeviceContext->ucNumberOfInterface == 1)*/ { CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP," Single interface\n"); pDeviceContext->bIsMultiplInterface = FALSE; WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&pDeviceContext->UsbInterfaceConfig); } //else //{ // CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"Multiple interface :0x%x\n",pDeviceContext->ucNumberOfInterface); // pDeviceContext->bIsMultiplInterface = TRUE; // pDeviceContext->MultipleInterfacePair = ExAllocatePoolWithTag(PagedPool, // sizeof(WDF_USB_INTERFACE_SETTING_PAIR) * pDeviceContext->ucNumberOfInterface, // CYMEM_TAG // ); // if (pDeviceContext->MultipleInterfacePair == NULL) // { // CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"Insufficient resources\n"); // return STATUS_INSUFFICIENT_RESOURCES; // } // // // // Call driver-defined routine to populate the // // WDF_USB_INTERFACE_SETTING_PAIR structures // // that ExAllocatePoolWithTag allocated. // // // InitInterfacePair( // pDeviceContext->CyUsbDevice, // pDeviceContext->MultipleInterfacePair, // pDeviceContext->ucNumberOfInterface // ); // WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES( // &pDeviceContext->UsbInterfaceConfig, // pDeviceContext->ucNumberOfInterface, // pDeviceContext->MultipleInterfacePair // ); //} NTStatus = WdfUsbTargetDeviceSelectConfig(pDeviceContext->CyUsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &pDeviceContext->UsbInterfaceConfig); if(!NT_SUCCESS(NTStatus)) { CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceSelectConfig failed %!STATUS! \n", NTStatus); return NTStatus; } pDeviceContext->ucNumAltSettigns = WdfUsbInterfaceGetNumSettings(pDeviceContext->UsbInterfaceConfig.Types.SingleInterface.ConfiguredUsbInterface); pDeviceContext->ucActiveAltSettings = 0; /* First active alternat settings will be ZERO */ pDeviceContext->ucActiveConfigNum = 0; // This is the defaul configuration number if(!(pDeviceContext->bIsMultiplInterface)) {//single interface CyGetActiveAltInterfaceConfig(pDeviceContext); } else {// Multiple interface cyGetMultipleInterfaceConfig(pDeviceContext); } pDeviceContext->ucNumberOfInterfaceCompositUSB30Only = 0; // intialize // Check if device is USB3.0 then parse the device configuration and store SS EP information if(pDeviceContext->UsbDeviceDescriptor.bcdUSB == USB30MAJORVER) { /* RTL_OSVERSIONINFOW lpVersionInformation= {0}; //WORKAROUND : WIN 8 based xHCI does not provide USBDI version of xHCI driver stack, so adding this works around to differenciate OS // Get the OS version if it is WIN 8 then we do not need to parse the descriptor table to get the MaxBurst other paramter as it is being added to MaxPacketSize in Windows 9 if(RtlGetVersion(&lpVersionInformation)==STATUS_SUCCESS) { CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"Operting System Version information\n"); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"dwMajorVersion:%x dwMinorVersion:%x dwBuildNumber:%x\n",lpVersionInformation.dwMajorVersion ,lpVersionInformation.dwMinorVersion ,lpVersionInformation.dwBuildNumber); } if(!((lpVersionInformation.dwMajorVersion==6) && (lpVersionInformation.dwMinorVersion ==2)))*/ CyGetAndParseUSB30DeviceConfiguration(pDeviceContext); } CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"End CySelectInterfaces\n"); return NTStatus; }