VOID OsrFxEvtUsbInterruptPipeReadComplete( WDFUSBPIPE Pipe, WDFMEMORY Buffer, size_t NumBytesTransferred, WDFCONTEXT Context ) /*++ Routine Description: This the completion routine of the continour reader. This can called concurrently on multiprocessor system if there are more than one readers configured. So make sure to protect access to global resources. Arguments: Buffer - This buffer is freed when this call returns. If the driver wants to delay processing of the buffer, it can take an additional referrence. Context - Provided in the WDF_USB_CONTINUOUS_READER_CONFIG_INIT macro Return Value: NT status value --*/ { PUCHAR switchState = NULL; WDFDEVICE device; PDEVICE_CONTEXT pDeviceContext = Context; UNREFERENCED_PARAMETER(NumBytesTransferred); UNREFERENCED_PARAMETER(Pipe); device = WdfObjectContextGetObject(pDeviceContext); ASSERT(NumBytesTransferred == sizeof(UCHAR)); switchState = WdfMemoryGetBuffer(Buffer, NULL); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "OsrFxEvtUsbInterruptPipeReadComplete SwitchState %x\n", *switchState); pDeviceContext->CurrentSwitchState = *switchState; }
VOID CyEvtInterruptINepReaderComplete( WDFUSBPIPE Pipe, WDFMEMORY Buffer, size_t szNumBytesTransferred, WDFCONTEXT Context ) { PUCHAR pucIntData = NULL; PDEVICE_CONTEXT pDeviceContext = Context; WDFDEVICE WdfDevice; UNREFERENCED_PARAMETER(Pipe); WdfDevice = WdfObjectContextGetObject(pDeviceContext); if (szNumBytesTransferred == 0) { CyTraceEvents(TRACE_LEVEL_WARNING, DBG_INIT, "CyEvtInterruptINepReaderComplete Zero length read " "occured on the Interrupt Pipe's Continuous Reader\n" ); return; } ASSERT(szNumBytesTransferred == sizeof(UCHAR)); pucIntData = WdfMemoryGetBuffer(Buffer, NULL); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "CyEvtInterruptINepReaderComplete Data %x\n", *pucIntData); pDeviceContext->ucIntInData = *pucIntData; CyCompleteIoctlRequest(WdfDevice); }
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 OsrFxEvtUsbInterruptPipeReadComplete( WDFUSBPIPE Pipe, WDFMEMORY Buffer, size_t NumBytesTransferred, WDFCONTEXT Context ) /*++ Routine Description: This the completion routine of the continour reader. This can called concurrently on multiprocessor system if there are more than one readers configured. So make sure to protect access to global resources. Arguments: Buffer - This buffer is freed when this call returns. If the driver wants to delay processing of the buffer, it can take an additional referrence. Context - Provided in the WDF_USB_CONTINUOUS_READER_CONFIG_INIT macro Return Value: NT status value --*/ { PMOUSE_STATE mouseState = NULL; WDFDEVICE device; PDEVICE_CONTEXT pDeviceContext = Context; UNREFERENCED_PARAMETER(Pipe); device = WdfObjectContextGetObject(pDeviceContext); // // Make sure that there is data in the read packet. Depending on the device // specification, it is possible for it to return a 0 length read in // certain conditions. // if (NumBytesTransferred == 0) { TraceEvents(TRACE_LEVEL_WARNING, DBG_INIT, "OsrFxEvtUsbInterruptPipeReadComplete Zero length read " "occured on the Interrupt Pipe's Continuous Reader\n" ); return; } ASSERT(NumBytesTransferred == sizeof(UCHAR)); mouseState = WdfMemoryGetBuffer(Buffer, NULL); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "OsrFxEvtUsbInterruptPipeReadComplete SwitchState %x\n", *mouseState); pDeviceContext->CurrentMouseState = *mouseState; // // Handle any pending Interrupt Message IOCTLs. Note that the OSR USB device // will generate an interrupt message when the the device resumes from a low // power state. So if the Interrupt Message IOCTL was sent after the device // has gone to a low power state, the pending Interrupt Message IOCTL will // get completed in the function call below, before the user twiddles the // dip switches on the OSR USB device. If this is not the desired behavior // for your driver, then you could handle this condition by maintaining a // state variable on D0Entry to track interrupt messages caused by power up. // OsrUsbIoctlGetInterruptMessage(device); }
NTSTATUS BthEchoRepeatReaderInitialize( _In_ PBTHECHO_CONNECTION Connection, _In_ PBTHECHO_REPEAT_READER RepeatReader, _In_ size_t BufferSize ) /*++ Description: This routine initializes repeat reader. Arguments: Connection - Connection with which this repeat reader is associated RepeatReader - Repeat reader BufferSize - Buffer size for read Return Value: NTSTATUS Status code. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES attributes; // // Create request object for pending read // Set connection object as the parent for the request // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = WdfObjectContextGetObject(Connection); status = WdfRequestCreate( &attributes, Connection->DevCtxHdr->IoTarget, &RepeatReader->RequestPendingRead ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, "Creating request for pending read failed, " "Status code %!STATUS!\n", status ); goto exit; } if (BufferSize <= 0) { TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, "BufferSize has an invalid value: %I64d\n", BufferSize ); status = STATUS_INVALID_PARAMETER; goto exit; } // // Create memory object for the pending read // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = RepeatReader->RequestPendingRead; status = WdfMemoryCreate( &attributes, NonPagedPoolNx, POOLTAG_BTHECHOSAMPLE, BufferSize, &RepeatReader->MemoryPendingRead, NULL //buffer ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, "Creating memory for pending read failed, " "Status code %!STATUS!\n", status ); goto exit; } // // Initialize Dpc that we will use for resubmitting pending read // KeInitializeDpc( &RepeatReader->ResubmitDpc, BthEchoRepeatReaderResubmitReadDpc, Connection->DevCtxHdr ); // // Initialize event used to wait for stop. // This even is created as signalled. It gets cleared when // request is submitted. // KeInitializeEvent(&RepeatReader->StopEvent, NotificationEvent, TRUE); RepeatReader->Connection = Connection; exit: if (!NT_SUCCESS(status)) { BthEchoRepeatReaderUninitialize(RepeatReader); } return status; }
NTSTATUS FireflySetFeature( IN PDEVICE_CONTEXT DeviceContext, IN UCHAR PageId, IN USHORT FeatureId, IN BOOLEAN EnableFeature ) /*++ Routine Description: This routine sets the HID feature by sending HID ioctls to our device. These IOCTLs will be handled by HIDUSB and converted into USB requests and send to the device. Arguments: DeviceContext - Context for our device PageID - UsagePage of the light control feature. FeatureId - Usage ID of the feature. EnanbleFeature - True to turn the light on, Falst to turn if off. Return Value: NT Status code --*/ { WDF_MEMORY_DESCRIPTOR inputDescriptor, outputDescriptor; NTSTATUS status; HID_COLLECTION_INFORMATION collectionInformation = {0}; PHIDP_PREPARSED_DATA preparsedData; HIDP_CAPS caps; USAGE usage; ULONG usageLength; PCHAR report; WDFIOTARGET hidTarget; WDF_IO_TARGET_OPEN_PARAMS openParams; PAGED_CODE(); // // Preinit for error. // preparsedData = NULL; report = NULL; hidTarget = NULL; status = WdfIoTargetCreate(WdfObjectContextGetObject(DeviceContext), WDF_NO_OBJECT_ATTRIBUTES, &hidTarget); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: WdfIoTargetCreate failed 0x%x\n", status)); return status; } // // Open it up, write access only! // WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( &openParams, &DeviceContext->PdoName, FILE_WRITE_ACCESS); // // We will let the framework to respond automatically to the pnp // state changes of the target by closing and opening the handle. // openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ; status = WdfIoTargetOpen(hidTarget, &openParams); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: WdfIoTargetOpen failed 0x%x\n", status)); goto ExitAndFree; } WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor, (PVOID) &collectionInformation, sizeof(HID_COLLECTION_INFORMATION)); // // Now get the collection information for this device // status = WdfIoTargetSendIoctlSynchronously(hidTarget, NULL, IOCTL_HID_GET_COLLECTION_INFORMATION, NULL, &outputDescriptor, NULL, NULL); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: WdfIoTargetSendIoctlSynchronously failed 0x%x\n", status)); goto ExitAndFree; } preparsedData = (PHIDP_PREPARSED_DATA) ExAllocatePoolWithTag( NonPagedPool, collectionInformation.DescriptorSize, 'ffly'); if (preparsedData == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto ExitAndFree; } WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor, (PVOID) preparsedData, collectionInformation.DescriptorSize); status = WdfIoTargetSendIoctlSynchronously(hidTarget, NULL, IOCTL_HID_GET_COLLECTION_DESCRIPTOR, NULL, &outputDescriptor, NULL, NULL); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: WdfIoTargetSendIoctlSynchronously failed 0x%x\n", status)); goto ExitAndFree; } // // Now get the capabilities. // RtlZeroMemory(&caps, sizeof(HIDP_CAPS)); status = HidP_GetCaps(preparsedData, &caps); if (!NT_SUCCESS(status)) { goto ExitAndFree; } // // Create a report to send to the device. // report = (PCHAR) ExAllocatePoolWithTag( NonPagedPool, caps.FeatureReportByteLength, 'ffly'); if (report == NULL) { goto ExitAndFree; } // // Start with a zeroed report. If we are disabling the feature, this might // be all we need to do. // RtlZeroMemory(report, caps.FeatureReportByteLength); status = STATUS_SUCCESS; if (EnableFeature) { // // Edit the report to reflect the enabled feature // usage = FeatureId; usageLength = 1; status = HidP_SetUsages( HidP_Feature, PageId, 0, &usage, // pointer to the usage list &usageLength, // number of usages in the usage list preparsedData, report, caps.FeatureReportByteLength ); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: HidP_SetUsages failed 0x%x\n", status)); goto ExitAndFree; } } WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputDescriptor, report, caps.FeatureReportByteLength); status = WdfIoTargetSendIoctlSynchronously(hidTarget, NULL, IOCTL_HID_SET_FEATURE, &inputDescriptor, NULL, NULL, NULL); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: WdfIoTargetSendIoctlSynchronously failed 0x%x\n", status)); goto ExitAndFree; } ExitAndFree: if (preparsedData != NULL) { ExFreePool(preparsedData); preparsedData = NULL; } if (report != NULL) { ExFreePool(report); report = NULL; } if (hidTarget != NULL) { WdfObjectDelete(hidTarget); } return status; }