// EvtDeviceD0Entry event callback must perform any operations that are necessary before the specified device is used. // Called every time the hardware needs to be initialized/reinitialized. // This function is not marked pageable because this function is in the device power up path. // This function runs at PASSIVE_LEVEL, even though it is not paged. // NTSTATUS HidFx2EvtDeviceD0Entry(_In_ WDFDEVICE hDevice, _In_ WDF_POWER_DEVICE_STATE previousState) { PDEVICE_EXTENSION pDevContext = NULL; NTSTATUS status = STATUS_SUCCESS; unsigned char bSwitchState = 0; unsigned char bMode = 0; pDevContext = GetDeviceContext(hDevice); TraceVerbose(DBG_PNP, "(%!FUNC!) Enter - coming from %S\n", DbgDevicePowerString(previousState)); SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_OFF); // Retrieve the current switch state and store it in device context status = HidFx2GetSwitchState(hDevice, &bSwitchState); if (NT_SUCCESS(status)) { // Left most switches define Mode bMode = bSwitchState & MODE_SELECTION_BUTTONS_BIT_MASK; switch (bMode) { case SWITCHPACK_SELECTION_FOR_MODE2: pDevContext->driverMode = DM_BUTTON_AND_LED; SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_2); break; case SWITCHPACK_SELECTION_FOR_MODE3: pDevContext->driverMode = DM_SLIDER_SWITCH; SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_3); break; case SWITCHPACK_SELECTION_FOR_MODE4: pDevContext->driverMode = DM_SLIDER_SWITCH_AND_LED; SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_4); break; case SWITCHPACK_SELECTION_FOR_MODE5: pDevContext->driverMode = DM_LED_ONLY; SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_5); break; default: pDevContext->driverMode = DM_BUTTON; SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_1); break; } pDevContext->bCurrentSwitchState = bSwitchState; // Start the target. This will start the continuous reader status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(pDevContext->hInterruptPipe)); if (NT_SUCCESS(status)) { pDevContext->fIsPowerUpSwitchState = TRUE; } } else { TraceErr(DBG_PNP, "(%!FUNC!) Failed to get current switch state, status: %!STATUS!\n", status); } TraceVerbose(DBG_PNP, "(%!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; }
NTSTATUS HidFx2EvtDeviceD0Entry( IN WDFDEVICE Device, IN WDF_POWER_DEVICE_STATE PreviousState ) /*++ Routine Description: EvtDeviceD0Entry event callback must perform any operations that are necessary before the specified device is used. It will be called every time the hardware needs to be (re-)initialized. This function is not marked pageable because this function is in the device power up path. When a function is marked pagable and the code section is paged out, it will generate a page fault which could impact the fast resume behavior because the client driver will have to wait until the system drivers can service this page fault. This function runs at PASSIVE_LEVEL, even though it is not paged. A driver can optionally make this function pageable if DO_POWER_PAGABLE is set. Even if DO_POWER_PAGABLE isn't set, this function still runs at PASSIVE_LEVEL. In this case, though, the function absolutely must not do anything that will cause a page fault. Arguments: Device - Handle to a framework device object. PreviousState - Device power state which the device was in most recently. If the device is being newly started, this will be PowerDeviceUnspecified. Return Value: NTSTATUS --*/ { PDEVICE_EXTENSION devContext = NULL; NTSTATUS status = STATUS_SUCCESS; UCHAR switchState = 0; devContext = GetDeviceContext(Device); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP, "HidFx2EvtDeviceD0Entry Enter - coming from %s\n", DbgDevicePowerString(PreviousState)); // // Retrieve the current switch state and store it in device context // status = HidFx2GetSwitchState(Device, &switchState); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Failed to get current swicth state, status: 0x%x\n", status); return status; } devContext->CurrentSwitchState = switchState; // // Start the target. This will start the continuous reader // status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(devContext->InterruptPipe)); if (NT_SUCCESS(status)) { devContext->IsPowerUpSwitchState = TRUE; } TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "HidFx2EvtDeviceD0Entry Exit, status: 0x%x\n", status); return status; }