VOID VirtRngEvtInterruptDpc(IN WDFINTERRUPT Interrupt, IN WDFOBJECT AssociatedObject) { PDEVICE_CONTEXT context = GetDeviceContext( WdfInterruptGetDevice(Interrupt)); struct virtqueue *vq = context->VirtQueue; PREAD_BUFFER_ENTRY entry; PSINGLE_LIST_ENTRY iter; NTSTATUS status; PVOID buffer; size_t bufferLen; unsigned int length; UNREFERENCED_PARAMETER(AssociatedObject); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "--> %!FUNC! Interrupt: %p", Interrupt); for (;;) { WdfSpinLockAcquire(context->VirtQueueLock); entry = (PREAD_BUFFER_ENTRY)virtqueue_get_buf(vq, &length); if (entry == NULL) { WdfSpinLockRelease(context->VirtQueueLock); break; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Got %p Request: %p Buffer: %p", entry, entry->Request, entry->Buffer); iter = &context->ReadBuffersList; while (iter->Next != NULL) { PREAD_BUFFER_ENTRY current = CONTAINING_RECORD(iter->Next, READ_BUFFER_ENTRY, ListEntry); if (entry == current) { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Delete %p Request: %p Buffer: %p", entry, entry->Request, entry->Buffer); iter->Next = current->ListEntry.Next; break; } else { iter = iter->Next; } }; if ((entry->Request == NULL) || (WdfRequestUnmarkCancelable(entry->Request) == STATUS_CANCELLED)) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "Ignoring a canceled read request: %p", entry->Request); entry->Request = NULL; } WdfSpinLockRelease(context->VirtQueueLock); if (entry->Request != NULL) { status = WdfRequestRetrieveOutputBuffer(entry->Request, length, &buffer, &bufferLen); if (NT_SUCCESS(status)) { length = min(length, (unsigned)bufferLen); RtlCopyMemory(buffer, entry->Buffer, length); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "Complete Request: %p Length: %d", entry->Request, length); WdfRequestCompleteWithInformation(entry->Request, STATUS_SUCCESS, (ULONG_PTR)length); } else { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestRetrieveOutputBuffer failed: %!STATUS!", status); WdfRequestComplete(entry->Request, status); } } ExFreePoolWithTag(entry->Buffer, VIRT_RNG_MEMORY_TAG); ExFreePoolWithTag(entry, VIRT_RNG_MEMORY_TAG); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "<-- %!FUNC!"); }
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 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; }
static NTSTATUS VirtQueueAddBuffer(IN PDEVICE_CONTEXT Context, IN WDFREQUEST Request, IN size_t Length) { PREAD_BUFFER_ENTRY entry; size_t length; struct virtqueue *vq = Context->VirtQueue; struct VirtIOBufferDescriptor sg; int ret; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> %!FUNC!"); entry = (PREAD_BUFFER_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(READ_BUFFER_ENTRY), VIRT_RNG_MEMORY_TAG); if (entry == NULL) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Failed to allocate a read entry."); return STATUS_INSUFFICIENT_RESOURCES; } length = min(Length, PAGE_SIZE); entry->Buffer = ExAllocatePoolWithTag(NonPagedPool, length, VIRT_RNG_MEMORY_TAG); if (entry->Buffer == NULL) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Failed to allocate a read buffer."); ExFreePoolWithTag(entry, VIRT_RNG_MEMORY_TAG); return STATUS_INSUFFICIENT_RESOURCES; } entry->Request = Request; sg.physAddr = MmGetPhysicalAddress(entry->Buffer); sg.length = (unsigned)length; WdfSpinLockAcquire(Context->VirtQueueLock); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Push %p Request: %p Buffer: %p", entry, entry->Request, entry->Buffer); PushEntryList(&Context->ReadBuffersList, &entry->ListEntry); ret = virtqueue_add_buf(vq, &sg, 0, 1, entry, NULL, 0); if (ret < 0) { PSINGLE_LIST_ENTRY removed; TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Failed to add buffer to virt queue."); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Pop %p Request: %p Buffer: %p", entry, entry->Request, entry->Buffer); removed = PopEntryList(&Context->ReadBuffersList); NT_ASSERT(entry == CONTAINING_RECORD( removed, READ_BUFFER_ENTRY, ListEntry)); ExFreePoolWithTag(entry->Buffer, VIRT_RNG_MEMORY_TAG); ExFreePoolWithTag(entry, VIRT_RNG_MEMORY_TAG); WdfSpinLockRelease(Context->VirtQueueLock); return STATUS_UNSUCCESSFUL; } WdfSpinLockRelease(Context->VirtQueueLock); virtqueue_kick(vq); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- %!FUNC!"); return STATUS_SUCCESS; }
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; }
NTSTATUS BthEchoCliRetrieveServerBthAddress( _In_ PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx ) /*++ Description: Retrieve server Bth address Arguments: DevCtx - Client context where we store bth address Return Value: NTSTATUS Status code. --*/ { NTSTATUS status, statusReuse; WDF_MEMORY_DESCRIPTOR outMemDesc; WDF_REQUEST_REUSE_PARAMS ReuseParams; BTH_DEVICE_INFO serverDeviceInfo; WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(DevCtx->Header.Request, &ReuseParams); NT_ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); RtlZeroMemory( &serverDeviceInfo, sizeof(serverDeviceInfo) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, &serverDeviceInfo, sizeof(serverDeviceInfo) ); status = WdfIoTargetSendInternalIoctlSynchronously( DevCtx->Header.IoTarget, DevCtx->Header.Request, IOCTL_INTERNAL_BTHENUM_GET_DEVINFO, NULL, //inMemDesc &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Failed to obtain server device info, Status code %!STATUS!\n", status); goto exit; } DevCtx->ServerBthAddress = serverDeviceInfo.address; exit: return status; }
NTSTATUS OsrFxEvtDevicePrepareHardware( IN WDFDEVICE Device, IN WDFCMRESLIST ResourceList, IN WDFCMRESLIST ResourceListTranslated ) /*++ Routine Description: In this callback, the driver does whatever is necessary to make the hardware ready to use. In the case of a USB device, this involves reading descriptors and selecting interfaces. Arguments: Device - handle to a device Return Value: NT status value --*/ { NTSTATUS status, tempStatus; PDEVICE_CONTEXT pDeviceContext; WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; UNREFERENCED_PARAMETER(ResourceList); UNREFERENCED_PARAMETER(ResourceListTranslated); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> EvtDevicePrepareHardware\n"); pDeviceContext = GetDeviceContext(Device); // // Create a USB device handle so that we can communicate with the // underlying USB stack. The WDFUSBDEVICE handle is used to query, // configure, and manage all aspects of the USB device. // These aspects include device properties, bus properties, // and I/O creation and synchronization. We only create device the first // the PrepareHardware is called. If the device is restarted by pnp manager // for resource rebalance, we will use the same device handle but then select // the interfaces again because the USB stack could reconfigure the device on // restart. // if (pDeviceContext->UsbDevice == NULL) { status = WdfUsbTargetDeviceCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &pDeviceContext->UsbDevice); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceCreate failed with Status code %!STATUS!\n", status); return status; } } WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams); status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams); if(!NT_SUCCESS(status)) { WDF_USB_DEVICE_INFORMATION deviceInfo; TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceSelectConfig failed %!STATUS! \n", status); // // detect if we are connected to a 1.1 USB port // WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo); tempStatus = WdfUsbTargetDeviceRetrieveInformation(pDeviceContext->UsbDevice, &deviceInfo); if (NT_SUCCESS(tempStatus)) { // // Since the Osr USB fx2 device is capable of working at high speed, the only reason // the device would not be working at high speed is if the port doesn't // support it. If the port doesn't support high speed it is a 1.1 port // if ((deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) == 0) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, " On a 1.1 USB port on Windows Vista" " this is expected as the OSR USB Fx2 board's Interrupt EndPoint descriptor" " doesn't conform to the USB specification. Windows Vista detects this and" " returns an error. \n" ); } } return status; } pDeviceContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; status = OsrFxConfigContReaderForInterruptEndPoint(pDeviceContext); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- EvtDevicePrepareHardware\n"); return status; }
CMyReadWriteQueue::OnRead( __in IWDFIoQueue *pWdfQueue, __in IWDFIoRequest *pWdfRequest, __in SIZE_T BytesToRead ) /*++ Routine Description: Read dispatch routine IQueueCallbackRead Aruments: pWdfQueue - Framework Queue instance pWdfRequest - Framework Request instance BytesToRead - Lenth of bytes in the read buffer Copy available data into the read buffer Return Value: VOID --*/ { UNREFERENCED_PARAMETER(pWdfQueue); TraceEvents(TRACE_LEVEL_INFORMATION, TEST_TRACE_QUEUE, "%!FUNC!: Queue %p Request %p BytesToTransfer %d\n", this, pWdfRequest, (ULONG)(ULONG_PTR)BytesToRead ); HRESULT hr = S_OK; IWDFMemory * pOutputMemory = NULL; pWdfRequest->GetOutputMemory(&pOutputMemory); hr = m_Device->GetInputPipe()->FormatRequestForRead( pWdfRequest, NULL, //pFile pOutputMemory, NULL, //Memory offset NULL //DeviceOffset ); if (FAILED(hr)) { pWdfRequest->Complete(hr); } else { ForwardFormattedRequest(pWdfRequest, m_Device->GetInputPipe()); } SAFE_RELEASE(pOutputMemory); return; }
HRESULT CMyDevice::SetPowerManagement( VOID ) /*++ Routine Description: This method enables the idle and wake functionality using UMDF. UMDF has been set as the power policy owner (PPO) for the device stack and we are using power managed queues. Arguments: None Return Value: Status --*/ { HRESULT hr; // // Enable USB selective suspend on the device. // hr = m_FxDevice->AssignS0IdleSettings( IdleUsbSelectiveSuspend, PowerDeviceMaximum, IDLE_TIMEOUT_IN_MSEC, IdleAllowUserControl, WdfUseDefault); if (FAILED(hr)) { TraceEvents(TRACE_LEVEL_ERROR, TEST_TRACE_DEVICE, "%!FUNC! Unable to assign S0 idle settings for the device %!HRESULT!", hr ); } // // Enable Sx wake settings // if (SUCCEEDED(hr)) { hr = m_FxDevice->AssignSxWakeSettings( PowerDeviceMaximum, WakeAllowUserControl, WdfUseDefault); if (FAILED(hr)) { TraceEvents(TRACE_LEVEL_ERROR, TEST_TRACE_DEVICE, "%!FUNC! Unable to set Sx Wake Settings for the device %!HRESULT!", hr ); } } return hr; }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: Driver initialization entry point. This entry point is called directly by the I/O system. Arguments: DriverObject - pointer to the driver object RegistryPath - pointer to a unicode string representing the path, to driver-specific key in the registry. Return Value: NTSTATUS - if the status value is not STATUS_SUCCESS, the driver will get unloaded immediately. --*/ { NTSTATUS status = STATUS_SUCCESS; WDF_DRIVER_CONFIG config; WDF_OBJECT_ATTRIBUTES attributes; // // Initialize WDF WPP tracing. // WPP_INIT_TRACING( DriverObject, RegistryPath ); // // TraceEvents function is mapped to DoTraceMessage provided by // WPP by using a directive in the sources file. // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Pci9656 Sample - Driver Framework Edition."); // // Initialize the Driver Config structure. // WDF_DRIVER_CONFIG_INIT( &config, PLxEvtDeviceAdd ); // // Register a cleanup callback so that we can call WPP_CLEANUP when // the framework driver object is deleted during driver unload. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.EvtCleanupCallback = PlxEvtDriverContextCleanup; status = WdfDriverCreate( DriverObject, RegistryPath, &attributes, &config, WDF_NO_HANDLE); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDriverCreate failed with status %!STATUS!", status); // // Cleanup tracing here because DriverContextCleanup will not be called // as we have failed to create WDFDRIVER object itself. // Please note that if your return failure from DriverEntry after the // WDFDRIVER object is created successfully, you don't have to // call WPP cleanup because in those cases DriverContextCleanup // will be executed when the framework deletes the DriverObject. // WPP_CLEANUP(DriverObject); } return status; }
CMyReadWriteQueue::OnWrite( __in IWDFIoQueue *pWdfQueue, __in IWDFIoRequest *pWdfRequest, __in SIZE_T BytesToWrite ) /*++ Routine Description: Write dispatch routine IQueueCallbackWrite Aruments: pWdfQueue - Framework Queue instance pWdfRequest - Framework Request instance BytesToWrite - Lenth of bytes in the write buffer Allocate and copy data to local buffer Return Value: VOID --*/ { UNREFERENCED_PARAMETER(pWdfQueue); TraceEvents(TRACE_LEVEL_INFORMATION, TEST_TRACE_QUEUE, "%!FUNC!: Queue %p Request %p BytesToTransfer %d\n", this, pWdfRequest, (ULONG)(ULONG_PTR)BytesToWrite ); HRESULT hr = S_OK; IWDFMemory * pInputMemory = NULL; IWDFUsbTargetPipe * pOutputPipe = m_Device->GetOutputPipe(); pWdfRequest->GetInputMemory(&pInputMemory); hr = pOutputPipe->FormatRequestForWrite( pWdfRequest, NULL, //pFile pInputMemory, NULL, //Memory offset NULL //DeviceOffset ); if (FAILED(hr)) { pWdfRequest->Complete(hr); } else { ForwardFormattedRequest(pWdfRequest, pOutputPipe); } SAFE_RELEASE(pInputMemory); return; }
NTSTATUS PLxEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. Here the driver should register all the PNP, power and Io callbacks, register interfaces and allocate other software resources required by the device. The driver can query any interfaces or get the config space information from the bus driver but cannot access hardware registers or initialize the device. Arguments: Return Value: --*/ { NTSTATUS status = STATUS_SUCCESS; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES attributes; WDFDEVICE device; PDEVICE_EXTENSION devExt = NULL; UNREFERENCED_PARAMETER( Driver ); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PLxEvtDeviceAdd"); PAGED_CODE(); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); // // Zero out the PnpPowerCallbacks structure. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // Set Callbacks for any of the functions we are interested in. // If no callback is set, Framework will take the default action // by itself. // pnpPowerCallbacks.EvtDevicePrepareHardware = PLxEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = PLxEvtDeviceReleaseHardware; // // These two callbacks set up and tear down hardware state that must be // done every time the device moves in and out of the D0-working state. // pnpPowerCallbacks.EvtDeviceD0Entry = PLxEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = PLxEvtDeviceD0Exit; // // Register the PnP Callbacks.. // WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // // Initialize Fdo Attributes. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); // // By opting for SynchronizationScopeDevice, we tell the framework to // synchronize callbacks events of all the objects directly associated // with the device. In this driver, we will associate queues and // and DpcForIsr. By doing that we don't have to worrry about synchronizing // access to device-context by Io Events and DpcForIsr because they would // not concurrently ever. Framework will serialize them by using an // internal device-lock. // attributes.SynchronizationScope = WdfSynchronizationScopeDevice; // // Create the device // status = WdfDeviceCreate( &DeviceInit, &attributes, &device ); if (!NT_SUCCESS(status)) { // // Device Initialization failed. // TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "DeviceCreate failed %!STATUS!", status); return status; } // // Get the DeviceExtension and initialize it. PLxGetDeviceContext is an inline function // defined by WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in the // private header file. This function will do the type checking and return // the device context. If you pass a wrong object a wrong object handle // it will return NULL and assert if run under framework verifier mode. // devExt = PLxGetDeviceContext(device); devExt->Device = device; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, " AddDevice PDO (0x%p) FDO (0x%p), DevExt (0x%p)", WdfDeviceWdmGetPhysicalDevice(device), WdfDeviceWdmGetDeviceObject(device), devExt); // // Tell the Framework that this device will need an interface // // NOTE: See the note in Public.h concerning this GUID value. // status = WdfDeviceCreateDeviceInterface( device, (LPGUID) &GUID_PLX_INTERFACE, NULL ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "<-- DeviceCreateDeviceInterface " "failed %!STATUS!", status); return status; } // // Set the idle and wait-wake policy for this device. // status = PLxSetIdleAndWakeSettings(devExt); if (!NT_SUCCESS (status)) { // // NOTE: The attempt to set the Idle and Wake options // is a best-effort try. Failure is probably due to // the non-driver environmentals, such as the system, // bus or OS indicating that Wake is not supported for // this case. // All that being said, it probably not desirable to // return the failure code as it would cause the // AddDevice to fail and Idle and Wake are probably not // "must-have" options. // // You must decide for your case whether Idle/Wake are // "must-have" options...but my guess is probably not. // #if 1 status = STATUS_SUCCESS; #else return status; #endif } // // Initalize the Device Extension. // status = PLxInitializeDeviceExtension(devExt); if (!NT_SUCCESS(status)) { return status; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- PLxEvtDeviceAdd %!STATUS!", status); return status; }
VOID HealthThermometerServiceContent::TemperatureMeasurementEvent( _In_ BTH_LE_GATT_EVENT_TYPE EventType, _In_ PVOID EventOutParameter ) { HRESULT hr = S_OK; PBLUETOOTH_GATT_VALUE_CHANGED_EVENT ValueChangedEventParameters = NULL; TEMPERATURE_MEASUREMENT Measurement = {0}; IPortableDeviceValues * pEventParams = NULL; BYTE* pBuffer = NULL; DWORD cbBuffer = 0; if (CharacteristicValueChangedEvent != EventType) { return; } ValueChangedEventParameters = (PBLUETOOTH_GATT_VALUE_CHANGED_EVENT)EventOutParameter; // // Our value is at least 5 bytes // if (5 > ValueChangedEventParameters->CharacteristicValue->DataSize) { hr = E_FAIL; CHECK_HR(hr, "Invalid data size: %d, expencting at least 5 bytes", ValueChangedEventParameters->CharacteristicValue->DataSize); } if (SUCCEEDED(hr)) { ULONG mantissa = 0; LONG exponent = 0; mantissa = (ULONG)(((ULONG)ValueChangedEventParameters->CharacteristicValue->Data[3] << (ULONG)16) | ((ULONG)ValueChangedEventParameters->CharacteristicValue->Data[2] << (ULONG)8) | ((ULONG)ValueChangedEventParameters->CharacteristicValue->Data[1] << (ULONG)0)); exponent = 0xFFFFFF00 | (LONG)ValueChangedEventParameters->CharacteristicValue->Data[4]; Measurement.Value = (double)mantissa * pow((double)10.0, (double)exponent); TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FLAG_DEVICE, "Received a value change event, new value [%.2f]", Measurement.Value); } // // Get the timestamp // if (SUCCEEDED(hr)) { FILETIME fTime; GetSystemTimeAsFileTime(&fTime); ConvertFileTimeToUlonglong(&fTime, &Measurement.TimeStamp); } // // CoCreate a collection to store the property set event parameters. // if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDeviceValues, (VOID**) &pEventParams); CHECK_HR(hr, "Failed to CoCreateInstance CLSID_PortableDeviceValues"); } if (SUCCEEDED(hr)) { hr = pEventParams->SetGuidValue(WPD_EVENT_PARAMETER_EVENT_ID, EVENT_HealthThermometerService_TemperatureMeasurement); CHECK_HR(hr, "Failed to add WPD_EVENT_PARAMETER_EVENT_ID"); } // // Set the timestamp // if (SUCCEEDED(hr)) { hr = pEventParams->SetUnsignedLargeIntegerValue(EVENT_PARAMETER_HealthTemperatureService_Measurement_TimeStamp, Measurement.TimeStamp); CHECK_HR(hr, "Failed to add EVENT_PARAMETER_HealthTemperatureService_Measurement_TimeStamp"); } // // Set the measurement Value // if (SUCCEEDED(hr)) { hr = pEventParams->SetFloatValue(EVENT_PARAMETER_HealthTemperatureService_Measurement_Value, (float)Measurement.Value); CHECK_HR(hr, "Failed to add EVENT_PARAMETER_HealthTemperatureService_Measurement_Value"); } // // Adding this event parameter will allow WPD to scope this event to the container functional object // if (SUCCEEDED(hr)) { hr = pEventParams->SetStringValue(WPD_EVENT_PARAMETER_OBJECT_PARENT_PERSISTENT_UNIQUE_ID, ParentPersistentUniqueID); CHECK_HR(hr, "Failed to add WPD_EVENT_PARAMETER_OBJECT_PARENT_PERSISTENT_UNIQUE_ID"); } // // Adding this event parameter will allow WPD to scope this event to the container functional object // if (SUCCEEDED(hr)) { hr = pEventParams->SetStringValue(WPD_OBJECT_CONTAINER_FUNCTIONAL_OBJECT_ID, SERVICE_OBJECT_ID); CHECK_HR(hr, "Failed to add WPD_OBJECT_CONTAINER_FUNCTIONAL_OBJECT_ID"); } // // Create a buffer with the serialized parameters // if (SUCCEEDED(hr)) { hr = m_pWpdSerializer->GetBufferFromIPortableDeviceValues(pEventParams, &pBuffer, &cbBuffer); CHECK_HR(hr, "Failed to get buffer from IPortableDeviceValues"); } if (SUCCEEDED(hr) && NULL == pBuffer) { hr = E_FAIL; CHECK_HR(hr, "pBuffer is NULL"); } // // Send the event // if (SUCCEEDED(hr)) { hr = m_pDevice->PostEvent(WPD_EVENT_NOTIFICATION, WdfEventBroadcast, pBuffer, cbBuffer); CHECK_HR(hr, "Failed to post WPD (broadcast) event"); } // // Cleanup // if (NULL != pBuffer) { CoTaskMemFree(pBuffer); pBuffer = NULL; } if (NULL != pEventParams) { pEventParams->Release(); pEventParams = NULL; } }
FORCEINLINE NTSTATUS ExecuteOpcode ( __in PUCHAR SpiBar, __in UCHAR OpcodeIndex, __in ULONG Offset ) { NTSTATUS Status; ULONG SwSeqRegs; LONG Timeout; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> ExecuteOpcode\n"); Timeout = TIMEOUT; TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "SSFS_SSFC: 0x%08x.\n", READ_REGISTER_ULONG((PULONG) (SpiBar + SSFS_SSFC_OFFSET))); do { SwSeqRegs = READ_REGISTER_ULONG((PULONG) (SpiBar + SSFS_SSFC_OFFSET)); if ((SwSeqRegs & SSFS_SCIP) == 0) { break; } KeStallExecutionProcessor(10); } while (--Timeout > 0); if (Timeout == 0) { TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "SCIP was not cleared.\n"); Status = STATUS_DEVICE_BUSY; goto End; } // // Program the offset, even if it is not needed (to simplify logic). // SPI addresses are 24 bits long. // WRITE_REGISTER_ULONG((PULONG) (SpiBar + FADDR_OFFSET), (Offset & 0x00FFFFFF)); // // Clear error status registers while preserving reserved bits. // SwSeqRegs &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK; SwSeqRegs |= SSFS_CDS | SSFS_FCERR; WRITE_REGISTER_ULONG((PULONG) (SpiBar + SSFS_SSFC_OFFSET), SwSeqRegs); // // Set the opcode index, relative to the OPMENU register. // SwSeqRegs |= ((ULONG) (OpcodeIndex & 0x07)) << (8 + 4); // // Start. // SwSeqRegs |= SSFC_SCGO; WRITE_REGISTER_ULONG((PULONG) (SpiBar + SSFS_SSFC_OFFSET), SwSeqRegs); // // Wait for any of the Cycle Done Status and Flash Cycle Error registers. // Timeout = TIMEOUT; TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "SSFS_SSFC: 0x%08x.\n", READ_REGISTER_ULONG((PULONG) (SpiBar + SSFS_SSFC_OFFSET))); while ((READ_REGISTER_ULONG((PULONG) (SpiBar + SSFS_SSFC_OFFSET)) & (SSFS_CDS | SSFS_FCERR)) == 0 && --Timeout > 0) { KeStallExecutionProcessor(10); } if (Timeout == 0) { TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "Timeout while waiting for a cycle to complete.\n"); Status = STATUS_TIMEOUT; goto End; } SwSeqRegs = READ_REGISTER_ULONG((PULONG) (SpiBar + SSFS_SSFC_OFFSET)); if (SwSeqRegs & SSFS_FCERR) { TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "Transaction error.\n"); SwSeqRegs &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK; WRITE_REGISTER_ULONG((PULONG) (SpiBar + SSFS_SSFC_OFFSET), SwSeqRegs | SSFS_FCERR); Status = STATUS_DEVICE_DATA_ERROR; goto End; } End: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "<-- ExecuteOpcode\n"); return Status; }
NTSTATUS BthEchoCliRetrievePsmFromSdpRecord( _In_ PBTHDDI_SDP_PARSE_INTERFACE SdpParseInterface, _In_ PBTH_SDP_STREAM_RESPONSE ServerSdpRecord, _Out_ USHORT * Psm ) /*++ Description: Retrieve PSM from the SDP record Arguments: sdpParseInterface - Parse interface used for sdp parse functions ServerSdpRecord - SDP record to obtain Psm from Psm - Psm retrieved Return Value: NTSTATUS Status code. --*/ { NTSTATUS status = STATUS_SUCCESS; PUCHAR nextElement; ULONG nextElementSize; PSDP_TREE_ROOT_NODE sdpTree = NULL; PSDP_NODE nodeProtoDescList = NULL; PSDP_NODE nodeProto0 = NULL; PSDP_NODE nodeProto0UUID = NULL; PSDP_NODE nodeProto0SParam0 = NULL; SdpParseInterface->SdpGetNextElement( &(ServerSdpRecord->response[0]), ServerSdpRecord->responseSize, NULL, &nextElement, &nextElementSize ); if(nextElementSize == 0) { status = STATUS_DEVICE_DATA_ERROR; TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "Getting first element from SDP record failed, returning status code %!STATUS!\n", status); goto exit; } status = SdpParseInterface->SdpConvertStreamToTree( nextElement, nextElementSize, &sdpTree, POOLTAG_BTHECHOSAMPLE ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "Converting SDP record to tree failed, status code %!STATUS!\n", status); goto exit; } // //Find PROTOCOL_DESCRIPTOR_LIST in the tree // status = SdpParseInterface->SdpFindAttributeInTree( sdpTree, (USHORT)SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST, &nodeProtoDescList ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "FindAttribute failed for SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST, status code %!STATUS!\n", status); goto exit0; } if(nodeProtoDescList->hdr.Type != SDP_TYPE_SEQUENCE) { goto SdpFormatError; } // // Get the next sequence. // if(nodeProtoDescList->u.sequence.Link.Flink == NULL) { goto SdpFormatError; } nodeProto0 = CONTAINING_RECORD(nodeProtoDescList->u.sequence.Link.Flink, SDP_NODE, hdr.Link); if(nodeProto0->hdr.Type != SDP_TYPE_SEQUENCE) { goto SdpFormatError; } if(nodeProto0->u.sequence.Link.Flink == NULL) { goto SdpFormatError; } // // Get the first GUID, (L2CAP) // nodeProto0UUID = CONTAINING_RECORD(nodeProto0->u.sequence.Link.Flink, SDP_NODE, hdr.Link); if(nodeProto0UUID->hdr.Type != SDP_TYPE_UUID) { goto SdpFormatError; } if(nodeProto0UUID->hdr.Link.Flink == NULL) { goto SdpFormatError; } // // Get the PSM // nodeProto0SParam0 = CONTAINING_RECORD(nodeProto0UUID->hdr.Link.Flink, SDP_NODE, hdr.Link); if(nodeProto0SParam0->hdr.SpecificType != SDP_ST_UINT16) { goto SdpFormatError; } *Psm = nodeProto0SParam0->u.uint16; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_SDP, "Psm: %d", *Psm); goto exit0; SdpFormatError: status = STATUS_DEVICE_DATA_ERROR; TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "Parsing error due to invalid SDP record, returning status code %!STATUS!\n", status); exit0: SdpParseInterface->SdpFreeTree(sdpTree); exit: return status; }
VOID FireShockEvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) /*++ Routine Description: This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. OutputBufferLength - Size of the output buffer in bytes InputBufferLength - Size of the input buffer in bytes IoControlCode - I/O control code. Return Value: VOID --*/ { NTSTATUS status = STATUS_SUCCESS; size_t bufferLength; size_t transferred = 0; PDEVICE_CONTEXT pDeviceContext; PFIRESHOCK_GET_HOST_BD_ADDR pGetHostAddr; PFIRESHOCK_GET_DEVICE_BD_ADDR pGetDeviceAddr; PFIRESHOCK_SET_HOST_BD_ADDR pSetHostAddr; PFIRESHOCK_GET_DEVICE_TYPE pGetDeviceType; TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "%!FUNC! Queue 0x%p, Request 0x%p OutputBufferLength %d InputBufferLength %d IoControlCode %d", Queue, Request, (int)OutputBufferLength, (int)InputBufferLength, IoControlCode); pDeviceContext = DeviceGetContext(WdfIoQueueGetDevice(Queue)); switch (IoControlCode) { #pragma region IOCTL_FIRESHOCK_GET_HOST_BD_ADDR case IOCTL_FIRESHOCK_GET_HOST_BD_ADDR: TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "IOCTL_FIRESHOCK_GET_HOST_BD_ADDR"); status = WdfRequestRetrieveOutputBuffer( Request, sizeof(FIRESHOCK_GET_HOST_BD_ADDR), (LPVOID)&pGetHostAddr, &bufferLength); if (NT_SUCCESS(status) && OutputBufferLength == sizeof(FIRESHOCK_GET_HOST_BD_ADDR)) { transferred = OutputBufferLength; RtlCopyMemory(&pGetHostAddr->Host, &pDeviceContext->HostAddress, sizeof(BD_ADDR)); } break; #pragma endregion #pragma region IOCTL_FIRESHOCK_GET_DEVICE_BD_ADDR case IOCTL_FIRESHOCK_GET_DEVICE_BD_ADDR: TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "IOCTL_FIRESHOCK_GET_DEVICE_BD_ADDR"); status = WdfRequestRetrieveOutputBuffer( Request, sizeof(FIRESHOCK_GET_DEVICE_BD_ADDR), (LPVOID)&pGetDeviceAddr, &bufferLength); if (NT_SUCCESS(status) && OutputBufferLength == sizeof(FIRESHOCK_GET_DEVICE_BD_ADDR)) { transferred = OutputBufferLength; RtlCopyMemory(&pGetDeviceAddr->Device, &pDeviceContext->DeviceAddress, sizeof(BD_ADDR)); } break; #pragma endregion #pragma region IOCTL_FIRESHOCK_SET_HOST_BD_ADDR case IOCTL_FIRESHOCK_SET_HOST_BD_ADDR: TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "IOCTL_FIRESHOCK_SET_HOST_BD_ADDR"); status = WdfRequestRetrieveInputBuffer( Request, sizeof(FIRESHOCK_SET_HOST_BD_ADDR), (LPVOID)&pSetHostAddr, &bufferLength); if (NT_SUCCESS(status) && InputBufferLength == sizeof(FIRESHOCK_SET_HOST_BD_ADDR)) { UCHAR controlBuffer[SET_HOST_BD_ADDR_CONTROL_BUFFER_LENGTH]; RtlZeroMemory(controlBuffer, SET_HOST_BD_ADDR_CONTROL_BUFFER_LENGTH); RtlCopyMemory(&controlBuffer[2], &pSetHostAddr->Host, sizeof(BD_ADDR)); status = SendControlRequest( pDeviceContext, BmRequestHostToDevice, BmRequestClass, SetReport, Ds3FeatureHostAddress, 0, controlBuffer, SET_HOST_BD_ADDR_CONTROL_BUFFER_LENGTH); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "Setting host address failed with %!STATUS!", status); break; } RtlCopyMemory(&pDeviceContext->HostAddress, &pSetHostAddr->Host, sizeof(BD_ADDR)); } break; #pragma endregion #pragma region IOCTL_FIRESHOCK_GET_DEVICE_TYPE case IOCTL_FIRESHOCK_GET_DEVICE_TYPE: TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "IOCTL_FIRESHOCK_GET_DEVICE_TYPE"); status = WdfRequestRetrieveOutputBuffer( Request, sizeof(FIRESHOCK_GET_DEVICE_TYPE), (LPVOID)&pGetDeviceType, &bufferLength); if (NT_SUCCESS(status) && OutputBufferLength == sizeof(FIRESHOCK_GET_DEVICE_TYPE)) { transferred = OutputBufferLength; pGetDeviceType->DeviceType = pDeviceContext->DeviceType; } break; #pragma endregion } WdfRequestCompleteWithInformation(Request, status, transferred); }
_IRQL_requires_same_ NTSTATUS BthEchoCliOpenRemoteConnection( _In_ PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx, _In_ WDFFILEOBJECT FileObject, _In_ WDFREQUEST Request ) /*++ Description: This routine is invoked by BthEchoCliEvtDeviceFileCreate. In this routine we send down open channel BRB. This routine allocates open channel BRB. If the request is sent down successfully completion routine needs to free this BRB. Arguments: _In_ PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx - _In_ WDFFILEOBJECT FileObject - _In_ WDFREQUEST Request - Return Value: NTSTATUS Status code. --*/ { NTSTATUS status; WDFOBJECT connectionObject; struct _BRB_L2CA_OPEN_ENHANCED_CHANNEL *brb = NULL; PBTHECHO_CONNECTION connection = NULL; PBTHECHOSAMPLE_CLIENT_FILE_CONTEXT fileCtx = GetFileContext(FileObject); ULONG modeConfigFlag = CM_BASIC; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONNECT, "Connect request"); // // Create the connection object that would store information // about the open channel // // Set file object as the parent for this connection object // status = BthEchoConnectionObjectCreate( &DevCtx->Header, FileObject, //parent &connectionObject ); if (!NT_SUCCESS(status)) { goto exit; } connection = GetConnectionObjectContext(connectionObject); connection->ConnectionState = ConnectionStateConnecting; // // Get the BRB from request context and initialize it as // BRB_L2CA_OPEN_CHANNEL BRB // brb = (struct _BRB_L2CA_OPEN_ENHANCED_CHANNEL *)GetRequestContext(Request); DevCtx->Header.ProfileDrvInterface.BthReuseBrb( (PBRB)brb, BRB_L2CA_OPEN_ENHANCED_CHANNEL ); brb->Hdr.ClientContext[0] = connection; brb->BtAddress = DevCtx->ServerBthAddress; brb->Psm = fileCtx->ServerPsm; brb->ChannelFlags = CF_ROLE_EITHER; brb->ConfigOut.Flags = CFG_ENHANCED; // // Open an ERTM channel if the local host supports it // if (DevCtx->Header.LocalFeatures.Mask & BTH_HOST_FEATURE_ENHANCED_RETRANSMISSION_MODE) { modeConfigFlag |= CM_RETRANSMISSION_AND_FLOW; brb->ConfigOut.ModeConfig.Flags = modeConfigFlag; // // Mode is specified using Flags above and this should be 0. // brb->ConfigOut.ModeConfig.RetransmissionAndFlow.Mode = 0; brb->ConfigOut.ModeConfig.RetransmissionAndFlow.MaxTransmit = L2CAP_RAF_DEFAULT_MAXTRANSMIT; brb->ConfigOut.ModeConfig.RetransmissionAndFlow.MaxPDUSize = L2CAP_RAF_DEFAULT_MAX_PDU_SIZE; brb->ConfigOut.ModeConfig.RetransmissionAndFlow.TxWindowSize = L2CAP_RAF_DEFAULT_TX_WINDOW_SIZE; } brb->ConfigOut.Flags |= CFG_MTU; brb->ConfigOut.Mtu.Max = L2CAP_DEFAULT_MTU; brb->ConfigOut.Mtu.Min = L2CAP_MIN_MTU; brb->ConfigOut.Mtu.Preferred = L2CAP_DEFAULT_MTU; brb->ConfigIn.Flags = CFG_MTU; brb->ConfigIn.Mtu.Max = brb->ConfigOut.Mtu.Max; brb->ConfigIn.Mtu.Min = brb->ConfigOut.Mtu.Min; brb->ConfigIn.Mtu.Preferred = brb->ConfigOut.Mtu.Max; // // Get notificaiton about remote disconnect // brb->CallbackFlags = CALLBACK_DISCONNECT; brb->Callback = &BthEchoCliIndicationCallback; brb->CallbackContext = connection; brb->ReferenceObject = (PVOID) WdfDeviceWdmGetDeviceObject(DevCtx->Header.Device); brb->IncomingQueueDepth = 50; status = BthEchoSharedSendBrbAsync( DevCtx->Header.IoTarget, Request, (PBRB) brb, sizeof(*brb), BthEchoCliRemoteConnectCompletion, brb //Context ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_CONNECT, "Sending brb for opening connection failed, returning status code %!STATUS!\n", status); goto exit; } exit: if(!NT_SUCCESS(status)) { if (connection) { // // Set the right state to facilitate debugging // connection->ConnectionState = ConnectionStateConnectFailed; } // // In case of failure of this routine we will fail // Create which will delete file object and since connection object // is child of the file object, it will be deleted too // } return status; }
NTSTATUS BalloonEvtDevicePrepareHardware( IN WDFDEVICE Device, IN WDFCMRESLIST ResourceList, IN WDFCMRESLIST ResourceListTranslated ) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN foundPort = FALSE; PHYSICAL_ADDRESS PortBasePA = {0}; ULONG PortLength = 0; ULONG i; WDF_INTERRUPT_INFO interruptInfo; PDEVICE_CONTEXT devCtx = NULL; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__); UNREFERENCED_PARAMETER(ResourceList); PAGED_CODE(); devCtx = GetDeviceContext(Device); for (i=0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++) { desc = WdfCmResourceListGetDescriptor( ResourceListTranslated, i ); if(!desc) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfResourceCmGetDescriptor failed\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } switch (desc->Type) { case CmResourceTypePort: if (!foundPort && desc->u.Port.Length >= 0x20) { devCtx->PortMapped = (desc->Flags & CM_RESOURCE_PORT_IO) ? FALSE : TRUE; PortBasePA = desc->u.Port.Start; PortLength = desc->u.Port.Length; foundPort = TRUE; if (devCtx->PortMapped) { devCtx->PortBase = (PUCHAR) MmMapIoSpace( PortBasePA, PortLength, MmNonCached ); if (!devCtx->PortBase) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, " Unable to map port range %08I64X, length %d\n", PortBasePA.QuadPart, PortLength); return STATUS_INSUFFICIENT_RESOURCES; } devCtx->PortCount = PortLength; } else { devCtx->PortBase = (PUCHAR)(ULONG_PTR) PortBasePA.QuadPart; devCtx->PortCount = PortLength; } } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-> Port Resource [%08I64X-%08I64X]\n", desc->u.Port.Start.QuadPart, desc->u.Port.Start.QuadPart + desc->u.Port.Length); break; default: break; } } if (!foundPort) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, " Missing resources\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } WDF_INTERRUPT_INFO_INIT(&interruptInfo); WdfInterruptGetInfo(devCtx->WdfInterrupt, &interruptInfo); VirtIODeviceInitialize(&devCtx->VDevice, (ULONG_PTR)devCtx->PortBase, sizeof(devCtx->VDevice)); VirtIODeviceSetMSIXUsed(&devCtx->VDevice, interruptInfo.MessageSignaled); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__); return status; }
VOID BthEchoCliRemoteConnectCompletion( _In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, _In_ WDFCONTEXT Context ) /*++ Description: Completion routine for Create request which we format as open channel BRB and send down the stack. We complete the Create request in this routine. We receive open channel BRB as the context. This BRB is part of the request context and doesn't need to be freed explicitly. Connection is part of the context in the BRB. Arguments: Request - Create request that we formatted with open channel BRB Target - Target to which we sent the request Params - Completion params Context - We receive BRB as the context Return Value: NTSTATUS Status code. --*/ { NTSTATUS status; struct _BRB_L2CA_OPEN_CHANNEL *brb; PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx; PBTHECHO_CONNECTION connection; DevCtx = GetClientDeviceContext(WdfIoTargetGetDevice(Target)); status = Params->IoStatus.Status; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONNECT, "Connection completion, status: %!STATUS!", status); brb = (struct _BRB_L2CA_OPEN_CHANNEL *) Context; connection = (PBTHECHO_CONNECTION) brb->Hdr.ClientContext[0]; // // In the client we don't check for ConnectionStateDisconnecting state // because only file close generates disconnect which // cannot happen before create completes. And we complete Create // only after we process this completion. // if(NT_SUCCESS(status)) { connection->OutMTU = brb->OutResults.Params.Mtu; connection->InMTU = brb->InResults.Params.Mtu; connection->ChannelHandle = brb->ChannelHandle; connection->RemoteAddress = brb->BtAddress; connection->ConnectionState = ConnectionStateConnected; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONNECT, "Connection established to server"); // // Call the function in device.c (BthEchoCliConnectionStateConnected) // for any post processing after connection has been established // status = BthEchoCliConnectionStateConnected(WdfRequestGetFileObject(Request), connection); if (!NT_SUCCESS(status)) { // // If such post processing fails we disconnect // BthEchoConnectionObjectRemoteDisconnect( &(DevCtx->Header), connection ); } } else { connection->ConnectionState = ConnectionStateConnectFailed; } // // Complete the Create request // WdfRequestComplete(Request, status); return; }
NTSTATUS BalloonDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { NTSTATUS status = STATUS_SUCCESS; WDFDEVICE device; PDEVICE_CONTEXT devCtx = NULL; WDF_INTERRUPT_CONFIG interruptConfig; WDF_FILEOBJECT_CONFIG fileConfig; WDF_OBJECT_ATTRIBUTES attributes; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = BalloonEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = BalloonEvtDeviceReleaseHardware; pnpPowerCallbacks.EvtDeviceD0Entry = BalloonEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = BalloonEvtDeviceD0Exit; pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = BalloonEvtDeviceD0ExitPreInterruptsDisabled; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, WDF_NO_EVENT_CALLBACK, BalloonEvtFileClose, WDF_NO_EVENT_CALLBACK ); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); attributes.EvtCleanupCallback = BalloonEvtDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreate failed with status 0x%08x\n", status); return status; } devCtx = GetDeviceContext(device); WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, BalloonInterruptIsr, BalloonInterruptDpc); interruptConfig.EvtInterruptEnable = BalloonInterruptEnable; interruptConfig.EvtInterruptDisable = BalloonInterruptDisable; status = WdfInterruptCreate(device, &interruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &devCtx->WdfInterrupt); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfInterruptCreate failed: 0x%08x\n", status); return status; } status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BALLOON, NULL); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreateDeviceInterface failed with status 0x%08x\n", status); return status; } devCtx->bShutDown = FALSE; devCtx->num_pages = 0; devCtx->PageListHead.Next = NULL; ExInitializeNPagedLookasideList( &devCtx->LookAsideList, NULL, NULL, 0, sizeof(PAGE_LIST_ENTRY), BALLOON_MGMT_POOL_TAG, 0 ); devCtx->bListInitialized = TRUE; devCtx->pfns_table = (PPFN_NUMBER) ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE, BALLOON_MGMT_POOL_TAG ); if(devCtx->pfns_table == NULL) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"ExAllocatePoolWithTag failed\n"); status = STATUS_INSUFFICIENT_RESOURCES; return status; } devCtx->MemStats = (PBALLOON_STAT) ExAllocatePoolWithTag( NonPagedPool, sizeof (BALLOON_STAT) * VIRTIO_BALLOON_S_NR, BALLOON_MGMT_POOL_TAG ); if(devCtx->MemStats == NULL) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"ExAllocatePoolWithTag failed\n"); status = STATUS_INSUFFICIENT_RESOURCES; return status; } RtlFillMemory (devCtx->MemStats, sizeof (BALLOON_STAT) * VIRTIO_BALLOON_S_NR, -1); KeInitializeEvent(&devCtx->HostAckEvent, SynchronizationEvent, FALSE ); status = BalloonQueueInitialize(device); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "BalloonQueueInitialize failed with status 0x%08x\n", status); return status; } KeInitializeEvent(&devCtx->WakeUpThread, SynchronizationEvent, FALSE ); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__); return status; }
NTSTATUS OsrFxEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a device object to represent a new instance of the device. All the software resources should be allocated in this callback. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES attributes; NTSTATUS status; WDFDEVICE device; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> OsrFxEvtDeviceAdd routine\n"); // // Initialize the pnpPowerCallbacks structure. Callback events for PNP // and Power are specified here. If you don't supply any callbacks, // the Framework will take appropriate default actions based on whether // DeviceInit is initialized to be an FDO, a PDO or a filter device // object. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // For usb devices, PrepareHardware callback is the to place select the // interface and configure the device. // pnpPowerCallbacks.EvtDevicePrepareHardware = OsrFxEvtDevicePrepareHardware; // // These two callbacks start and stop the WDFUSBPIPE continuous reader // as we go in and out of the D0-working state. // pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = OsrFxEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); OsrFxInitChildList(DeviceInit); // // Now specify the size of device extension where we track per device // context.DeviceInit is completely initialized. So call the framework // to create the device and attach it to the lower stack. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreate failed with Status code %!STATUS!\n", status); return status; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "OsrFxEvtDeviceAdd - ends\n"); return status; }
//----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- VOID HSACEvtIoDeviceControl( __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 output buffer, if an output buffer is available. InputBufferLength - length of the request 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 --*/ { PDEVICE_EXTENSION devExt; size_t length = 0; NTSTATUS status = STATUS_SUCCESS; PVOID pInputBuffer = NULL; PVOID pOutputBuffer = NULL; ULONG a1 = 0,a2 = 0; ULONG readIndex = 0, readNum = 0; UNREFERENCED_PARAMETER( InputBufferLength ); UNREFERENCED_PARAMETER( OutputBufferLength ); // // Get the device extension. // devExt = HSACGetDeviceContext(WdfIoQueueGetDevice( Queue )); #if (DBG != 0) TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "HSACEvtIoDeviceControl InputBufferLength: 0x%x, OutputBufferLength: 0x%x\n", InputBufferLength, OutputBufferLength); #endif // // Handle this request specific code. // switch (IoControlCode) { case IOCTL_GET_REGISTER: { #if (DBG != 0) TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "IOCTL_GET_REGISTER-->require length: 0x%x\n", sizeof(ULONG)); #endif status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } readIndex = *(PULONG)pInputBuffer; readNum = *((PULONG)pInputBuffer + 1); #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "readIndex: %d, readNum: %d\n", readIndex, readNum); #endif if (readNum == 0) { length = 0; break; } //if (readNum > 1) //{ if (readIndex + readNum > (sizeof(HSAC_REGS)/sizeof(unsigned int) )) { readNum = (sizeof(HSAC_REGS)/sizeof(unsigned int) ) - readIndex; } WdfInterruptAcquireLock( devExt->Interrupt ); READ_REGISTER_BUFFER_ULONG(((PULONG) devExt->Regs) + readIndex, (PULONG)pOutputBuffer, readNum); WdfInterruptReleaseLock( devExt->Interrupt ); //} //else //{ // *(PULONG)pOutputBuffer = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + readIndex ); //} length = readNum; break; } case IOCTL_GET_SINGLE_REGISTER: { #if (DBG != 0) TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "IOCTL_GET_REGISTER-->require length: 0x%x\n", sizeof(ULONG)); #endif status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } readIndex = *(PULONG)pInputBuffer; #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "readIndex: %d\n", readIndex); #endif WdfInterruptAcquireLock( devExt->Interrupt ); *(PULONG)pOutputBuffer = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + readIndex ); WdfInterruptReleaseLock( devExt->Interrupt ); length = sizeof(ULONG); break; } case IOCTL_SET_REGISTER: { status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } WdfInterruptAcquireLock( devExt->Interrupt ); WRITE_REGISTER_ULONG( ((PULONG) devExt->Regs) + (*(PULONG)pInputBuffer), *((PULONG)pInputBuffer + 1) ); WdfInterruptReleaseLock( devExt->Interrupt ); // //a1 = *(PULONG)pInputBuffer; // //a2 = *((PULONG)pInputBuffer + 1); // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, // "IOCTL_SET_REGISTER-->offset:0x%x, value:0x%x\n", a1, a2); //#endif // // //a2 = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + (*(PULONG)pInputBuffer) ); // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, // "IOCTL_SET_REGISTER-->offset:0x%x, value:0x%x\n", a1, a2); //#endif length = 0; break; } case IOCTL_GET_SRAM: { #if (DBG != 0) TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "IOCTL_GET_SRAM-->require length: 0x%x\n", sizeof(ULONG)); #endif status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } readIndex = *(PULONG)pInputBuffer; readNum = *((PULONG)pInputBuffer + 1); if (readNum == 0) { length = 0; break; } //if (readNum > 1) //{ if (readIndex + readNum > (devExt->SRAMLength/sizeof(ULONG) )) { readNum = (devExt->SRAMLength/sizeof(ULONG) ) - readIndex; } #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "readIndex: %d, readNum: %d\n", readIndex, readNum); #endif WdfInterruptAcquireLock( devExt->Interrupt ); READ_REGISTER_BUFFER_ULONG(((PULONG) devExt->SRAMBase) + readIndex, (PULONG)pOutputBuffer, readNum); WdfInterruptReleaseLock( devExt->Interrupt ); //} //else //{ // *(PULONG)pOutputBuffer = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + readIndex ); //} length = readNum; break; } case IOCTL_SET_SRAM: { status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } readIndex = *(PULONG)pInputBuffer; readNum = *((PULONG)pInputBuffer + 1); if (readNum == 0) { length = 0; break; } //if (readNum > 1) //{ if (readIndex + readNum > (devExt->SRAMLength/sizeof(ULONG) )) { readNum = (devExt->SRAMLength/sizeof(ULONG) ) - readIndex; } #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "readIndex: %d, readNum: %d\n", readIndex, readNum); #endif WdfInterruptAcquireLock( devExt->Interrupt ); WRITE_REGISTER_BUFFER_ULONG( ((PULONG) devExt->SRAMBase) + readIndex, (PULONG)pInputBuffer + 2, readNum); WdfInterruptReleaseLock( devExt->Interrupt ); // //a1 = *(PULONG)pInputBuffer; // //a2 = *((PULONG)pInputBuffer + 1); // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, // "IOCTL_SET_REGISTER-->offset:0x%x, value:0x%x\n", a1, a2); //#endif // // //a2 = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + (*(PULONG)pInputBuffer) ); // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, // "IOCTL_SET_REGISTER-->offset:0x%x, value:0x%x\n", a1, a2); //#endif length = readNum; break; } case IOCTL_MAP_DMA_BUF_ADDR: { ULONG_PTR address = 0; status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } if (devExt->MapFlag == 1) { HSACUnmapUserAddress(devExt); devExt->MapFlag = 0; } HSACMapUserAddress( devExt ); devExt->MapFlag = 1; #if (CACHE_MODE == MULTI_DISCRETE_CACHE) if (*(PULONG)pInputBuffer == 0) { length = devExt->readCommonBufferNum * sizeof(PVOID); RtlCopyMemory(pOutputBuffer, devExt->pReadUserAddress, length); } else if (*(PULONG)pInputBuffer == 1) { length = devExt->writeCommonBufferNum * sizeof(PVOID); RtlCopyMemory(pOutputBuffer, devExt->pWriteUserAddress, length); } else { status = STATUS_INVALID_DEVICE_REQUEST; } #else if (*(PULONG)pInputBuffer == 0) { address = (ULONG_PTR)devExt->ReadUserAddress0; } else if (*(PULONG)pInputBuffer == 1) { address = (ULONG_PTR)devExt->WriteUserAddress0; } else { status = STATUS_INVALID_DEVICE_REQUEST; } #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "UserAddress: 0x%I64x", address); #endif RtlCopyMemory(pOutputBuffer, &address, sizeof(PVOID)); #endif break; } case IOCTL_UNMAP_DMA_BUF_ADDR: { if (devExt->MapFlag == 1) { HSACUnmapUserAddress(devExt); devExt->MapFlag = 0; } break; } case IOCTL_SET_DMA_PROFILE: { status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } devExt->dmaProfile = (WDF_DMA_PROFILE)(*(PULONG)pInputBuffer); #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "dmaProfile: %d\n", devExt->dmaProfile); #endif length = 0; break; } case IOCTL_DIRECT_DMA_READ: { // ULONG dma1Ctl = 0; // status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); // devExt->ReadSize = *(PULONG)pInputBuffer; // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, // "devExt->ReadSize: %d\n", devExt->ReadSize); //#endif // // WdfInterruptAcquireLock( devExt->Interrupt ); // // WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA1_ADDR32, // devExt->ReadCommonBufferBaseLA.LowPart); // WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA1_ADDR64, // devExt->ReadCommonBufferBaseLA.HighPart ); // // WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA1_SIZE, devExt->ReadSize); // devExt->ReadSize = 0; // // dma1Ctl = DMA_CTRL_START; // //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA1_CTRL, dma1Ctl); // // WdfInterruptReleaseLock( devExt->Interrupt ); break; } case IOCTL_DIRECT_DMA_WRITE: { //ULONG dma0Ctl = 0; //status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); //devExt->WriteSize = *(PULONG)pInputBuffer; //WdfInterruptAcquireLock( devExt->Interrupt ); //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA0_ADDR32, // devExt->WriteCommonBufferBaseLA.LowPart ); //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA0_ADDR64, // devExt->WriteCommonBufferBaseLA.HighPart ); //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA0_SIZE, devExt->WriteSize); //dma0Ctl = DMA_CTRL_START; //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA0_CTRL, dma0Ctl); //WdfInterruptReleaseLock( devExt->Interrupt ); break; } case IOCTL_RESET: // code == 0x801 { status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } //*(PULONG) buffer = 0x0004000A; //status = STATUS_SUCCESS; length = sizeof(ULONG); break; } default: status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation(Request, status, length); }
VOID ProcessExplorerEvtIoStop( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ ULONG ActionFlags ) /*++ Routine Description: This event is invoked for a power-managed queue before the device leaves the working state (D0). Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. ActionFlags - A bitwise OR of one or more WDF_REQUEST_STOP_ACTION_FLAGS-typed flags that identify the reason that the callback function is being called and whether the request is cancelable. Return Value: VOID --*/ { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "%!FUNC! Queue 0x%p, Request 0x%p ActionFlags %d", Queue, Request, ActionFlags); // // In most cases, the EvtIoStop callback function completes, cancels, or postpones // further processing of the I/O request. // // Typically, the driver uses the following rules: // // - If the driver owns the I/O request, it calls WdfRequestUnmarkCancelable // (if the request is cancelable) and either calls WdfRequestStopAcknowledge // with a Requeue value of TRUE, or it calls WdfRequestComplete with a // completion status value of STATUS_SUCCESS or STATUS_CANCELLED. // // Before it can call these methods safely, the driver must make sure that // its implementation of EvtIoStop has exclusive access to the request. // // In order to do that, the driver must synchronize access to the request // to prevent other threads from manipulating the request concurrently. // The synchronization method you choose will depend on your driver's design. // // For example, if the request is held in a shared context, the EvtIoStop callback // might acquire an internal driver lock, take the request from the shared context, // and then release the lock. At this point, the EvtIoStop callback owns the request // and can safely complete or requeue the request. // // - If the driver has forwarded the I/O request to an I/O target, it either calls // WdfRequestCancelSentRequest to attempt to cancel the request, or it postpones // further processing of the request and calls WdfRequestStopAcknowledge with // a Requeue value of FALSE. // // A driver might choose to take no action in EvtIoStop for requests that are // guaranteed to complete in a small amount of time. // // In this case, the framework waits until the specified request is complete // before moving the device (or system) to a lower power state or removing the device. // Potentially, this inaction can prevent a system from entering its hibernation state // or another low system power state. In extreme cases, it can cause the system // to crash with bugcheck code 9F. // return; }
NTSTATUS PVPanicEvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDFDEVICE device; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_FILEOBJECT_CONFIG fileConfig; WDF_OBJECT_ATTRIBUTES attributes; WDF_IO_QUEUE_CONFIG queueConfig; PDEVICE_CONTEXT context; DECLARE_CONST_UNICODE_STRING(dosDeviceName, PVPANIC_DOS_DEVICE_NAME); UNREFERENCED_PARAMETER(Driver); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "--> %!FUNC!"); PAGED_CODE(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = PVPanicEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = PVPanicEvtDeviceReleaseHardware; pnpPowerCallbacks.EvtDeviceD0Entry = PVPanicEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = PVPanicEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, PVPanicEvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed: %!STATUS!", status); return status; } status = WdfDeviceCreateSymbolicLink(device, &dosDeviceName); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed: %!STATUS!", status); return status; } WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoDeviceControl = PVPanicEvtQueueDeviceControl; context = GetDeviceContext(device); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &context->IoctlQueue); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed: %!STATUS!", status); return status; } status = WdfDeviceConfigureRequestDispatching(device, context->IoctlQueue, WdfRequestTypeDeviceControl); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceConfigureRequestDispatching failed: %!STATUS!", status); return status; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "<-- %!FUNC!"); 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; }
NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath ) /*++ Routine Description: DriverEntry initializes the driver and is the first routine called by the system after the driver is loaded. Parameters Description: DriverObject - represents the instance of the function driver that is loaded into memory. DriverEntry must initialize members of DriverObject before it returns to the caller. DriverObject is allocated by the system before the driver is loaded, and it is released by the system after the system unloads the function driver from memory. RegistryPath - represents the driver specific path in the Registry. The function driver can use the path to store driver related data between reboots. The path does not store hardware instance specific data. Return Value: STATUS_SUCCESS if successful, STATUS_UNSUCCESSFUL otherwise. --*/ { WDF_DRIVER_CONFIG config; NTSTATUS status; WDF_OBJECT_ATTRIBUTES attributes; // // Initialize WPP Tracing // WPP_INIT_TRACING(DriverObject, RegistryPath); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "OSRUSBFX2 Driver Sample - Driver Framework Edition.\n"); // // Initiialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, // you can override that by manually setting the EvtDriverUnload in the // config structure. In general xxx_CONFIG_INIT macros are provided to // initialize most commonly used members. // WDF_DRIVER_CONFIG_INIT( &config, OsrFxEvtDeviceAdd ); // // Register a cleanup callback so that we can call WPP_CLEANUP when // the framework driver object is deleted during driver unload. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.EvtCleanupCallback = OsrFxEvtDriverContextCleanup; // // Create a framework driver object to represent our driver. // status = WdfDriverCreate( DriverObject, RegistryPath, &attributes, // Driver Attributes &config, // Driver Config Info WDF_NO_HANDLE // hDriver ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDriverCreate failed with status 0x%x\n", status); // // Cleanup tracing here because DriverContextCleanup will not be called // as we have failed to create WDFDRIVER object itself. // Please note that if your return failure from DriverEntry after the // WDFDRIVER object is created successfully, you don't have to // call WPP cleanup because in those cases DriverContextCleanup // will be executed when the framework deletes the DriverObject. // WPP_CLEANUP(DriverObject); } 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 BthEchoCliRetrieveServerSdpRecord( _In_ PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx, _Out_ PBTH_SDP_STREAM_RESPONSE * ServerSdpRecord ) /*++ Description: Retrive server SDP record. We call this function on every file open to get the PSM Arguments: DevCtx - Client context ServerSdpRecord - SDP record retrieved Return Value: NTSTATUS Status code. --*/ { NTSTATUS status, statusReuse, disconnectStatus; WDF_MEMORY_DESCRIPTOR inMemDesc; WDF_MEMORY_DESCRIPTOR outMemDesc; WDF_REQUEST_REUSE_PARAMS ReuseParams; BTH_SDP_CONNECT connect = {0}; BTH_SDP_DISCONNECT disconnect = {0}; BTH_SDP_SERVICE_ATTRIBUTE_SEARCH_REQUEST requestSdp = {0}; BTH_SDP_STREAM_RESPONSE responseSdp = {0}; ULONG requestSize; PBTH_SDP_STREAM_RESPONSE serverSdpRecord = NULL; WDFREQUEST request; WDF_OBJECT_ATTRIBUTES attributes; PAGED_CODE(); // // Allocate the request we will use for obtaining sdp record // NOTE that we do it for every file open, hence we // // can't use reserve request from the context // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); status = WdfRequestCreate( &attributes, DevCtx->Header.IoTarget, &request ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Failed to allocate request for retriving server sdp record, Status code %!STATUS!\n", status); goto exit; } connect.bthAddress = DevCtx->ServerBthAddress; connect.requestTimeout = SDP_REQUEST_TO_DEFAULT; connect.fSdpConnect = 0; // // Connect to the SDP service. // WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &connect, sizeof(connect) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, &connect, sizeof(connect) ); status = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_CONNECT, &inMemDesc, &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "IOCTL_BTH_SDP_CONNECT failed, Status code %!STATUS!\n", status); goto exit1; } // // Obtain the required size of the SDP record // requestSdp.hConnection = connect.hConnection; requestSdp.uuids[0].u.uuid128 = BTHECHOSAMPLE_SVC_GUID; requestSdp.uuids[0].uuidType = SDP_ST_UUID128; requestSdp.range[0].minAttribute = 0; requestSdp.range[0].maxAttribute = 0xFFFF; WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(request, &ReuseParams); NT_ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &requestSdp, sizeof(requestSdp) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, &responseSdp, sizeof(responseSdp) ); status = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH, &inMemDesc, &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH failed while querying response size, " "status code %!STATUS!\n", status); goto exit2; } // // Allocate the required size for SDP record // status = RtlULongAdd( responseSdp.requiredSize, sizeof(BTH_SDP_STREAM_RESPONSE), &requestSize ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "SDP record size too large, status code %!STATUS!\n", status); goto exit2; } serverSdpRecord = ExAllocatePoolWithTag(NonPagedPoolNx, requestSize, POOLTAG_BTHECHOSAMPLE); if (NULL == serverSdpRecord) { status = STATUS_INSUFFICIENT_RESOURCES; TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "Allocating SDP record failed, returning status code %!STATUS!\n", status); goto exit2; } // // Send request with required size // WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(request, &ReuseParams); NT_ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &requestSdp, sizeof(requestSdp) ); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &outMemDesc, serverSdpRecord, requestSize ); status = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH, &inMemDesc, &outMemDesc, NULL, //sendOptions NULL //bytesReturned ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, "IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH failed, status code %!STATUS!\n", status); ExFreePoolWithTag(serverSdpRecord, POOLTAG_BTHECHOSAMPLE); } else { *ServerSdpRecord = serverSdpRecord; } exit2: // // Disconnect from SDP service. // WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); statusReuse = WdfRequestReuse(request, &ReuseParams); NT_ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); disconnect.hConnection = connect.hConnection; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( &inMemDesc, &disconnect, sizeof(disconnect) ); disconnectStatus = WdfIoTargetSendIoctlSynchronously( DevCtx->Header.IoTarget, request, IOCTL_BTH_SDP_DISCONNECT, &inMemDesc, NULL, //outMemDesc NULL, //sendOptions NULL //bytesReturned ); NT_ASSERT(NT_SUCCESS(disconnectStatus)); //Disconnect should not fail if (!NT_SUCCESS(disconnectStatus)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "IOCTL_BTH_SDP_DISCONNECT failed, Status code %!STATUS!\n", status); } exit1: WdfObjectDelete(request); exit: return status; }
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; }
/** * @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); }