// This function gets the switch state of the USB device directly from the hardware // NTSTATUS HidFx2GetSwitchState(_In_ WDFDEVICE hDevice, _Out_ unsigned char *pbSwitchState) { PDEVICE_EXTENSION pDevContext = NULL; NTSTATUS status = STATUS_SUCCESS; WDF_MEMORY_DESCRIPTOR memDesc; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; ULONG cBytesTransferred = 0; if(pbSwitchState != NULL) { *pbSwitchState = 0; } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); pDevContext = GetDeviceContext(hDevice); // set the segment state on the USB device WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestDeviceToHost, BmRequestToDevice, HIDFX2_READ_SWITCH_STATE, // Request 0, // Value 0); // Index WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, pbSwitchState, sizeof(*pbSwitchState)); status = WdfUsbTargetDeviceSendControlTransferSynchronously(pDevContext->hUsbDevice, NULL, // Optional WDFREQUEST NULL, // PWDF_REQUEST_SEND_OPTIONS &controlSetupPacket, &memDesc, &cBytesTransferred); if (!NT_SUCCESS(status)) { TraceErr(DBG_IOCTL, "(%!FUNC!) Failed to read switch state - %!STATUS! \n", status); } else { TraceVerbose(DBG_IOCTL, "(%!FUNC!) Switch state is 0x%x\n", *pbSwitchState); *pbSwitchState = ~(*pbSwitchState); // switchs are inverted on hardware boards TraceVerbose(DBG_IOCTL, "(%!FUNC!) Switch state is 0x%x\n", *pbSwitchState); } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit, status: %!STATUS!\n", status); return status; }
//This routine sets the state of the Feature: in this case Segment Display on the USB FX2 board. NTSTATUS SendVendorCommand(_In_ WDFDEVICE hDevice, _In_ unsigned char bVendorCommand, _In_ unsigned char bCommandData) { NTSTATUS status = STATUS_SUCCESS; ULONG cBytesTransferred = 0; PDEVICE_EXTENSION pDevContext = NULL; WDF_MEMORY_DESCRIPTOR memDesc; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; PAGED_CODE(); TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); pDevContext = GetDeviceContext(hDevice); TraceInfo(DBG_IOCTL, "(%!FUNC!): Command:0x%x, data: 0x%x\n", bVendorCommand, bCommandData); // Send the I/O with a timeout. // We do that because we send the I/O in the context of the user thread and if it gets stuck, it would prevent the user process from existing. WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_SEC(5)); WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestHostToDevice, BmRequestToDevice, bVendorCommand, // Request 0, // Value 0); // Index WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, &bCommandData, sizeof(bCommandData)); status = WdfUsbTargetDeviceSendControlTransferSynchronously(pDevContext->hUsbDevice, WDF_NO_HANDLE, // Optional WDFREQUEST &sendOptions, // PWDF_REQUEST_SEND_OPTIONS &controlSetupPacket, &memDesc, &cBytesTransferred); if (!NT_SUCCESS(status)) { TraceErr(DBG_IOCTL, "(%!FUNC!): Failed to set Segment Display state - %!STATUS!\n", status); } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit\n"); return status; }
NTSTATUS GetDevInfoData( __in PFILTER_EXTENSION filterExt, __in ULONG DevInfoLen, __out BYTE* pDevInfoData, __out size_t* bytesRead ) /*++ Routine Description This routine gets the data of the device Arguments: pDevInfoLen - One of our device extensions Return Value: NT status value --*/ { NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; WDF_MEMORY_DESCRIPTOR memDesc; ULONG bytesTransferred; PAGED_CODE(); WDF_REQUEST_SEND_OPTIONS_INIT( &sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT ); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT( &sendOptions, WDF_REL_TIMEOUT_IN_SEC(5) ); WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestDeviceToHost, BmRequestToDevice, USBFX2LK_READ_DEVINFO_DATA, // Request 0, // Value 0); // Index WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, pDevInfoData, DevInfoLen); status = WdfUsbTargetDeviceSendControlTransferSynchronously( filterExt->UsbDevice, WDF_NO_HANDLE, // Optional WDFREQUEST &sendOptions, &controlSetupPacket, &memDesc, &bytesTransferred); if(!NT_SUCCESS(status)) { KdPrint( ("GetDevInfoData: Failed - 0x%x \n", status)); *bytesRead = 0; } else { KdPrint( ("GetDevInfoData: transferred bytes %d \n", bytesTransferred )); *bytesRead = (size_t)bytesTransferred; } return status; }
NTSTATUS GetDevInfoLength( __in PFILTER_EXTENSION filterExt, __out BYTE* pDevInfoLen ) /*++ Routine Description This routine gets the length of device info, so caller app can prepare proper buffer to retrieve the actual content info Arguments: pDevInfoLen - One of our device extensions Return Value: NT status value --*/ { NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; WDF_MEMORY_DESCRIPTOR memDesc; ULONG bytesTransferred; PAGED_CODE(); WDF_REQUEST_SEND_OPTIONS_INIT( &sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT ); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT( &sendOptions, WDF_REL_TIMEOUT_IN_SEC(5) ); WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestDeviceToHost, BmRequestToDevice, USBFX2LK_READ_DEVINFO_LEN, // Request 0, // Value 0); // Index // // Set the buffer to 0, the board will OR in everything that is set // *pDevInfoLen = 0; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, pDevInfoLen, sizeof(BYTE)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( filterExt->UsbDevice, WDF_NO_HANDLE, // Optional WDFREQUEST &sendOptions, &controlSetupPacket, &memDesc, &bytesTransferred); if(!NT_SUCCESS(status)) { KdPrint( ("GetDevInfoLength: Failed - 0x%x \n", status)); } else { KdPrint( ("GetDevInfoLength: %d \n", *pDevInfoLen )); } return status; }
NTSTATUS HidFx2GetSwitchState( IN WDFDEVICE Device, OUT PUCHAR SwitchState ) /*++ Routine Description: This function gets the swicth state of teh USB device Arguments: Device - Handle to a framework device object. SwitchState - Pointer to a variable that receives the switch state Return Value: Success implies that the device can be used. Failure will result in the device stack being torn down. --*/ { PDEVICE_EXTENSION devContext = NULL; NTSTATUS status = STATUS_SUCCESS; WDF_MEMORY_DESCRIPTOR memDesc; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; ULONG bytesTransferred = 0; devContext = GetDeviceContext(Device); // // set the segment state on the USB device // WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestDeviceToHost, BmRequestToDevice, HIDFX2_READ_SWITCH_STATE, // Request 0, // Value 0); // Index WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, SwitchState, sizeof(UCHAR)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( devContext->UsbDevice, NULL, // Optional WDFREQUEST NULL, // PWDF_REQUEST_SEND_OPTIONS &controlSetupPacket, &memDesc, &bytesTransferred ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "GetSwitchState: Failed to read switch state - 0x%x \n", status); } else { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "GetSwitchState: Switch state is 0x%x\n", *SwitchState); } return status; }
/////////////////////////////////////////////////////////////////////////////// // // BasicUsbEvtDeviceControl // // This routine is called by the framework when there is a // device control request for us to process // // INPUTS: // // Queue - Our default queue // // Request - A device control request // // OutputBufferLength - The length of the output buffer // // InputBufferLength - The length of the input buffer // // IoControlCode - The operation being performed // // OUTPUTS: // // None. // // RETURNS: // // None. // // IRQL: // // This routine is called at IRQL == PASSIVE_LEVEL, due to // our PASSIVE_LEVEL execution level contraint // // NOTES: // // /////////////////////////////////////////////////////////////////////////////// VOID BasicUsbEvtDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode) { NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDFMEMORY inputMemory; WDF_MEMORY_DESCRIPTOR inputMemoryDescriptor; PBASICUSB_DEVICE_CONTEXT devContext; #if DBG DbgPrint("BasicUsbEvtDeviceControl\n"); #endif devContext = BasicUsbGetContextFromDevice( WdfIoQueueGetDevice(Queue) ); switch (IoControlCode) { case IOCTL_OSR_BASICUSB_SET_BAR_GRAPH: { // // Validate the buffers for this request: // // OutputBufferLength - Must be zero // if (OutputBufferLength != 0) { #if DBG DbgPrint("Invalid parameter - output buffer supplied in "\ "SET_BAR_GRAPH IOCTL (%u bytes)\n", (ULONG)OutputBufferLength); #endif WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } // // InputBufferLength - Must be at least 1 byte // if (InputBufferLength == 0) { #if DBG DbgPrint("No input buffer supplied in SET_BAR_GRAPH IOCTL\n"); #endif WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_TOO_SMALL, sizeof(UCHAR)); return; } // // We need the input memory from the request so that we can pass // it to the bus driver. // status = WdfRequestRetrieveInputMemory(Request, &inputMemory); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfRequestRetrieveInputMemory failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); return; } // // The routine we want to call takes a memory descriptor, so // initialize that now with the handle to the user memory. // WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&inputMemoryDescriptor, inputMemory, NULL); // // Initialize the vendor command (defined by the device) that // allows us to light the bar graph. // WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR( &controlSetupPacket, BmRequestHostToDevice, BmRequestToDevice, USBFX2LK_SET_BARGRAPH_DISPLAY, 0, 0); // // And send the vendor command as a control transfer. This // shouldn't take very long, so we'll just send it synchronously // to the device. // // // We've specified an execution level restraint of // PASSIVE_LEVEL, so we're allowed to send this request // synchronously. // ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); status = WdfUsbTargetDeviceSendControlTransferSynchronously( devContext->BasicUsbUsbDevice, WDF_NO_HANDLE, NULL, &controlSetupPacket, &inputMemoryDescriptor, NULL); if (NT_SUCCESS(status)) { // // If the request succeeded, complete the request with success // and indicate to the user how much data was transferred (in // this case a single byte was sent to the device) // WdfRequestCompleteWithInformation(Request, status, sizeof(UCHAR)); } else { // // Bad news! Just complete the request with the failure status. // #if DBG DbgPrint("WdfUsbTargetDeviceSendControlTransferSynchronously "\ "failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); } return; } case IOCTL_OSR_BASICUSB_GET_SWITCHPACK_STATE: { // // Validate the buffers for this request: // // InputBufferLength - Must be zero // if (InputBufferLength != 0) { #if DBG DbgPrint("Invalid parameter - input buffer supplied in "\ "SWITCHPACK_STATE_CHANGE_NOTIFY IOCTL (%u bytes)\n", (ULONG)InputBufferLength); #endif WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } // // OutputBufferLength - Must be at least 1 byte // if (OutputBufferLength == 0) { #if DBG DbgPrint("No input buffer supplied in "\ "SWITCHPACK_STATE_CHANGE_NOTIFY IOCTL\n"); #endif WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_TOO_SMALL, sizeof(UCHAR)); return; } // // Forward the request to our switchpack state change requests // queue // status = WdfRequestForwardToIoQueue( Request, devContext->SwitchPackStateChangeQueue); if (!NT_SUCCESS(status)) { // // Bad news! Print out the status and fail the request. // #if DBG DbgPrint("WdfRequestForwardToIoQueue failed with Status "\ "code 0x%x", status); #endif WdfRequestComplete(Request, status); return; } return; } default: { #if DBG DbgPrint("Unknown IOCTL: 0x%x\n", IoControlCode); #endif WdfRequestCompleteWithInformation(Request, STATUS_INVALID_DEVICE_REQUEST, 0); return; } } return; }
NTSTATUS GetSwitchState( _In_ PDEVICE_CONTEXT DevContext, _In_ PSWITCH_STATE SwitchState ) /*++ Routine Description This routine gets the state of the switches on the board Arguments: DevContext - One of our device extensions Return Value: NT status value --*/ { NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; WDF_MEMORY_DESCRIPTOR memDesc; ULONG bytesTransferred; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "--> GetSwitchState\n"); PAGED_CODE(); WDF_REQUEST_SEND_OPTIONS_INIT( &sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT ); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT( &sendOptions, DEFAULT_CONTROL_TRANSFER_TIMEOUT ); WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestDeviceToHost, BmRequestToDevice, USBFX2LK_READ_SWITCHES, // Request 0, // Value 0); // Index SwitchState->SwitchesAsUChar = 0; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, SwitchState, sizeof(SWITCH_STATE)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( DevContext->UsbDevice, NULL, // Optional WDFREQUEST &sendOptions, &controlSetupPacket, &memDesc, &bytesTransferred); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "GetSwitchState: Failed to Get switches - 0x%x \n", status); } else { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "GetSwitchState: Switch mask is 0x%x\n", SwitchState->SwitchesAsUChar); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "<-- GetSwitchState\n"); return status; }
NTSTATUS SetSevenSegmentState( _In_ PDEVICE_CONTEXT DevContext, _In_ PUCHAR SevenSegment ) /*++ Routine Description This routine sets the state of the 7 segment display on the board Arguments: DevContext - One of our device extensions SevenSegment - desired state of the 7 segment display Return Value: NT status value --*/ { NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; WDF_MEMORY_DESCRIPTOR memDesc; ULONG bytesTransferred; PAGED_CODE(); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "--> SetSevenSegmentState\n"); WDF_REQUEST_SEND_OPTIONS_INIT( &sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT ); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT( &sendOptions, DEFAULT_CONTROL_TRANSFER_TIMEOUT ); WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestHostToDevice, BmRequestToDevice, USBFX2LK_SET_7SEGMENT_DISPLAY, // Request 0, // Value 0); // Index WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, SevenSegment, sizeof(UCHAR)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( DevContext->UsbDevice, NULL, // Optional WDFREQUEST &sendOptions, &controlSetupPacket, &memDesc, &bytesTransferred); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "SetSevenSegmentState: Failed to set 7 Segment state - 0x%x \n", status); } else { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "SetSevenSegmentState: 7 Segment mask is 0x%x\n", *SevenSegment); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "<-- SetSevenSegmentState\n"); return status; }
NTSTATUS GetSevenSegmentState( _In_ PDEVICE_CONTEXT DevContext, _Out_ PUCHAR SevenSegment ) /*++ Routine Description This routine gets the state of the 7 segment display on the board by sending a synchronous control command. NOTE: It's not a good practice to send a synchronous request in the context of the user thread because if the transfer takes long time to complete, you end up holding the user thread. I'm choosing to do synchronous transfer because a) I know this one completes immediately b) and for demonstration. Arguments: DevContext - One of our device extensions SevenSegment - receives the state of the 7 segment display Return Value: NT status value --*/ { NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; WDF_MEMORY_DESCRIPTOR memDesc; ULONG bytesTransferred; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "GetSetSevenSegmentState: Enter\n"); PAGED_CODE(); WDF_REQUEST_SEND_OPTIONS_INIT( &sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT ); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT( &sendOptions, DEFAULT_CONTROL_TRANSFER_TIMEOUT ); WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestDeviceToHost, BmRequestToDevice, USBFX2LK_READ_7SEGMENT_DISPLAY, // Request 0, // Value 0); // Index // // Set the buffer to 0, the board will OR in everything that is set // *SevenSegment = 0; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, SevenSegment, sizeof(UCHAR)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( DevContext->UsbDevice, NULL, // Optional WDFREQUEST &sendOptions, &controlSetupPacket, &memDesc, &bytesTransferred); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "GetSevenSegmentState: Failed to get 7 Segment state - 0x%x \n", status); } else { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "GetSevenSegmentState: 7 Segment mask is 0x%x\n", *SevenSegment); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "GetSetSevenSegmentState: Exit\n"); return status; }
NTSTATUS SetBarGraphState( _In_ PDEVICE_CONTEXT DevContext, _In_ PBAR_GRAPH_STATE BarGraphState ) /*++ Routine Description This routine sets the state of the bar graph on the board Arguments: DevContext - One of our device extensions BarGraphState - Struct that describes the bar graph's desired state Return Value: NT status value --*/ { NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; WDF_MEMORY_DESCRIPTOR memDesc; ULONG bytesTransferred; PAGED_CODE(); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "--> SetBarGraphState\n"); WDF_REQUEST_SEND_OPTIONS_INIT( &sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT ); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT( &sendOptions, DEFAULT_CONTROL_TRANSFER_TIMEOUT ); WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestHostToDevice, BmRequestToDevice, USBFX2LK_SET_BARGRAPH_DISPLAY, // Request 0, // Value 0); // Index WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, BarGraphState, sizeof(BAR_GRAPH_STATE)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( DevContext->UsbDevice, NULL, // Optional WDFREQUEST &sendOptions, &controlSetupPacket, &memDesc, &bytesTransferred); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "SetBarGraphState: Failed - 0x%x \n", status); } else { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "SetBarGraphState: LED mask is 0x%x\n", BarGraphState->BarsAsUChar); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "<-- SetBarGraphState\n"); return status; }
NTSTATUS ReenumerateDevice( _In_ PDEVICE_CONTEXT DevContext ) /*++ Routine Description This routine re-enumerates the USB device. Arguments: pDevContext - One of our device extensions Return Value: NT status value --*/ { NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; GUID activity; PAGED_CODE(); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,"--> ReenumerateDevice\n"); WDF_REQUEST_SEND_OPTIONS_INIT( &sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT ); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT( &sendOptions, DEFAULT_CONTROL_TRANSFER_TIMEOUT ); WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestHostToDevice, BmRequestToDevice, USBFX2LK_REENUMERATE, // Request 0, // Value 0); // Index status = WdfUsbTargetDeviceSendControlTransferSynchronously( DevContext->UsbDevice, WDF_NO_HANDLE, // Optional WDFREQUEST &sendOptions, &controlSetupPacket, NULL, // MemoryDescriptor NULL); // BytesTransferred if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ReenumerateDevice: Failed to Reenumerate - 0x%x \n", status); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,"<-- ReenumerateDevice\n"); // // Send event to eventlog // activity = DeviceToActivityId(WdfObjectContextGetObject(DevContext)); EventWriteDeviceReenumerated(DevContext->DeviceName, DevContext->Location, status); return status; }
VOID EvtIoDeviceControl( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) { WDFDEVICE device; PDEVICE_CONTEXT pDevContext; size_t bytesTransferred = 0; NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_MEMORY_DESCRIPTOR memDesc; WDFMEMORY memory; WDF_REQUEST_SEND_OPTIONS sendOptions; UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(OutputBufferLength); device = WdfIoQueueGetDevice(Queue); pDevContext = GetDeviceContext(device); switch(IoControlCode) { case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY: if(InputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_OVERFLOW; bytesTransferred = sizeof(UCHAR); break; } status = WdfRequestRetrieveInputMemory(Request, &memory); if (!NT_SUCCESS(status)) { KdPrint(("WdfRequestRetrieveMemory failed %!STATUS!", status)); break; } WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestHostToDevice, BmRequestToDevice, USBFX2LK_SET_BARGRAPH_DISPLAY, // Request 0, // Value 0); // Index WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&memDesc, memory, NULL); // // Send the I/O with a timeout to avoid hanging the calling // thread indefinitely. // WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_MS(100)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( pDevContext->UsbDevice, NULL, // Optional WDFREQUEST &sendOptions, // PWDF_REQUEST_SEND_OPTIONS &controlSetupPacket, &memDesc, (PULONG)&bytesTransferred); if (!NT_SUCCESS(status)) { KdPrint(("SendControlTransfer failed %!STATUS!", status)); break; } break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation(Request, status, bytesTransferred); return; }