Sample Code
Windows Driver Samples/ Sample KMDF Function Driver for OSR USB-FX2/ C++/ driver/ ioctl.c/
/*++ Copyright (c) Microsoft Corporation. All rights reserved. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. Module Name: Ioctl.c Abstract: USB device driver for OSR USB-FX2 Learning Kit Environment: Kernel mode only --*/ #include <osrusbfx2.h> #if defined(EVENT_TRACING) #include "ioctl.tmh" #endif #pragma alloc_text(PAGE, OsrFxEvtIoDeviceControl) #pragma alloc_text(PAGE, ResetPipe) #pragma alloc_text(PAGE, ResetDevice) #pragma alloc_text(PAGE, ReenumerateDevice) #pragma alloc_text(PAGE, GetBarGraphState) #pragma alloc_text(PAGE, SetBarGraphState) #pragma alloc_text(PAGE, GetSevenSegmentState) #pragma alloc_text(PAGE, SetSevenSegmentState) #pragma alloc_text(PAGE, GetSwitchState) VOID OsrFxEvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_DEVICE_CONTROL requests from the system. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. OutputBufferLength - length of the request's output buffer, if an output buffer is available. InputBufferLength - length of the request's input buffer, if an input buffer is available. IoControlCode - the driver-defined or system-defined I/O control code (IOCTL) that is associated with the request. Return Value: VOID --*/ { WDFDEVICE device; PDEVICE_CONTEXT pDevContext; size_t bytesReturned = 0; PBAR_GRAPH_STATE barGraphState = NULL; PSWITCH_STATE switchState = NULL; PUCHAR sevenSegment = NULL; BOOLEAN requestPending = FALSE; NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(OutputBufferLength); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "--> OsrFxEvtIoDeviceControl\n"); // // initialize variables // device = WdfIoQueueGetDevice(Queue); pDevContext = GetDeviceContext(device); switch(IoControlCode) { case IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR: { PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL; USHORT requiredSize = 0; // // First get the size of the config descriptor // status = WdfUsbTargetDeviceRetrieveConfigDescriptor( pDevContext->UsbDevice, NULL, &requiredSize); if (status != STATUS_BUFFER_TOO_SMALL) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfUsbTargetDeviceRetrieveConfigDescriptor failed 0x%x\n", status); break; } // // Get the buffer - make sure the buffer is big enough // status = WdfRequestRetrieveOutputBuffer(Request, (size_t)requiredSize, // MinimumRequired &configurationDescriptor, NULL); if(!NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); break; } status = WdfUsbTargetDeviceRetrieveConfigDescriptor( pDevContext->UsbDevice, configurationDescriptor, &requiredSize); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfUsbTargetDeviceRetrieveConfigDescriptor failed 0x%x\n", status); break; } bytesReturned = requiredSize; } break; case IOCTL_OSRUSBFX2_RESET_DEVICE: status = ResetDevice(device); break; case IOCTL_OSRUSBFX2_REENUMERATE_DEVICE: // // Otherwise, call our function to reenumerate the // device // status = ReenumerateDevice(pDevContext); bytesReturned = 0; break; case IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY: // // Make sure the caller's output buffer is large enough // to hold the state of the bar graph // status = WdfRequestRetrieveOutputBuffer(Request, sizeof(BAR_GRAPH_STATE), &barGraphState, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n"); break; } // // Call our function to get the bar graph state // status = GetBarGraphState(pDevContext, barGraphState); // // If we succeeded return the user their data // if (NT_SUCCESS(status)) { bytesReturned = sizeof(BAR_GRAPH_STATE); } else { bytesReturned = 0; } break; case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY: status = WdfRequestRetrieveInputBuffer(Request, sizeof(BAR_GRAPH_STATE), &barGraphState, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's input buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n"); break; } // // Call our routine to set the bar graph state // status = SetBarGraphState(pDevContext, barGraphState); // // There's no data returned for this call // bytesReturned = 0; break; case IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY: status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UCHAR), &sevenSegment, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting an UCHAR\n"); break; } // // Call our function to get the 7 segment state // status = GetSevenSegmentState(pDevContext, sevenSegment); // // If we succeeded return the user their data // if (NT_SUCCESS(status)) { bytesReturned = sizeof(UCHAR); } else { bytesReturned = 0; } break; case IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY: status = WdfRequestRetrieveInputBuffer(Request, sizeof(UCHAR), &sevenSegment, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's input buffer is too small for this IOCTL, expecting an UCHAR\n"); bytesReturned = sizeof(UCHAR); break; } // // Call our routine to set the 7 segment state // status = SetSevenSegmentState(pDevContext, sevenSegment); // // There's no data returned for this call // bytesReturned = 0; break; case IOCTL_OSRUSBFX2_READ_SWITCHES: status = WdfRequestRetrieveOutputBuffer(Request, sizeof(SWITCH_STATE), &switchState, NULL);// BufferLength if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n"); bytesReturned = sizeof(SWITCH_STATE); break; } // // Call our routine to get the state of the switches // status = GetSwitchState(pDevContext, switchState); // // If successful, return the user their data // if (NT_SUCCESS(status)) { bytesReturned = sizeof(SWITCH_STATE); } else { // // Don't return any data // bytesReturned = 0; } break; case IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE: // // Forward the request to an interrupt message queue and dont complete // the request until an interrupt from the USB device occurs. // status = WdfRequestForwardToIoQueue(Request, pDevContext->InterruptMsgQueue); if (NT_SUCCESS(status)) { requestPending = TRUE; } break; default : status = STATUS_INVALID_DEVICE_REQUEST; break; } if (requestPending == FALSE) { WdfRequestCompleteWithInformation(Request, status, bytesReturned); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "<-- OsrFxEvtIoDeviceControl\n"); return; } _IRQL_requires_(PASSIVE_LEVEL) NTSTATUS ResetPipe( _In_ WDFUSBPIPE Pipe ) /*++ Routine Description: This routine resets the pipe. Arguments: Pipe - framework pipe handle Return Value: NT status value --*/ { NTSTATUS status; PAGED_CODE(); // // This routine synchronously submits a URB_FUNCTION_RESET_PIPE // request down the stack. // status = WdfUsbTargetPipeResetSynchronously(Pipe, WDF_NO_HANDLE, // WDFREQUEST NULL // PWDF_REQUEST_SEND_OPTIONS ); if (NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "ResetPipe - success\n"); status = STATUS_SUCCESS; } else { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ResetPipe - failed\n"); } return status; } VOID StopAllPipes( IN PDEVICE_CONTEXT DeviceContext ) { WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(DeviceContext->InterruptPipe), WdfIoTargetCancelSentIo); WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(DeviceContext->BulkReadPipe), WdfIoTargetCancelSentIo); WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(DeviceContext->BulkWritePipe), WdfIoTargetCancelSentIo); } NTSTATUS StartAllPipes( IN PDEVICE_CONTEXT DeviceContext ) { NTSTATUS status; status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(DeviceContext->InterruptPipe)); if (!NT_SUCCESS(status)) { return status; } status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(DeviceContext->BulkReadPipe)); if (!NT_SUCCESS(status)) { return status; } status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(DeviceContext->BulkWritePipe)); if (!NT_SUCCESS(status)) { return status; } return status; } _IRQL_requires_(PASSIVE_LEVEL) NTSTATUS ResetDevice( _In_ WDFDEVICE Device ) /*++ Routine Description: This routine calls WdfUsbTargetDeviceResetPortSynchronously to reset the device if it's still connected. Arguments: Device - Handle to a framework device Return Value: NT status value --*/ { PDEVICE_CONTEXT pDeviceContext; NTSTATUS status; PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "--> ResetDevice\n"); pDeviceContext = GetDeviceContext(Device); // // A NULL timeout indicates an infinite wake // status = WdfWaitLockAcquire(pDeviceContext->ResetDeviceWaitLock, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ResetDevice - could not acquire lock\n"); return status; } StopAllPipes(pDeviceContext); status = WdfUsbTargetDeviceResetPortSynchronously(pDeviceContext->UsbDevice); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ResetDevice failed - 0x%x\n", status); } status = StartAllPipes(pDeviceContext); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Failed to start all pipes - 0x%x\n", status); } WdfWaitLockRelease(pDeviceContext->ResetDeviceWaitLock); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "<-- ResetDevice\n"); return status; } _IRQL_requires_(PASSIVE_LEVEL) 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(&activity, DevContext->DeviceName, DevContext->Location, status); return status; } _IRQL_requires_(PASSIVE_LEVEL) NTSTATUS GetBarGraphState( _In_ PDEVICE_CONTEXT DevContext, _Out_ PBAR_GRAPH_STATE BarGraphState ) /*++ Routine Description This routine gets the state of the bar graph on the board Arguments: DevContext - One of our device extensions BarGraphState - Struct that receives the bar graph's 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, "--> GetBarGraphState\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, BmRequestDeviceToHost, BmRequestToDevice, USBFX2LK_READ_BARGRAPH_DISPLAY, // Request 0, // Value 0); // Index // // Set the buffer to 0, the board will OR in everything that is set // BarGraphState->BarsAsUChar = 0; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, BarGraphState, sizeof(BAR_GRAPH_STATE)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( DevContext->UsbDevice, WDF_NO_HANDLE, // Optional WDFREQUEST &sendOptions, &controlSetupPacket, &memDesc, &bytesTransferred); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "GetBarGraphState: Failed to GetBarGraphState - 0x%x \n", status); } else { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "GetBarGraphState: LED mask is 0x%x\n", BarGraphState->BarsAsUChar); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "<-- GetBarGraphState\n"); return status; } _IRQL_requires_(PASSIVE_LEVEL) 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; } _IRQL_requires_(PASSIVE_LEVEL) 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; } _IRQL_requires_(PASSIVE_LEVEL) 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; } _IRQL_requires_(PASSIVE_LEVEL) 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; } VOID OsrUsbIoctlGetInterruptMessage( _In_ WDFDEVICE Device, _In_ NTSTATUS ReaderStatus ) /*++ Routine Description This method handles the completion of the pended request for the IOCTL IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE. Arguments: Device - Handle to a framework device. Return Value: None. --*/ { NTSTATUS status; WDFREQUEST request; PDEVICE_CONTEXT pDevContext; size_t bytesReturned = 0; PSWITCH_STATE switchState = NULL; pDevContext = GetDeviceContext(Device); do { // // Check if there are any pending requests in the Interrupt Message Queue. // If a request is found then complete the pending request. // status = WdfIoQueueRetrieveNextRequest(pDevContext->InterruptMsgQueue, &request); if (NT_SUCCESS(status)) { status = WdfRequestRetrieveOutputBuffer(request, sizeof(SWITCH_STATE), &switchState, NULL);// BufferLength if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n"); bytesReturned = sizeof(SWITCH_STATE); } else { // // Copy the state information saved by the continuous reader. // if (NT_SUCCESS(ReaderStatus)) { switchState->SwitchesAsUChar = pDevContext->CurrentSwitchState; bytesReturned = sizeof(SWITCH_STATE); } else { bytesReturned = 0; } } // // Complete the request. If we failed to get the output buffer then // complete with that status. Otherwise complete with the status from the reader. // WdfRequestCompleteWithInformation(request, NT_SUCCESS(status) ? ReaderStatus : status, bytesReturned); status = STATUS_SUCCESS; } else if (status != STATUS_NO_MORE_ENTRIES) { KdPrint(("WdfIoQueueRetrieveNextRequest status %08x\n", status)); } request = NULL; } while (status == STATUS_SUCCESS); return; }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials