// Pass down Idle notification request to lower driver // NTSTATUS HidFx2SendIdleNotification(_In_ WDFREQUEST hRequest) { NTSTATUS status = STATUS_SUCCESS; WDF_REQUEST_SEND_OPTIONS options; WDFIOTARGET hNextLowerDriver; WDFDEVICE hDevice; PIO_STACK_LOCATION pCurrentIrpStack = NULL; IO_STACK_LOCATION nextIrpStack; TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest)); pCurrentIrpStack = IoGetCurrentIrpStackLocation(WdfRequestWdmGetIrp(hRequest)); // Convert the request to corresponding USB Idle notification request if (pCurrentIrpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO)) { ASSERT(sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) == sizeof(USB_IDLE_CALLBACK_INFO)); #pragma warning(suppress :4127) // conditional expression is constant warning if (sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) == sizeof(USB_IDLE_CALLBACK_INFO)) { // prepare next stack location RtlZeroMemory(&nextIrpStack, sizeof(IO_STACK_LOCATION)); nextIrpStack.MajorFunction = pCurrentIrpStack->MajorFunction; nextIrpStack.Parameters.DeviceIoControl.InputBufferLength = pCurrentIrpStack->Parameters.DeviceIoControl.InputBufferLength; nextIrpStack.Parameters.DeviceIoControl.Type3InputBuffer = pCurrentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; nextIrpStack.Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION; nextIrpStack.DeviceObject = WdfIoTargetWdmGetTargetDeviceObject(WdfDeviceGetIoTarget(hDevice)); // Format the I/O request for the driver's local I/O target by using the contents of the specified WDM I/O stack location structure. WdfRequestWdmFormatUsingStackLocation(hRequest, &nextIrpStack); // Send the request down using Fire and forget option. WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); hNextLowerDriver = WdfDeviceGetIoTarget(hDevice); if (WdfRequestSend(hRequest, hNextLowerDriver, &options) == FALSE) { status = STATUS_UNSUCCESSFUL; } } else // Incorrect DeviceIoControl.InputBufferLength { status = STATUS_INFO_LENGTH_MISMATCH; TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect DeviceIoControl.InputBufferLength, %!STATUS!\n", status); return status; } } else // DeviceIoControl.InputBufferLength too small { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) DeviceIoControl.InputBufferLength too small, %!STATUS!\n", status); return status; } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit = %!STATUS!\n", status); return status; }
static VOID XenVbd_StopRing(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend) { PXENVBD_FILTER_DATA xvfd = (PXENVBD_FILTER_DATA)xvdd->xvfd; NTSTATUS status; WDFREQUEST request; WDF_REQUEST_SEND_OPTIONS send_options; IO_STACK_LOCATION stack; SCSI_REQUEST_BLOCK srb; SRB_IO_CONTROL sic; FUNCTION_ENTER(); /* send a 'stop' down if we are suspending */ if (suspend) { status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request); FUNCTION_MSG("WdfRequestCreate = %08x\n", status); RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION)); stack.MajorFunction = IRP_MJ_SCSI; stack.MinorFunction = IRP_MN_SCSI_CLASS; stack.Parameters.Scsi.Srb = &srb; RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE); srb.SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; srb.Length = SCSI_REQUEST_BLOCK_SIZE; srb.PathId = 0; srb.TargetId = 0; srb.Lun = 0; srb.OriginalRequest = WdfRequestWdmGetIrp(request); srb.Function = SRB_FUNCTION_IO_CONTROL; srb.DataBuffer = &sic; RtlZeroMemory(&sic, sizeof(SRB_IO_CONTROL)); sic.HeaderLength = sizeof(SRB_IO_CONTROL); memcpy(sic.Signature, XENVBD_CONTROL_SIG, 8); sic.Timeout = 60; sic.ControlCode = XENVBD_CONTROL_STOP; WdfRequestWdmFormatUsingStackLocation(request, &stack); WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) { FUNCTION_MSG("Request was _NOT_ sent\n"); } #if DBG status = WdfRequestGetStatus(request); FUNCTION_MSG("Request Status = %08x\n", status); FUNCTION_MSG("SRB Status = %08x\n", srb.SrbStatus); #endif WdfObjectDelete(request); } status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosing); FUNCTION_EXIT(); }
static VOID XenVbd_SendEvent(WDFDEVICE device) { PXENVBD_FILTER_DATA xvfd = GetXvfd(device); NTSTATUS status; WDFREQUEST request; WDF_REQUEST_SEND_OPTIONS send_options; IO_STACK_LOCATION stack; PUCHAR buf; PSCSI_REQUEST_BLOCK srb; PSRB_IO_CONTROL sic; status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request); if (status != STATUS_SUCCESS) { FUNCTION_MSG("WdfRequestCreate failed %08x\n", status); /* this is bad - event will be dropped */ return; } buf = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL) + sizeof(LARGE_INTEGER), XENVBD_POOL_TAG); RtlZeroMemory(buf, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL)); srb = (PSCSI_REQUEST_BLOCK)(buf); sic = (PSRB_IO_CONTROL)(buf + sizeof(SCSI_REQUEST_BLOCK)); srb->Length = sizeof(SCSI_REQUEST_BLOCK); srb->SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; srb->PathId = 0; srb->TargetId = 0; srb->Lun = 0; srb->OriginalRequest = WdfRequestWdmGetIrp(request); srb->Function = SRB_FUNCTION_IO_CONTROL; srb->DataBuffer = sic; srb->DataTransferLength = sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL); srb->TimeOutValue = (ULONG)-1; sic->HeaderLength = sizeof(SRB_IO_CONTROL); memcpy(sic->Signature, XENVBD_CONTROL_SIG, 8); sic->Timeout = (ULONG)-1; sic->ControlCode = XENVBD_CONTROL_EVENT; KeQuerySystemTime((PLARGE_INTEGER)((PUCHAR)buf + sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL))); RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION)); stack.MajorFunction = IRP_MJ_SCSI; stack.MinorFunction = IRP_MN_SCSI_CLASS; stack.Parameters.Scsi.Srb = srb; WdfRequestWdmFormatUsingStackLocation(request, &stack); WdfRequestSetCompletionRoutine(request, XenVbd_SendEventComplete, buf); WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, 0); //WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE); if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) { FUNCTION_MSG("Error sending request\n"); } }
NTSTATUS HidFx2SetOutput(_In_ WDFREQUEST hRequest) { NTSTATUS status = STATUS_SUCCESS; PHID_XFER_PACKET pTransferPacket = NULL; WDF_REQUEST_PARAMETERS params; PHIDFX2_IO_REPORT pOutputReport = NULL; WDFDEVICE hDevice; PAGED_CODE(); TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest)); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(hRequest, ¶ms); if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) Userbuffer is small %!STATUS!\n", status); return status; } pTransferPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(hRequest)->UserBuffer; if (pTransferPacket == NULL) { status = STATUS_INVALID_DEVICE_REQUEST; TraceErr(DBG_IOCTL, "(%!FUNC!) Irp->UserBuffer is NULL %!STATUS!\n", status); return status; } if (pTransferPacket->reportBufferLen == 0) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is 0, %!STATUS!\n", status); return status; } if (pTransferPacket->reportBufferLen < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is too small, %!STATUS!\n", status); return status; } if (pTransferPacket->reportId != GENERIC_DESKTOP_REPORT_ID) { status = STATUS_INVALID_DEVICE_REQUEST; TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect report ID, %!STATUS!\n", status); return status; } pOutputReport = (PHIDFX2_IO_REPORT)pTransferPacket->reportBuffer; if (pOutputReport->bData == 0) { status = SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_OFF); } else { status = SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_ON); } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit status %!STATUS!\n", status); return status; }
NTSTATUS HidFx2GetInput(_In_ WDFREQUEST hRequest) { NTSTATUS status = STATUS_SUCCESS; WDF_REQUEST_PARAMETERS params; WDFDEVICE hDevice; PHID_XFER_PACKET pTransferPacket = NULL; PHIDFX2_IO_REPORT pOutputReport = NULL; unsigned char bSwitchState = 0; PAGED_CODE(); TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest)); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(hRequest, ¶ms); if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET)) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) Userbuffer is small %!STATUS!\n", status); return status; } pTransferPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(hRequest)->UserBuffer; if (pTransferPacket == NULL) { status = STATUS_INVALID_DEVICE_REQUEST; TraceErr(DBG_IOCTL, "(%!FUNC!) Irp->UserBuffer is NULL %!STATUS!\n", status); return status; } if (pTransferPacket->reportBufferLen == 0) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is 0, %!STATUS!\n", status); return status; } if (pTransferPacket->reportBufferLen < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is too small, %!STATUS!\n", status); return status; } if (pTransferPacket->reportId != GENERIC_DESKTOP_REPORT_ID) { status = STATUS_INVALID_DEVICE_REQUEST; TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect report ID, %!STATUS!\n", status); return status; } pOutputReport = (PHIDFX2_IO_REPORT)pTransferPacket->reportBuffer; // Get the switch state directly from the hardware status = HidFx2GetSwitchState(hDevice, &bSwitchState); TraceVerbose(DBG_IOCTL, "(%!FUNC!) switch state 0x%x\n", bSwitchState); //Mask off everything except the actual switch bit bSwitchState &= RADIO_SWITCH_BUTTONS_BIT_MASK; TraceVerbose(DBG_IOCTL, "(%!FUNC!) maskedswitch state 0x%x\n", bSwitchState); pOutputReport->bReportId = GENERIC_DESKTOP_REPORT_ID; pOutputReport->bData = bSwitchState; TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit status %!STATUS!\n", status); return status; }
/** * @brief DPC callback. * Calls the Xen interface api to process the ringbuffer until the ringbuffer is empty, * then completes all requests provided by the Xen api. * * @todo consider completion within the XenDpc() loop. However this would release the device * lock. * * @param[in] Dpc The WDFDPC handle. * */ VOID FdoEvtDeviceDpcFunc( IN VOID *Context) { // --XT-- FDO context passed directly now. PUSB_FDO_CONTEXT fdoContext = (PUSB_FDO_CONTEXT)Context; // // this stuff needs to be done at DPC level in order to complete irps. // ULONG passes = 0; AcquireFdoLock(fdoContext); if (fdoContext->InDpc) { fdoContext->DpcOverLapCount++; ReleaseFdoLock(fdoContext); return; } fdoContext->InDpc = TRUE; BOOLEAN moreWork; do { moreWork = XenDpc(fdoContext, fdoContext->RequestCollection); passes++; if (fdoContext->DpcOverLapCount) { fdoContext->totalDpcOverLapCount += fdoContext->DpcOverLapCount; fdoContext->DpcOverLapCount = 0; moreWork = TRUE; } if (moreWork & (passes >= KeQueryActiveProcessorCount(NULL))) { // // reschedule the dpc to prevent starvation. // // --XT-- WdfDpcEnqueue(fdoContext->WdfDpc); // // --XT-- Schedule through the Xen interface now. // XenScheduleDPC(fdoContext->Xen); TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DPC, __FUNCTION__": enqueue dpc at %d passes\n", passes); fdoContext->totalDpcReQueueCount++; break; } } while (moreWork); fdoContext->InDpc = FALSE; // allow another dpc instance to run and add to the collection. if (passes > fdoContext->maxDpcPasses) { fdoContext->maxDpcPasses = passes; } // // complete all queued Irps. Note that this section is re-entrant. // Note also that all of these requests have been "uncanceled" and ahve // been marked as completed in their request contexts and that the // additional reference on the request object has been removed. // The collection can be safely completed with no race conditions. // ULONG responseCount = 0; WDFREQUEST Request; while ((Request = (WDFREQUEST) WdfCollectionGetFirstItem(fdoContext->RequestCollection)) != NULL) { WdfCollectionRemoveItem(fdoContext->RequestCollection, 0); TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DPC, __FUNCTION__": complete Request %p Status %x\n", Request, WdfRequestWdmGetIrp(Request)->IoStatus.Status); ReleaseFdoLock(fdoContext); WdfRequestCompleteWithPriorityBoost(Request, WdfRequestWdmGetIrp(Request)->IoStatus.Status, IO_SOUND_INCREMENT); AcquireFdoLock(fdoContext); responseCount++; } if (responseCount > fdoContext->maxRequestsProcessed) { fdoContext->maxRequestsProcessed = responseCount; } // // fire up any queued requests // DrainRequestQueue(fdoContext, FALSE); ReleaseFdoLock(fdoContext); // --XT-- this trace was way too noisy, made it verbose. TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DPC, __FUNCTION__": exit responses processed %d passes %d\n", responseCount, passes); }
NTSTATUS PowerContextReuseRequest( _In_ PCDROM_DEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: reset fields for the request. Arguments: DeviceExtension - device context Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; WDF_REQUEST_REUSE_PARAMS reuseParams; PIRP irp = NULL; RtlZeroMemory(&(DeviceExtension->PowerContext.SenseData), sizeof(DeviceExtension->PowerContext.SenseData)); RtlZeroMemory(&(DeviceExtension->PowerContext.Srb), sizeof(DeviceExtension->PowerContext.Srb)); irp = WdfRequestWdmGetIrp(DeviceExtension->PowerContext.PowerRequest); // Re-use the previously created PowerRequest object and format it WDF_REQUEST_REUSE_PARAMS_INIT(&reuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); status = WdfRequestReuse(DeviceExtension->PowerContext.PowerRequest, &reuseParams); if (NT_SUCCESS(status)) { // This request was preformated during initialization so this call should never fail. status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget, DeviceExtension->PowerContext.PowerRequest, IOCTL_SCSI_EXECUTE_IN, NULL, NULL, NULL, NULL, NULL, NULL); if (!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "PowerContextReuseRequest: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n", status)); } } // Do some basic initialization of the PowerRequest, the rest will be done by the caller // of this function if (NT_SUCCESS(status)) { PIO_STACK_LOCATION nextStack = NULL; nextStack = IoGetNextIrpStackLocation(irp); nextStack->MajorFunction = IRP_MJ_SCSI; nextStack->Parameters.Scsi.Srb = &(DeviceExtension->PowerContext.Srb); DeviceExtension->PowerContext.Srb.Length = sizeof(SCSI_REQUEST_BLOCK); DeviceExtension->PowerContext.Srb.OriginalRequest = irp; DeviceExtension->PowerContext.Srb.SenseInfoBuffer = &(DeviceExtension->PowerContext.SenseData); DeviceExtension->PowerContext.Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE; } return status; }
VOID EvtIoDeviceControl( WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode) { NTSTATUS status; BOOLEAN completeRequest = TRUE; WDFDEVICE device = WdfIoQueueGetDevice(Queue); PINPUT_DEVICE pContext = GetDeviceContext(device); ULONG uReportSize; HID_XFER_PACKET Packet; WDF_REQUEST_PARAMETERS params; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "--> %s, code = %d\n", __FUNCTION__, IoControlCode); switch (IoControlCode) { case IOCTL_HID_GET_DEVICE_DESCRIPTOR: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_GET_DEVICE_DESCRIPTOR\n"); // // Return the device's HID descriptor. // ASSERT(pContext->HidDescriptor.bLength != 0); status = RequestCopyFromBuffer(Request, &pContext->HidDescriptor, pContext->HidDescriptor.bLength); break; case IOCTL_HID_GET_DEVICE_ATTRIBUTES: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_GET_DEVICE_ATTRIBUTES\n"); // // Return the device's attributes in a HID_DEVICE_ATTRIBUTES structure. // status = RequestCopyFromBuffer(Request, &pContext->HidDeviceAttributes, sizeof(HID_DEVICE_ATTRIBUTES)); break; case IOCTL_HID_GET_REPORT_DESCRIPTOR: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_GET_REPORT_DESCRIPTOR\n"); // // Return the report descriptor for the HID device. // status = RequestCopyFromBuffer(Request, pContext->HidReportDescriptor, pContext->HidDescriptor.DescriptorList[0].wReportLength); break; case IOCTL_HID_READ_REPORT: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_READ_REPORT\n"); // // Queue up a report request. We'll complete it when we actually // receive data from the device. // status = WdfRequestForwardToIoQueue( Request, pContext->HidQueue); if (NT_SUCCESS(status)) { completeRequest = FALSE; } else { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestForwardToIoQueue failed with 0x%x\n", status); } break; case IOCTL_HID_WRITE_REPORT: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_WRITE_REPORT\n"); // // Write a report to the device, commonly used for controlling keyboard // LEDs. We'll complete the request after the host processes all virtio // buffers we add to the status queue. // WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(Request, ¶ms); if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) { status = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory(&Packet, WdfRequestWdmGetIrp(Request)->UserBuffer, sizeof(HID_XFER_PACKET)); WdfRequestSetInformation(Request, Packet.reportBufferLen); status = ProcessOutputReport(pContext, Request, &Packet); if (NT_SUCCESS(status)) { completeRequest = FALSE; } } break; default: TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "Unrecognized IOCTL %d\n", IoControlCode); status = STATUS_NOT_IMPLEMENTED; break; } if (completeRequest) { WdfRequestComplete(Request, status); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- %s\n", __FUNCTION__); }