static NTSTATUS UsbChief_ReadAndSelectDescriptors(IN WDFDEVICE Device) { PDEVICE_CONTEXT pDeviceContext; NTSTATUS Status; PAGED_CODE(); pDeviceContext = GetDeviceContext(Device); if (!pDeviceContext->WdfUsbTargetDevice) { Status = WdfUsbTargetDeviceCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &pDeviceContext->WdfUsbTargetDevice); if (!NT_SUCCESS(Status)) return Status; } WdfUsbTargetDeviceGetDeviceDescriptor(pDeviceContext->WdfUsbTargetDevice, &pDeviceContext->UsbDeviceDescriptor); return UsbChief_ConfigureDevice(Device); }
/*++ Routine Description: This routine configures the USB device. In this routines we get the device descriptor, the configuration descriptor and select the configuration. Arguments: Device - Handle to a framework device Return Value: NTSTATUS - NT status value. --*/ NTSTATUS ReadAndSelectDescriptors(IN WDFDEVICE Device) { NTSTATUS status; PDEVICE_CONTEXT pDeviceContext; PAGED_CODE(); // initialize variables pDeviceContext = GetDeviceContext(Device); // Create a USB device handle so that we can communicate with the // underlying USB stack. The WDFUSBDEVICE handle is used to query, // configure, and manage all aspects of the USB device. // These aspects include device properties, bus properties, // and I/O creation and synchronization. We only create device the first // the PrepareHardware is called. If the device is restarted by pnp manager // for resource re-balance, we will use the same device handle but then select // the interfaces again because the USB stack could reconfigure the device on // restart. if (pDeviceContext->WdfUsbTargetDevice == NULL) { status = WdfUsbTargetDeviceCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &pDeviceContext->WdfUsbTargetDevice); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(3, ("WdfUsbTargetDeviceCreate failed! (Status = %x)\n", status)); return status; } } WdfUsbTargetDeviceGetDeviceDescriptor(pDeviceContext->WdfUsbTargetDevice, &pDeviceContext->UsbDeviceDescriptor); ASSERT(pDeviceContext->UsbDeviceDescriptor.bNumConfigurations); status = ConfigureDevice(Device); return status; }
NTSTATUS HidFx2EvtDevicePrepareHardware( IN WDFDEVICE Device, IN WDFCMRESLIST ResourceList, IN WDFCMRESLIST ResourceListTranslated ) /*++ Routine Description: In this callback, the driver does whatever is necessary to make the hardware ready to use. In the case of a USB device, this involves reading and selecting descriptors. Arguments: Device - handle to a device ResourceList - A handle to a framework resource-list object that identifies the raw hardware resourcest ResourceListTranslated - A handle to a framework resource-list object that identifies the translated hardware resources Return Value: NT status value --*/ { NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION devContext = NULL; WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; WDF_OBJECT_ATTRIBUTES attributes; PUSB_DEVICE_DESCRIPTOR usbDeviceDescriptor = NULL; UNREFERENCED_PARAMETER(ResourceList); UNREFERENCED_PARAMETER(ResourceListTranslated); PAGED_CODE (); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "HidFx2EvtDevicePrepareHardware Enter\n"); devContext = GetDeviceContext(Device); // // Create a WDFUSBDEVICE object. WdfUsbTargetDeviceCreate obtains the // USB device descriptor and the first USB configuration descriptor from // the device and stores them. It also creates a framework USB interface // object for each interface in the device's first configuration. // // The parent of each USB device object is the driver's framework driver // object. The driver cannot change this parent, and the ParentObject // member or the WDF_OBJECT_ATTRIBUTES structure must be NULL. // // We only create device the first time PrepareHardware is called. If // the device is restarted by pnp manager for resource rebalance, we // will use the same device handle but then select the interfaces again // because the USB stack could reconfigure the device on restart. // if (devContext->UsbDevice == NULL) { status = WdfUsbTargetDeviceCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &devContext->UsbDevice); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceCreate failed 0x%x\n", status); return status; } } // // Select a device configuration by using a // WDF_USB_DEVICE_SELECT_CONFIG_PARAMS structure to specify USB // descriptors, a URB, or handles to framework USB interface objects. // WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams); status = WdfUsbTargetDeviceSelectConfig(devContext->UsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n", status); return status; } devContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; // // Get the device descriptor and store it in device context // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = Device; status = WdfMemoryCreate( &attributes, NonPagedPool, 0, sizeof(USB_DEVICE_DESCRIPTOR), &devContext->DeviceDescriptor, &usbDeviceDescriptor ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfMemoryCreate for Device Descriptor failed %!STATUS!\n", status); return status; } WdfUsbTargetDeviceGetDeviceDescriptor( devContext->UsbDevice, usbDeviceDescriptor ); // // Get the Interrupt pipe. There are other endpoints but we are only // interested in interrupt endpoint since our HID data comes from that // endpoint. Another way to get the interrupt endpoint is by enumerating // through all the pipes in a loop and looking for pipe of Interrupt type. // devContext->InterruptPipe = WdfUsbInterfaceGetConfiguredPipe( devContext->UsbInterface, INTERRUPT_ENDPOINT_INDEX, NULL);// pipeInfo if (NULL == devContext->InterruptPipe) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Failed to get interrupt pipe info\n"); status = STATUS_INVALID_DEVICE_STATE; return status; } // // Tell the framework that it's okay to read less than // MaximumPacketSize // WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(devContext->InterruptPipe); // //configure continuous reader // status = HidFx2ConfigContReaderForInterruptEndPoint(devContext); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "HidFx2EvtDevicePrepareHardware Exit, Status:0x%x\n", status); return status; }
// 并行处理 VOID CY001Drv::DeviceIoControlParallel(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { NTSTATUS status = STATUS_SUCCESS; ULONG ulRetLen = 0; size_t size = 0; void* pBufferInput = NULL; void* pBufferOutput = NULL; KDBG(DPFLTR_INFO_LEVEL, "[DeviceIoControlParallel] CtlCode:0x%0.8X", IoControlCode); // 取得输入缓冲区,判断其有效性 if(InputBufferLength){ status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &pBufferInput, &size); if(status != STATUS_SUCCESS || pBufferInput == NULL || size < InputBufferLength){ WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } } // 取得输出缓冲区,判断其有效性 if(OutputBufferLength){ status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &pBufferOutput, &size); if(status != STATUS_SUCCESS || pBufferOutput == NULL || size < OutputBufferLength){ WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } } // // 下面是主处理过程。 // switch(IoControlCode) { // 取得驱动的版本信息 case IOCTL_GET_DRIVER_VERSION: { PDRIVER_VERSION pVersion = (PDRIVER_VERSION)pBufferOutput; ULONG length; char tcsBuffer[120]; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_GET_DRIVER_VERSION"); if(OutputBufferLength < sizeof(DRIVER_VERSION)){ status = STATUS_BUFFER_TOO_SMALL; break; } pVersion->DriverType = DR_WDF; pVersion->FirmwareType = FW_NOT_CY001; ulRetLen = sizeof(DRIVER_VERSION);// 告示返回长度 // 根据String描述符,判断Firmware代码是否已经被加载。 GetStringDes(2, 0, tcsBuffer, 120, &length); if(length){ WCHAR* pCyName = L"CY001 V"; size_t len; int nIndex; if(length < 8) break; RtlStringCchLengthW(pCyName, 7, &len); for(nIndex = 0; nIndex < len; nIndex++){ if(pCyName[nIndex] != ((WCHAR*)tcsBuffer)[nIndex]) break; } if(nIndex == len) pVersion->FirmwareType = FW_CY001; // 完全相符,说明新版Firmware已经加载到开发板。 } break; } // 收到App发送过来的一个同步Request,我们应该把它保存到同步Queue中,等到有同步事件发生的时候再从Queue中取出并完成。 case IOCTL_USB_SYNC: KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SYNC"); status = WdfRequestForwardToIoQueue(Request, m_hAppSyncManualQueue); // 直接返回,不调用WdfRequestComplete函数。 // 请求者将不会为此而等待;请求的完成在将来的某个时刻。 // 这就是所谓的异步处理之要义了。 if(NT_SUCCESS(status)) return; break; // 清空同步队列中的所有请求 case IOCTL_USB_SYNC_RELEASE: KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SYNC"); ClearSyncQueue(); break; // 应用程序退出,取消所有被阻塞的请求。 case IOCTL_APP_EXIT_CANCEL: // 取消USB设备的所有IO操作。它将连带取消所有Pipe的IO操作。 //WdfIoTargetStop(WdfUsbTargetDeviceGetIoTarget(m_hUsbDevice), WdfIoTargetCancelSentIo); break; // 取得当前的配置号.总是设置为0,因为在WDF框架中,0以外的配置是不被支持的。 case IOCTL_USB_GET_CURRENT_CONFIG: { KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_CURRENT_CONFIG"); if(InputBufferLength < 4){ status = STATUS_INVALID_PARAMETER; break; } *(PULONG)pBufferInput = 0;// 直接赋值0,即总是选择0号配置。也可以发送URB到总线获取当前配置选项。 ulRetLen = sizeof(ULONG); break; } case IOCTL_USB_ABORTPIPE: { ULONG pipenum = *((PULONG) pBufferOutput); KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_ABORTPIPE"); status = AbortPipe(pipenum); } break; // 获取Pipe信息 case IOCTL_USB_GET_PIPE_INFO: { // 遍历获取Pipe信息,复制到输出缓冲中。 BYTE byCurSettingIndex = 0; BYTE byPipeNum = 0; BYTE index; USB_INTERFACE_DESCRIPTOR interfaceDescriptor; WDF_USB_PIPE_INFORMATION pipeInfor; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_PIPE_INFO"); // 取得Pipe数。根据Pipe数计算缓冲区长度 byCurSettingIndex = WdfUsbInterfaceGetConfiguredSettingIndex(m_hUsbInterface); WdfUsbInterfaceGetDescriptor(m_hUsbInterface, byCurSettingIndex, &interfaceDescriptor); byPipeNum = WdfUsbInterfaceGetNumConfiguredPipes(m_hUsbInterface); if(OutputBufferLength < byPipeNum * sizeof(pipeInfor)){ status = STATUS_BUFFER_TOO_SMALL; // 缓冲区不足 }else{ ulRetLen = byPipeNum*sizeof(pipeInfor); // 遍历获取全部管道信息,拷贝到输出缓冲中。 // 应用程序得到输出缓冲的时候,也应该使用WDF_USB_PIPE_INFORMATION结构体解析缓冲区。 for(index = 0; index < byPipeNum; index++) { WDF_USB_PIPE_INFORMATION_INIT(&pipeInfor); WdfUsbInterfaceGetEndpointInformation(m_hUsbInterface, byCurSettingIndex, index, &pipeInfor); RtlCopyMemory((PUCHAR)pBufferOutput + index*pipeInfor.Size, &pipeInfor, sizeof(pipeInfor)); } } } break; // 获取设备描述符 case IOCTL_USB_GET_DEVICE_DESCRIPTOR: { USB_DEVICE_DESCRIPTOR UsbDeviceDescriptor; WdfUsbTargetDeviceGetDeviceDescriptor(m_hUsbDevice, &UsbDeviceDescriptor); KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_DEVICE_DESCRIPTOR"); // 判断输入缓冲区的长度是否足够长 if(OutputBufferLength < UsbDeviceDescriptor.bLength) status = STATUS_BUFFER_TOO_SMALL; else{ RtlCopyMemory(pBufferOutput, &UsbDeviceDescriptor, UsbDeviceDescriptor.bLength); ulRetLen = UsbDeviceDescriptor.bLength; } break; } // 获取字符串描述符 case IOCTL_USB_GET_STRING_DESCRIPTOR: { PGET_STRING_DESCRIPTOR Input = (PGET_STRING_DESCRIPTOR)pBufferInput; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_STRING_DESCRIPTOR"); status = GetStringDes(Input->Index, Input->LanguageId, pBufferOutput, OutputBufferLength, &ulRetLen); // 由字符长度调整为字节长度 if(NT_SUCCESS(status) && ulRetLen > 0) ulRetLen *= (sizeof(WCHAR)/sizeof(char)); break; } // 获取配置描述信息。 case IOCTL_USB_GET_CONFIGURATION_DESCRIPTOR: { KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_CONFIGURATION_DESCRIPTOR"); // 首先获得配置描述符的长度。 status = WdfUsbTargetDeviceRetrieveConfigDescriptor(m_hUsbDevice, NULL, (USHORT*)&size); if(!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) break; // 输出缓冲区不够长 if(OutputBufferLength < size) break; // 正式取得配置描述符。 status = WdfUsbTargetDeviceRetrieveConfigDescriptor(m_hUsbDevice, pBufferOutput, (USHORT*)&size); if(!NT_SUCCESS(status)) break; ulRetLen = size; break; } // 根据可选值配置接口 case IOCTL_USB_SET_INTERFACE: { BYTE byAlterSetting = *(BYTE*)pBufferInput; BYTE byCurSetting = WdfUsbInterfaceGetConfiguredSettingIndex(m_hUsbInterface); // 当前Alternate值 KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SETINTERFACE"); if(InputBufferLength < 1 || OutputBufferLength < 1) { status = STATUS_BUFFER_TOO_SMALL; break; } // 如果传入的可选值与当前的不同,则重新配置接口; // 否则直接返回。 if(byCurSetting != byAlterSetting) { WDF_USB_INTERFACE_SELECT_SETTING_PARAMS par; WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&par, byAlterSetting); status = WdfUsbInterfaceSelectSetting(m_hUsbInterface, NULL, &par); } *(BYTE*)pBufferOutput = byCurSetting; break; } // 固件Rest。自定义命令,与Port Rest是两码事。 case IOCTL_USB_FIRMWRAE_RESET: { KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_FIRMWRAE_RESET"); if(InputBufferLength < 1 || pBufferInput == NULL) status = STATUS_INVALID_PARAMETER; else status = FirmwareReset(*(char*)pBufferInput); break; } // 重置USB总线端口 case IOCTL_USB_PORT_RESET: { KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_PORT_RESET"); WdfUsbTargetDeviceResetPortSynchronously(m_hUsbDevice); break; } // 管道重置 case IOCTL_USB_PIPE_RESET: { UCHAR uchPipe; WDFUSBPIPE pipe = NULL; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_PIPE_RESET"); if(InputBufferLength < 1){ status = STATUS_INVALID_PARAMETER; break; } // 根据ID找到对应的Pipe uchPipe = *(UCHAR*)pBufferInput; pipe = WdfUsbInterfaceGetConfiguredPipe(m_hUsbInterface, uchPipe, NULL); if(pipe == NULL){ status = STATUS_INVALID_PARAMETER; break; } status = WdfUsbTargetPipeResetSynchronously(pipe, NULL, NULL); break; } // 中断管道,放弃管道当前正在进行的操作 case IOCTL_USB_PIPE_ABORT: { UCHAR uchPipe; WDFUSBPIPE pipe = NULL; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_PIPE_ABORT"); if(InputBufferLength < 1){ status = STATUS_INVALID_PARAMETER; break; } // 根据ID找到对应的Pipe uchPipe = *(UCHAR*)pBufferInput; pipe = WdfUsbInterfaceGetConfiguredPipe(m_hUsbInterface, uchPipe, NULL); if(pipe == NULL){ status = STATUS_INVALID_PARAMETER; break; } status = WdfUsbTargetPipeAbortSynchronously(pipe, NULL, NULL); break; } // 取得驱动错误信息,驱动总是把最后一次发现的错误保存在设备对象的环境块中。 // 这个逻辑虽然实现了,但目前的版本中,应用程序并没有利用这个接口。 case IOCTL_USB_GET_LAST_ERROR: { KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_LAST_ERROR"); if (OutputBufferLength >= sizeof(ULONG)) *((PULONG)pBufferOutput) = m_ulLastUSBErrorStatusValue; else status = STATUS_BUFFER_TOO_SMALL; ulRetLen = sizeof(ULONG); break; } // Clear feature命令 case IOCTL_USB_SET_CLEAR_FEATURE: { KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SET_CLEAR_FEATURE"); status = UsbSetOrClearFeature(Request); break; } // 为USB设备加载固件程序。带有偏移量参数,用这个分支;不带偏移量,可用下一个分支。 // 带偏移量的情况下,固件代码是一段一段地加载; // 不带偏移量的情况,固件代码作为一整块一次性被加载。 case IOCTL_FIRMWARE_UPLOAD_OFFSET: { void* pData = pBufferOutput; WORD offset = 0; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_FIRMWARE_UPLOAD_OFFSET"); if(InputBufferLength < sizeof(WORD)){ status = STATUS_INVALID_PARAMETER; break; } offset = *(WORD*)pBufferInput; status = FirmwareUpload((PUCHAR)pData, OutputBufferLength, offset); break; } // 为USB设备加载固件程序。 case IOCTL_FIRMWARE_UPLOAD: { void* pData = pBufferOutput; KDBG(DPFLTR_INFO_LEVEL, "IOCTL_FIRMWARE_UPLOAD"); status = FirmwareUpload((PUCHAR)pData, InputBufferLength, 0); break; } // 读取开发板设备的RAM内容。RAM也就是内存。 // 每次从同一地址读取的内容可能不尽相同,开发板中固件程序在不断运行,RAM被用来储数据(包括临时数据)。 case IOCTL_FIRMWARE_READ_RAM: { KDBG(DPFLTR_INFO_LEVEL, "IOCTL_FIRMWARE_READ_RAM"); status = ReadRAM(Request, &ulRetLen);// inforVal中保存读取的长度 break; } // 其他的请求 default: { // 一律转发到SerialQueue中去。 WdfRequestForwardToIoQueue(Request, m_hIoCtlSerialQueue); // 命令转发之后,这里必须直接返回,千万不可调用WdfRequestComplete函数。 // 否则会导致一个Request被完成两次的错误。 return; } } // 完成请求 WdfRequestCompleteWithInformation(Request, status, ulRetLen); }
// In this callback, the driver does whatever is necessary to make the hardware ready to use. // In the case of a USB device, this involves reading and selecting descriptors. NTSTATUS HidFx2EvtDevicePrepareHardware( _In_ WDFDEVICE hDevice, _In_ WDFCMRESLIST hResourceList, _In_ WDFCMRESLIST hResourceListTranslated ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION pDevContext = NULL; WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; WDF_OBJECT_ATTRIBUTES attributes; PUSB_DEVICE_DESCRIPTOR pUsbDeviceDescriptor = NULL; UNREFERENCED_PARAMETER(hResourceList); UNREFERENCED_PARAMETER(hResourceListTranslated); PAGED_CODE (); TraceVerbose(DBG_INIT, "(%!FUNC!) Enter\n"); pDevContext = GetDeviceContext(hDevice); // Create a WDFUSBDEVICE object. WdfUsbTargetDeviceCreate obtains the USB device descriptor and the first USB configuration //descriptor from the device and stores them. It also creates a framework USB interface object for each interface in the device's first configuration. // // The parent of each USB device object is the driver's framework driver object. The driver cannot change this parent, and the ParentObject // member or the WDF_OBJECT_ATTRIBUTES structure must be NULL. // // We only create device the first time PrepareHardware is called. If the device is restarted by pnp manager for resource rebalance, we // will use the same device handle but then select the interfaces again because the USB stack could reconfigure the device on restart. if (pDevContext->hUsbDevice == NULL) { status = WdfUsbTargetDeviceCreate(hDevice, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->hUsbDevice); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceCreate failed %!STATUS!\n", status); return status; } } // Select a device configuration by using a WDF_USB_DEVICE_SELECT_CONFIG_PARAMS WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams); status = WdfUsbTargetDeviceSelectConfig(pDevContext->hUsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n", status); return status; } pDevContext->hUsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; // Get the device descriptor and store it in device context WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hDevice; status = WdfMemoryCreate(&attributes, NonPagedPool, 0, sizeof(USB_DEVICE_DESCRIPTOR), &pDevContext->hDeviceDescriptor, &pUsbDeviceDescriptor); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfMemoryCreate for Device Descriptor failed %!STATUS!\n", status); return status; } WdfUsbTargetDeviceGetDeviceDescriptor(pDevContext->hUsbDevice, pUsbDeviceDescriptor); // Get the Interrupt pipe. There are other endpoints but we are only interested in interrupt endpoint since our HID data comes from this pDevContext->hInterruptPipe = WdfUsbInterfaceGetConfiguredPipe(pDevContext->hUsbInterface, INTERRUPT_ENDPOINT_INDEX, NULL); if (NULL == pDevContext->hInterruptPipe) { TraceErr(DBG_PNP, "(%!FUNC!) Failed to get interrupt pipe info\n"); status = STATUS_INVALID_DEVICE_STATE; return status; } // Tell the framework that it's okay to read less than MaximumPacketSize WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDevContext->hInterruptPipe); //configure continuous reader status = HidFx2ConfigContReaderForInterruptEndPoint(pDevContext); TraceVerbose(DBG_INIT, "(%!FUNC!) Exit, Status: %!STATUS!\n", status); return status; }
NTSTATUS AndroidUsbDeviceObject::OnEvtDevicePrepareHardware( WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated) { ASSERT_IRQL_PASSIVE(); // Create a USB device handle so that we can communicate with the underlying // USB stack. The wdf_target_device_ handle is used to query, configure, and // manage all aspects of the USB device. These aspects include device // properties, bus properties, and I/O creation and synchronization. This // call gets the device and configuration descriptors and stores them in // wdf_target_device_ object. NTSTATUS status = WdfUsbTargetDeviceCreate(wdf_device(), WDF_NO_OBJECT_ATTRIBUTES, &wdf_target_device_); ASSERT(NT_SUCCESS(status) && (NULL != wdf_target_device_)); if (!NT_SUCCESS(status)) return status; // Retrieve USBD version information, port driver capabilites and device // capabilites such as speed, power, etc. WDF_USB_DEVICE_INFORMATION_INIT(&usb_device_info_); status = WdfUsbTargetDeviceRetrieveInformation(wdf_target_device(), &usb_device_info_); ASSERT(NT_SUCCESS(status)); if (!NT_SUCCESS(status)) return status; WdfUsbTargetDeviceGetDeviceDescriptor(wdf_target_device(), &usb_device_descriptor_); #if DBG PrintUsbTargedDeviceInformation(usb_device_info()); PrintUsbDeviceDescriptor(&usb_device_descriptor_); #endif // DBG // Save device serial number status = WdfUsbTargetDeviceAllocAndQueryString(wdf_target_device(), WDF_NO_OBJECT_ATTRIBUTES, &serial_number_handle_, &serial_number_char_len_, usb_device_descriptor_.iSerialNumber, 0x0409); // English (US) if (!NT_SUCCESS(status)) return status; #if DBG UNICODE_STRING ser_num; ser_num.Length = serial_number_byte_len(); ser_num.MaximumLength = ser_num.Length; ser_num.Buffer = const_cast<WCHAR*> (serial_number()); GoogleDbgPrint("\n*** Device serial number %wZ", &ser_num); #endif // DBG // Configure our device now status = ConfigureDevice(); ASSERT(NT_SUCCESS(status)); if (!NT_SUCCESS(status)) return status; // Select device interfaces status = SelectInterfaces(); if (!NT_SUCCESS(status)) return status; return status; }
NTSTATUS CyEvtDevicePrepareHardware ( IN WDFDEVICE Device, IN WDFCMRESLIST ResourcesRaw, IN WDFCMRESLIST ResourcesTranslated ) { NTSTATUS NTStatus; PDEVICE_CONTEXT pDeviceContext; WDF_USB_DEVICE_INFORMATION UsbDeviceInfo; ULONG ulWaitWakeEnable; UNICODE_STRING unicodeSCRIPTFILE; WDF_OBJECT_ATTRIBUTES attributes; WDFMEMORY hScriptFileNameBufMem; PVOID pScriptFNBuf=NULL; ULONG ScripFileNtBufferlen=0; UNREFERENCED_PARAMETER(ResourcesRaw); UNREFERENCED_PARAMETER(ResourcesTranslated); ulWaitWakeEnable = FALSE; PAGED_CODE(); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Start CyEvtDevicePrepareHardware\n"); pDeviceContext = CyGetDeviceContext(Device); // // Create a USB device handle so that we can communicate with the // underlying USB stack. The WDFUSBDEVICE handle is used to query, // configure, and manage all aspects of the USB device. // These aspects include device properties, bus properties, // and I/O creation and synchronization. We only create device the first // the PrepareHardware is called. If the device is restarted by pnp manager // for resource rebalance, we will use the same device handle but then select // the interfaces again because the USB stack could reconfigure the device on // restart. // if (pDeviceContext->CyUsbDevice == NULL) { NTStatus = WdfUsbTargetDeviceCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &pDeviceContext->CyUsbDevice); if (!NT_SUCCESS(NTStatus)) { CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceCreate failed with Status code %!STATUS!\n", NTStatus); return NTStatus; } } // // Retrieve USBD version information, port driver capabilites and device // capabilites such as speed, power, etc. // WDF_USB_DEVICE_INFORMATION_INIT(&UsbDeviceInfo); NTStatus = WdfUsbTargetDeviceRetrieveInformation( pDeviceContext->CyUsbDevice, &UsbDeviceInfo); if (NT_SUCCESS(NTStatus)) { CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceHighSpeed: %s\n", (UsbDeviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) ? "TRUE" : "FALSE"); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceSelfPowered: %s\n", (UsbDeviceInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED) ? "TRUE" : "FALSE"); ulWaitWakeEnable = UsbDeviceInfo.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE; CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceRemoteWakeable: %s\n", ulWaitWakeEnable ? "TRUE" : "FALSE"); pDeviceContext->ulUSBDeviceTrait = UsbDeviceInfo.Traits; pDeviceContext->ulUSBDIVersion = UsbDeviceInfo.UsbdVersionInformation.USBDI_Version; pDeviceContext->ulWaitWakeEnable = ulWaitWakeEnable; } //Get device descriptor WdfUsbTargetDeviceGetDeviceDescriptor( pDeviceContext->CyUsbDevice, &pDeviceContext->UsbDeviceDescriptor ); NTStatus = CySelectInterfaces(Device); if (!NT_SUCCESS(NTStatus)) { CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "SelectInterfaces failed 0x%x\n", NTStatus); return NTStatus; } if (ulWaitWakeEnable) { NTStatus = CySetPowerPolicy(Device); if (!NT_SUCCESS (NTStatus)) { CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Set power policy failed %!STATUS!\n", NTStatus); return NTStatus; } } // Check for the script file in the registry and execute if it is exist // Allocate buffer to get the registry key WDF_OBJECT_ATTRIBUTES_INIT(&attributes); NTStatus = WdfMemoryCreate( &attributes, NonPagedPool, 0, CYREGSCRIPT_BUFFER_SIZE, &hScriptFileNameBufMem, &pScriptFNBuf ); if (!NT_SUCCESS(NTStatus)) { CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfMemoryCreate failed %!STATUS!\n",NTStatus); return FALSE; } if(GetRegistryKey(Device, NULL, REG_SZ, CYREG_SCRIPTFILE, pScriptFNBuf,&ScripFileNtBufferlen)) { CyExecuteScriptFile(Device, pScriptFNBuf); } CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyEvtDevicePrepareHardware\n"); //// CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyEvtDevicePrepareHardware\n"); return NTStatus; }