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; }
// 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; }