VOID kmdf1394_EvtDeviceSelfManagedIoCleanup ( IN WDFDEVICE Device) /*++ Routine Description: EvtDeviceSelfManagedIoCleanup is called by the Framework when the device is being torn down, either in response to IRP_MN_REMOVE_DEVICE or IRP_MN_SURPRISE_REMOVE_DEVICE. It will be called only once. Its job is to stop all outstanding I/O in the driver that the Framework is not managing. Arguments: Device - Handle to a framework device object. Return Value: None --*/ { PDEVICE_EXTENSION deviceExtension = NULL; PLIST_ENTRY listEntry = NULL; Enter(); deviceExtension = GetDeviceContext(Device); DoTraceLevelMessage(TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "Removing KMDF1394VDEV.SYS.\n"); // // lets free up any crom data structs we've allocated... // WdfSpinLockAcquire (deviceExtension->CromSpinLock); while (!IsListEmpty (&deviceExtension->CromData)) { PCROM_DATA CromData; // // get struct off list // listEntry = RemoveHeadList (&deviceExtension->CromData); CromData = CONTAINING_RECORD (listEntry, CROM_DATA, CromList); // // need to free up everything associated with this allocate... // if (CromData) { if (CromData->Buffer) { ExFreePoolWithTag (CromData->Buffer, POOLTAG_KMDF_VDEV); } if (CromData->pMdl) { IoFreeMdl (CromData->pMdl); } // // we already checked CromData // ExFreePoolWithTag (CromData, POOLTAG_KMDF_VDEV); } } WdfSpinLockRelease (deviceExtension->CromSpinLock); // // lets free up any allocated addresses and deallocate all // memory associated with them... // WdfSpinLockAcquire (deviceExtension->AsyncSpinLock); while (!IsListEmpty (&deviceExtension->AsyncAddressData)) { PASYNC_ADDRESS_DATA AsyncAddressData; // // get struct off list // listEntry = RemoveHeadList (&deviceExtension->AsyncAddressData); AsyncAddressData = CONTAINING_RECORD ( listEntry, ASYNC_ADDRESS_DATA, AsyncAddressList); // // need to free up everything associated with this allocate... // if (AsyncAddressData->pMdl) { IoFreeMdl (AsyncAddressData->pMdl); } if (AsyncAddressData->Buffer) { ExFreePoolWithTag(AsyncAddressData->Buffer, POOLTAG_KMDF_VDEV); } if (AsyncAddressData->AddressRange) { ExFreePoolWithTag(AsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV); } ExFreePoolWithTag(AsyncAddressData, POOLTAG_KMDF_VDEV); } WdfSpinLockRelease(deviceExtension->AsyncSpinLock); // // TODO: Free up any attached isoch buffers when // we get the attach / detach code inserted again. // // // Remove any isoch resource data // WHILE (TRUE) { WdfSpinLockAcquire(deviceExtension->IsochResourceSpinLock); if (!IsListEmpty(&deviceExtension->IsochResourceData)) { PISOCH_RESOURCE_DATA IsochResourceData = NULL; listEntry = RemoveHeadList(&deviceExtension->CromData); IsochResourceData = CONTAINING_RECORD ( listEntry, ISOCH_RESOURCE_DATA, IsochResourceList); WdfSpinLockRelease(deviceExtension->IsochResourceSpinLock); DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "Surprise Removal: IsochResourceData = 0x%p\n", IsochResourceData); if (IsochResourceData) { PIRB pIrb; WDFREQUEST request; NTSTATUS ntStatus; DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "Surprise Removal: Freeing hResource = 0x%p\n", IsochResourceData->hResource); ntStatus = WdfRequestCreate ( WDF_NO_OBJECT_ATTRIBUTES, deviceExtension->StackIoTarget, &request); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Failed to allocate request %!STATUS!\n", ntStatus); } else { pIrb = ExAllocatePoolWithTag( NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!pIrb) { WdfObjectDelete(request); DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Failed to allocate pIrb!\n"); } else { RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES; pIrb->Flags = 0; pIrb->u.IsochFreeResources.hResource = \ IsochResourceData->hResource; ntStatus = kmdf1394_SubmitIrpSynch ( deviceExtension->StackIoTarget, request, pIrb); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "SubmitIrpSync failed = %!STATUS!\n", ntStatus); } ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV); WdfObjectDelete (request); } // else } // else } // if (IsochResourceData) } // if (!IsListEmpty(&deviceExtension->IsochResourceData)) else { WdfSpinLockRelease (deviceExtension->IsochResourceSpinLock); break; } } ExitS(STATUS_SUCCESS); } // kmdf1394_EvtDeviceSelfManagedIoCleanup
VOID OnIoDeviceControl( _In_ WDFQUEUE FxQueue, _In_ WDFREQUEST FxRequest, _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: FxQueue - Handle to the framework queue object that is associated with the I/O request. FxRequest - 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 --*/ { FuncEntry(TRACE_FLAG_SPBAPI); WDFDEVICE device; PDEVICE_CONTEXT pDevice; BOOLEAN fSync = FALSE; NTSTATUS status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); device = WdfIoQueueGetDevice(FxQueue); pDevice = GetDeviceContext(device); ElanPrint( DEBUG_LEVEL_INFO, DBG_IOCTL, "DeviceIoControl request %p received with IOCTL=%lu", FxRequest, IoControlCode); ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, "%s, Queue:0x%p, Request:0x%p\n", DbgHidInternalIoctlString(IoControlCode), FxQueue, FxRequest ); // // Translate the test IOCTL into the appropriate // SPB API method. Open and close are completed // synchronously. // switch (IoControlCode) { case IOCTL_HID_GET_DEVICE_DESCRIPTOR: // // Retrieves the device's HID descriptor. // status = ElanGetHidDescriptor(device, FxRequest); fSync = TRUE; break; case IOCTL_HID_GET_DEVICE_ATTRIBUTES: // //Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure. // status = ElanGetDeviceAttributes(FxRequest); fSync = TRUE; break; case IOCTL_HID_GET_REPORT_DESCRIPTOR: // //Obtains the report descriptor for the HID device. // status = ElanGetReportDescriptor(device, FxRequest); fSync = TRUE; break; case IOCTL_HID_GET_STRING: // // Requests that the HID minidriver retrieve a human-readable string // for either the manufacturer ID, the product ID, or the serial number // from the string descriptor of the device. The minidriver must send // a Get String Descriptor request to the device, in order to retrieve // the string descriptor, then it must extract the string at the // appropriate index from the string descriptor and return it in the // output buffer indicated by the IRP. Before sending the Get String // Descriptor request, the minidriver must retrieve the appropriate // index for the manufacturer ID, the product ID or the serial number // from the device extension of a top level collection associated with // the device. // status = ElanGetString(FxRequest); fSync = TRUE; break; case IOCTL_HID_WRITE_REPORT: case IOCTL_HID_SET_OUTPUT_REPORT: // //Transmits a class driver-supplied report to the device. // status = BOOTTRACKPAD(pDevice); if (!NT_SUCCESS(status)){ ElanPrint(DBG_IOCTL, DEBUG_LEVEL_ERROR, "Error booting Elan device!\n"); } fSync = TRUE; break; case IOCTL_HID_READ_REPORT: case IOCTL_HID_GET_INPUT_REPORT: // // Returns a report from the device into a class driver-supplied buffer. // status = ElanReadReport(pDevice, FxRequest, &fSync); break; case IOCTL_HID_GET_FEATURE: // // returns a feature report associated with a top-level collection // status = ElanGetFeature(pDevice, FxRequest, &fSync); break; case IOCTL_HID_ACTIVATE_DEVICE: // // Makes the device ready for I/O operations. // case IOCTL_HID_DEACTIVATE_DEVICE: // // Causes the device to cease operations and terminate all outstanding // I/O requests. // default: fSync = TRUE; status = STATUS_NOT_SUPPORTED; ElanPrint( DEBUG_LEVEL_INFO, DBG_IOCTL, "Request %p received with unexpected IOCTL=%lu", FxRequest, IoControlCode); } // // Complete the request if necessary. // if (fSync) { ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, "%s completed, Queue:0x%p, Request:0x%p\n", DbgHidInternalIoctlString(IoControlCode), FxQueue, FxRequest ); WdfRequestComplete(FxRequest, status); } else { ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, "%s deferred, Queue:0x%p, Request:0x%p\n", DbgHidInternalIoctlString(IoControlCode), FxQueue, FxRequest ); } FuncExit(TRACE_FLAG_SPBAPI); }
VOID ReadWriteBulkEndPoints( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG Length, IN WDF_REQUEST_TYPE RequestType ) /*++ Routine Description: This callback is invoked when the framework received WdfRequestTypeRead or RP_MJ_WRITE request. This read/write is performed in stages of MAX_TRANSFER_SIZE. Once a stage of transfer is complete, then the request is circulated again, until the requested length of transfer is performed. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. This one represents the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework. Length - Length of the input/output buffer. Return Value: VOID --*/ { size_t totalLength = Length; size_t stageLength = 0; NTSTATUS status; PVOID virtualAddress = 0; PREQUEST_CONTEXT rwContext = NULL; PFILE_CONTEXT fileContext = NULL; WDFUSBPIPE pipe; WDFMEMORY reqMemory; WDFMEMORY_OFFSET offset; WDF_OBJECT_ATTRIBUTES objectAttribs; PDEVICE_CONTEXT deviceContext; kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - begins\n")); // // First validate input parameters. // deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); if (totalLength > deviceContext->MaximumTransferSize) { kJtag_DbgPrint(1, ("Transfer length > circular buffer\n")); status = STATUS_INVALID_PARAMETER; goto Exit; } if ((RequestType != WdfRequestTypeRead) && (RequestType != WdfRequestTypeWrite)) { kJtag_DbgPrint(1, ("RequestType has to be either Read or Write\n")); status = STATUS_INVALID_PARAMETER; goto Exit; } // // Get the pipe associate with this request. // fileContext = GetFileContext(WdfRequestGetFileObject(Request)); pipe = fileContext->Pipe; rwContext = GetRequestContext(Request); if(RequestType == WdfRequestTypeRead) { status = WdfRequestRetrieveOutputBuffer(Request, Length, &virtualAddress, &totalLength); rwContext->Read = TRUE; } else { //Write status = WdfRequestRetrieveInputBuffer(Request, Length, &virtualAddress, &totalLength); rwContext->Read = FALSE; } if(!NT_SUCCESS(status)){ kJtag_DbgPrint(1, ("WdfRequestRetrieveInputBuffer failed\n")); goto Exit; } // // If the totalLength exceeds MAX_TRANSFER_SIZE, we will break // that into multiple transfer of size no more than MAX_TRANSFER_SIZE // in each stage. // if (totalLength > MAX_TRANSFER_SIZE) { stageLength = MAX_TRANSFER_SIZE; } else { stageLength = totalLength; } WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); objectAttribs.ParentObject = Request; status = WdfMemoryCreatePreallocated(&objectAttribs, virtualAddress, totalLength, &reqMemory); if(!NT_SUCCESS(status)){ kJtag_DbgPrint(1, ("WdfMemoryCreatePreallocated failed\n")); goto Exit; } offset.BufferOffset = 0; offset.BufferLength = stageLength; // // The framework format call validates to make sure that you are reading or // writing to the right pipe type, sets the appropriate transfer flags, // creates an URB and initializes the request. // if(RequestType == WdfRequestTypeRead) { kJtag_DbgPrint(3, ("Read operation\n")); status = WdfUsbTargetPipeFormatRequestForRead(pipe, Request, reqMemory, &offset); } else { kJtag_DbgPrint(3, ("Write operation\n")); status = WdfUsbTargetPipeFormatRequestForWrite(pipe, Request, reqMemory, &offset); } if (!NT_SUCCESS(status)) { kJtag_DbgPrint(1, ("WdfUsbTargetPipeFormatRequest failed 0x%x\n", status)); goto Exit; } WdfRequestSetCompletionRoutine( Request, ReadWriteCompletion, NULL); // // set REQUEST_CONTEXT parameters. // rwContext->Length = totalLength - stageLength; rwContext->Numxfer = 0; // // Send the request asynchronously. // if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) { kJtag_DbgPrint(1, ("WdfRequestSend failed\n")); status = WdfRequestGetStatus(Request); goto Exit; } Exit: if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); } kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - ends\n")); return; }
// 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 and selecting descriptors. NTSTATUS HidFx2EvtDevicePrepareHardware( _In_ WDFDEVICE hDevice, _In_ WDFCMRESLIST hResourceList, _In_ WDFCMRESLIST hResourceListTranslated ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION pDevContext = NULL; WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; WDF_OBJECT_ATTRIBUTES attributes; PUSB_DEVICE_DESCRIPTOR pUsbDeviceDescriptor = NULL; UNREFERENCED_PARAMETER(hResourceList); UNREFERENCED_PARAMETER(hResourceListTranslated); PAGED_CODE (); TraceVerbose(DBG_INIT, "(%!FUNC!) Enter\n"); pDevContext = GetDeviceContext(hDevice); // Create a WDFUSBDEVICE object. WdfUsbTargetDeviceCreate obtains the USB device descriptor and the first USB configuration //descriptor from the device and stores them. It also creates a framework USB interface object for each interface in the device's first configuration. // // The parent of each USB device object is the driver's framework driver object. The driver cannot change this parent, and the ParentObject // member or the WDF_OBJECT_ATTRIBUTES structure must be NULL. // // We only create device the first time 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 (pDevContext->hUsbDevice == NULL) { status = WdfUsbTargetDeviceCreate(hDevice, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->hUsbDevice); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceCreate failed %!STATUS!\n", status); return status; } } // Select a device configuration by using a WDF_USB_DEVICE_SELECT_CONFIG_PARAMS WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams); status = WdfUsbTargetDeviceSelectConfig(pDevContext->hUsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n", status); return status; } pDevContext->hUsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; // Get the device descriptor and store it in device context WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hDevice; status = WdfMemoryCreate(&attributes, NonPagedPool, 0, sizeof(USB_DEVICE_DESCRIPTOR), &pDevContext->hDeviceDescriptor, &pUsbDeviceDescriptor); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfMemoryCreate for Device Descriptor failed %!STATUS!\n", status); return status; } WdfUsbTargetDeviceGetDeviceDescriptor(pDevContext->hUsbDevice, pUsbDeviceDescriptor); // Get the Interrupt pipe. There are other endpoints but we are only interested in interrupt endpoint since our HID data comes from this pDevContext->hInterruptPipe = WdfUsbInterfaceGetConfiguredPipe(pDevContext->hUsbInterface, INTERRUPT_ENDPOINT_INDEX, NULL); if (NULL == pDevContext->hInterruptPipe) { TraceErr(DBG_PNP, "(%!FUNC!) Failed to get interrupt pipe info\n"); status = STATUS_INVALID_DEVICE_STATE; return status; } // Tell the framework that it's okay to read less than MaximumPacketSize WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDevContext->hInterruptPipe); //configure continuous reader status = HidFx2ConfigContReaderForInterruptEndPoint(pDevContext); TraceVerbose(DBG_INIT, "(%!FUNC!) Exit, Status: %!STATUS!\n", status); return status; }
/****************************************************************************** WDF_DEVICE_SEFL_MANAGED_IO_CLEANUP (Only the CromData cleanup part of it) ******************************************************************************/ VOID t1394_EvtDeviceSelfManagedIoCleanup( /*IN*/ WDFDEVICE Device ) /*++ Routine Description: EvtDeviceSelfManagedIoCleanup is called by the Framework when the device is being torn down, either in response to IRP_MN_REMOVE_DEVICE or IRP_MN_SURPRISE_REMOVE_DEVICE. It will be called only once. Its job is to stop all outstanding I/O in the driver that the Framework is not managing. Arguments: Device - Handle to a framework device object. Return Value: None --*/ { PDEVICE_EXTENSION deviceExtension; PLIST_ENTRY listEntry; //ENTER("t1394_PnpRemoveDevice"); deviceExtension = GetDeviceContext(Device); // TRACE(TL_WARNING, ("Removing 1394VDEV.SYS.\n")); // lets free up any crom data structs we've allocated... WdfSpinLockAcquire(deviceExtension->CromSpinLock); while (!IsListEmpty(&deviceExtension->CromData)) { PCROM_DATA CromData; // get struct off list listEntry = RemoveHeadList(&deviceExtension->CromData); CromData = CONTAINING_RECORD(listEntry, CROM_DATA, CromList); // need to free up everything associated with this allocate... if (CromData) { if (CromData->Buffer) { ExFreePool(CromData->Buffer); } if (CromData->pMdl) { IoFreeMdl(CromData->pMdl); } // we already checked CromData ExFreePool(CromData); } } WdfSpinLockRelease(deviceExtension->CromSpinLock); /* // lets free up any allocated addresses and deallocate all */ /* // memory associated with them... */ /* WdfSpinLockAcquire(deviceExtension->AsyncSpinLock); */ /* while (!IsListEmpty(&deviceExtension->AsyncAddressData)) { */ /* PASYNC_ADDRESS_DATA AsyncAddressData; */ /* // get struct off list */ /* listEntry = RemoveHeadList(&deviceExtension->AsyncAddressData); */ /* AsyncAddressData = CONTAINING_RECORD(listEntry, ASYNC_ADDRESS_DATA, */ /* AsyncAddressList); */ /* // need to free up everything associated with this allocate... */ /* if (AsyncAddressData->pMdl) */ /* IoFreeMdl(AsyncAddressData->pMdl); */ /* if (AsyncAddressData->Buffer) */ /* ExFreePool(AsyncAddressData->Buffer); */ /* if (AsyncAddressData->AddressRange) */ /* ExFreePool(AsyncAddressData->AddressRange); */ /* if (AsyncAddressData) */ /* ExFreePool(AsyncAddressData); */ /* } */ /* WdfSpinLockRelease(deviceExtension->AsyncSpinLock); */ /* // */ /* // Free up any attached isoch buffers */ /* // Note: There are known bugs in this code path */ /* // */ /* WHILE (TRUE) { */ /* WdfSpinLockAcquire(deviceExtension->IsochSpinLock); */ /* if (!IsListEmpty(&deviceExtension->IsochDetachData)) { */ /* PISOCH_DETACH_DATA IsochDetachData; */ /* IsochDetachData = (PISOCH_DETACH_DATA) */ /* RemoveHeadList(&deviceExtension->IsochDetachData); */ /* // TRACE(TL_TRACE, ("Surprise Removal: IsochDetachData = 0x%x\n", */ /* IsochDetachData)); */ /* KeCancelTimer(&IsochDetachData->Timer); */ /* WdfSpinLockRelease(deviceExtension->IsochSpinLock); */ /* // TRACE(TL_TRACE, ("Surprise Removal: IsochDetachData->Irp = 0x%x\n", */ /* IsochDetachData->Request)); */ /* // need to save the status of the attach */ /* // we'll clean up in the same spot for success's and timeout's */ /* IsochDetachData->AttachStatus = STATUS_SUCCESS; */ /* // detach no matter what... */ /* IsochDetachData->bDetach = TRUE; */ /* t1394_IsochCleanup(IsochDetachData); */ /* } */ /* else { */ /* WdfSpinLockRelease(deviceExtension->IsochSpinLock); */ /* break; */ /* } */ /* } */ /* // */ /* // Remove any isoch resource data */ /* // */ /* WHILE (TRUE) { */ /* WdfSpinLockAcquire(deviceExtension->IsochResourceSpinLock); */ /* if (!IsListEmpty(&deviceExtension->IsochResourceData)) { */ /* PISOCH_RESOURCE_DATA IsochResourceData = NULL; */ /* listEntry = RemoveHeadList(&deviceExtension->CromData); */ /* IsochResourceData = CONTAINING_RECORD(listEntry, */ /* ISOCH_RESOURCE_DATA, */ /* IsochResourceList); */ /* WdfSpinLockRelease(deviceExtension->IsochResourceSpinLock); */ /* // TRACE(TL_TRACE, ("Surprise Removal: IsochResourceData = 0x%x\n", */ /* IsochResourceData)); */ /* if (IsochResourceData) { */ /* PIRB pIrb; */ /* WDFREQUEST request; */ /* NTSTATUS status; */ /* // TRACE(TL_TRACE, ("Surprise Removal: Freeing hResource = 0x%x\n", */ /* IsochResourceData->hResource)); */ /* status = WdfRequestCreate( */ /* WDF_NO_OBJECT_ATTRIBUTES, */ /* deviceExtension->StackIoTarget, */ /* &request); */ /* if (!NT_SUCCESS(status)) { */ /* // TRACE(TL_ERROR, ("Failed to allocate request %x\n", status)); */ /* } */ /* else { */ /* pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_1394); */ /* if (!pIrb) { */ /* WdfObjectDelete(request); */ /* // TRACE(TL_ERROR, ("Failed to allocate pIrb!\n")); */ /* } */ /* else { */ /* RtlZeroMemory (pIrb, sizeof (IRB)); */ /* pIrb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES; */ /* pIrb->Flags = 0; */ /* pIrb->u.IsochFreeResources.hResource = IsochResourceData->hResource; */ /* status = t1394_SubmitIrpSynch(deviceExtension->StackIoTarget, request, pIrb); */ /* if (!NT_SUCCESS(status)) { */ /* // TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", status)); */ /* } */ /* ExFreePool(pIrb); */ /* WdfObjectDelete(request); */ /* } */ /* } */ /* } */ /* } */ /* else { */ /* WdfSpinLockRelease(deviceExtension->IsochResourceSpinLock); */ /* break; */ /* } */ /* } */ //EXIT("t1394_PnpRemoveDevice", STATUS_SUCCESS); } // t1394_PnpRemoveDevice
//HidFx2EvtDeviceAdd is called by the framework in response to AddDevicecall from the PnP manager. //We create and initialize a WDF device object to represent a new instance of device. // NTSTATUS HidFx2EvtDeviceAdd(_In_ WDFDRIVER hDriver, _Inout_ PWDFDEVICE_INIT pDeviceInit) { NTSTATUS status = STATUS_SUCCESS; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES attributes; WDFDEVICE hDevice; PDEVICE_EXTENSION pDevContext = NULL; WDFQUEUE hQueue; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_TIMER_CONFIG timerConfig; WDFTIMER hTimer; UNREFERENCED_PARAMETER(hDriver); PAGED_CODE(); TraceVerbose(DBG_PNP, "(%!FUNC!) Enter\n"); // Tell framework this is a filter driver. WdfFdoInitSetFilter(pDeviceInit); // Initialize pnp-power callbacks, attributes and a context area for the 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 = HidFx2EvtDevicePrepareHardware; // These two callbacks start and stop the wdfusb pipe continuous reader as we go in and out of the D0-working state. pnpPowerCallbacks.EvtDeviceD0Entry = HidFx2EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = HidFx2EvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); // Create a framework device object.This call will in turn create a WDM device object, attach to the lower stack. status = WdfDeviceCreate(&pDeviceInit, &attributes, &hDevice); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfDeviceCreate failed with status code %!STATUS!\n", status); return status; } pDevContext = GetDeviceContext(hDevice); WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoInternalDeviceControl = HidFx2EvtInternalDeviceControl; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &hQueue); if (!NT_SUCCESS (status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfIoQueueCreate failed 0x%x\n", status); return status; } // Register a manual I/O queue for handling Interrupt Message Read Requests. WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); // This queue is used for requests that dont directly access the device. // The requests in this queue are serviced only when the device is in a fully powered state and sends an interrupt. queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->hInterruptMsgQueue); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfIoQueueCreate failed %!STATUS!\n", status); return status; } // Create a timer to handle debouncing of switchpack WDF_TIMER_CONFIG_INIT(&timerConfig, HidFx2EvtTimerFunction); timerConfig.AutomaticSerialization = FALSE; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hDevice; status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfTimerCreate failed status:%!STATUS!\n", status); return status; } pDevContext->hDebounceTimer = hTimer; TraceVerbose(DBG_PNP, "(%!FUNC!) Exit\n"); return status; }
NTSTATUS HidFx2EvtDevicePrepareHardware( 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 and selecting descriptors. Arguments: Device - handle to a device ResourceList - A handle to a framework resource-list object that identifies the raw hardware resourcest ResourceListTranslated - A handle to a framework resource-list object that identifies the translated hardware resources Return Value: NT status value --*/ { NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION devContext = NULL; WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; WDF_OBJECT_ATTRIBUTES attributes; PUSB_DEVICE_DESCRIPTOR usbDeviceDescriptor = NULL; UNREFERENCED_PARAMETER(ResourceList); UNREFERENCED_PARAMETER(ResourceListTranslated); PAGED_CODE (); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "HidFx2EvtDevicePrepareHardware Enter\n"); devContext = GetDeviceContext(Device); // // Create a WDFUSBDEVICE object. WdfUsbTargetDeviceCreate obtains the // USB device descriptor and the first USB configuration descriptor from // the device and stores them. It also creates a framework USB interface // object for each interface in the device's first configuration. // // The parent of each USB device object is the driver's framework driver // object. The driver cannot change this parent, and the ParentObject // member or the WDF_OBJECT_ATTRIBUTES structure must be NULL. // // We only create device the first time 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 (devContext->UsbDevice == NULL) { status = WdfUsbTargetDeviceCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &devContext->UsbDevice); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceCreate failed 0x%x\n", status); return status; } // // TODO: If you are fetching configuration descriptor from device for // selecting a configuration or to parse other descriptors, call // HidFx2ValidateConfigurationDescriptor // to do basic validation on the descriptors before you access them. // } // // Select a device configuration by using a // WDF_USB_DEVICE_SELECT_CONFIG_PARAMS structure to specify USB // descriptors, a URB, or handles to framework USB interface objects. // WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams); status = WdfUsbTargetDeviceSelectConfig(devContext->UsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n", status); return status; } devContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; // // Get the device descriptor and store it in device context // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = Device; status = WdfMemoryCreate( &attributes, NonPagedPoolNx, 0, sizeof(USB_DEVICE_DESCRIPTOR), &devContext->DeviceDescriptor, &usbDeviceDescriptor ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfMemoryCreate for Device Descriptor failed %!STATUS!\n", status); return status; } WdfUsbTargetDeviceGetDeviceDescriptor( devContext->UsbDevice, usbDeviceDescriptor ); // // Get the Interrupt pipe. There are other endpoints but we are only // interested in interrupt endpoint since our HID data comes from that // endpoint. Another way to get the interrupt endpoint is by enumerating // through all the pipes in a loop and looking for pipe of Interrupt type. // devContext->InterruptPipe = WdfUsbInterfaceGetConfiguredPipe( devContext->UsbInterface, INTERRUPT_ENDPOINT_INDEX, NULL);// pipeInfo if (NULL == devContext->InterruptPipe) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Failed to get interrupt pipe info\n"); status = STATUS_INVALID_DEVICE_STATE; return status; } // // Tell the framework that it's okay to read less than // MaximumPacketSize // WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(devContext->InterruptPipe); // //configure continuous reader // status = HidFx2ConfigContReaderForInterruptEndPoint(devContext); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "HidFx2EvtDevicePrepareHardware Exit, Status:0x%x\n", status); return status; }
NTSTATUS t1394_SetLocalHostProperties( /*IN*/ WDFDEVICE Device, /*IN*/ WDFREQUEST Request, /*IN*/ ULONG nLevel, /*IN*/ PVOID Information ) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device); PIRB pIrb = NULL; PSET_LOCAL_HOST_PROPS3 R0_SetLocalHostProps3 = NULL; PCROM_DATA CromData = NULL; PLIST_ENTRY listHead, thisEntry; //ENTER("t1394_SetLocalHostProperties"); // allocate irb pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_1394); if (!pIrb) { // TRACE(TL_ERROR, ("Failed to allocate pIrb!\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto Exit_SetLocalHostProperties; } // if RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_SET_LOCAL_HOST_PROPERTIES; pIrb->Flags = 0; // SI: writes to union broken // pIrb->u.SetLocalHostProperties.nLevel = nLevel; // TRACE(TL_TRACE, ("nLevel = 0x%x\n", nLevel)); // TRACE(TL_TRACE, ("Information = 0x%x\n", Information)); if (nLevel == SET_LOCAL_HOST_PROPERTIES_GAP_COUNT) { PSET_LOCAL_HOST_PROPS2 SetLocalHostProps2; SetLocalHostProps2 = (PSET_LOCAL_HOST_PROPS2)Information; // TRACE(TL_TRACE, ("GapCountLowerBound = 0x%x\n", SetLocalHostProps2->GapCountLowerBound)); // SI: writes to union broken // pIrb->u.SetLocalHostProperties.Information = Information; } else if (nLevel == SET_LOCAL_HOST_PROPERTIES_MODIFY_CROM) { PSET_LOCAL_HOST_PROPS3 SetLocalHostProps3; SetLocalHostProps3 = (PSET_LOCAL_HOST_PROPS3)Information; // TRACE(TL_TRACE, ("fulFlags = 0x%x\n", SetLocalHostProps3->fulFlags)); // TRACE(TL_TRACE, ("hCromData = 0x%x\n", SetLocalHostProps3->hCromData)); // TRACE(TL_TRACE, ("nLength = 0x%x\n", SetLocalHostProps3->nLength)); // since we need to create a mdl, we'll create another setlocalhostprops3 // and pass that down to the bus driver R0_SetLocalHostProps3 = ExAllocatePoolWithTag(NonPagedPool, sizeof(SET_LOCAL_HOST_PROPS3), POOLTAG_1394); if (!R0_SetLocalHostProps3) { // TRACE(TL_ERROR, ("Failed to allocate R0_SetLocalHostProps3!\n")); if (pIrb) ExFreePool(pIrb); ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto Exit_SetLocalHostProperties; } // if // TRACE(TL_TRACE, ("R0_SetLocalHostProps3 = 0x%x\n", R0_SetLocalHostProps3)); // copy over the contents... RtlCopyMemory( R0_SetLocalHostProps3, SetLocalHostProps3, sizeof(SET_LOCAL_HOST_PROPS3) ); // branch, depending if we are adding or removing if (R0_SetLocalHostProps3->fulFlags == SLHP_FLAG_ADD_CROM_DATA) { // we are adding an entry. let's get our crom data struct... CromData = ExAllocatePoolWithTag(NonPagedPool, sizeof(CROM_DATA), POOLTAG_1394); if (!CromData) { // TRACE(TL_ERROR, ("Failed to allocate CromData!\n")); if (pIrb) ExFreePool(pIrb); if (R0_SetLocalHostProps3) ExFreePool(R0_SetLocalHostProps3); ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto Exit_SetLocalHostProperties; } // let's allocate our buffer... CromData->Buffer = ExAllocatePoolWithTag(NonPagedPool, R0_SetLocalHostProps3->nLength, POOLTAG_1394); // TRACE(TL_TRACE, ("CromData->Buffer = 0x%x\n", CromData->Buffer)); if (!CromData->Buffer) { // TRACE(TL_ERROR, ("Failed to allocate CromData->Buffer!\n")); if (pIrb) ExFreePool(pIrb); if (R0_SetLocalHostProps3) ExFreePool(R0_SetLocalHostProps3); if (CromData) ExFreePool(CromData); ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto Exit_SetLocalHostProperties; } // copy over contents (mdl == ring 3 buffer) RtlCopyMemory(CromData->Buffer, &SetLocalHostProps3->Mdl, SetLocalHostProps3->nLength); R0_SetLocalHostProps3->Mdl = IoAllocateMdl (CromData->Buffer, R0_SetLocalHostProps3->nLength, FALSE, FALSE, NULL); if(R0_SetLocalHostProps3->Mdl == NULL) { // TRACE(TL_ERROR, ("Failed to allocate mdl for CromData->Buffer!\n")); if (pIrb) ExFreePool(pIrb); if (R0_SetLocalHostProps3) ExFreePool(R0_SetLocalHostProps3); if (CromData) ExFreePool(CromData); ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto Exit_SetLocalHostProperties; } MmBuildMdlForNonPagedPool(R0_SetLocalHostProps3->Mdl); // TRACE(TL_TRACE, ("Mdl = 0x%x\n", R0_SetLocalHostProps3->Mdl)); } else if (SetLocalHostProps3->fulFlags == SLHP_FLAG_REMOVE_CROM_DATA) { // TRACE(TL_TRACE, ("hCromData = 0x%x\n", R0_SetLocalHostProps3->hCromData)); } // SI: writes to union broken // pIrb->u.SetLocalHostProperties.Information = (PVOID)R0_SetLocalHostProps3; } ntStatus = t1394_SubmitIrpSynch(deviceExtension->StackIoTarget, Request, pIrb); if (!NT_SUCCESS(ntStatus)) { if (nLevel == SET_LOCAL_HOST_PROPERTIES_MODIFY_CROM) { if (R0_SetLocalHostProps3 && R0_SetLocalHostProps3->fulFlags == SLHP_FLAG_ADD_CROM_DATA) { if (R0_SetLocalHostProps3->Mdl) IoFreeMdl(R0_SetLocalHostProps3->Mdl); if (CromData) { if (CromData->Buffer) { ExFreePool(CromData->Buffer); } ExFreePool(CromData); } } if (R0_SetLocalHostProps3) ExFreePool(R0_SetLocalHostProps3); } // TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", ntStatus)); } else { if (nLevel == SET_LOCAL_HOST_PROPERTIES_MODIFY_CROM) { // // branch, depending if we are adding or removing // if (R0_SetLocalHostProps3 && R0_SetLocalHostProps3->fulFlags == SLHP_FLAG_ADD_CROM_DATA) { PSET_LOCAL_HOST_PROPS3 SetLocalHostProps3; SetLocalHostProps3 = Information; SetLocalHostProps3->hCromData = R0_SetLocalHostProps3->hCromData; // TRACE(TL_TRACE, ("hCromData = 0x%x\n", SetLocalHostProps3->hCromData)); if (CromData) { CromData->hCromData = SetLocalHostProps3->hCromData; CromData->pMdl = R0_SetLocalHostProps3->Mdl; // need to add to our list... WdfSpinLockAcquire(deviceExtension->CromSpinLock); InsertHeadList(&deviceExtension->CromData, &CromData->CromList); WdfSpinLockRelease(deviceExtension->CromSpinLock); } } else if (R0_SetLocalHostProps3 && R0_SetLocalHostProps3->fulFlags == SLHP_FLAG_REMOVE_CROM_DATA) { // have to find our struct... WdfSpinLockAcquire(deviceExtension->CromSpinLock); listHead = &deviceExtension->CromData; for(thisEntry = listHead->Flink; thisEntry != listHead; CromData = NULL, thisEntry = thisEntry->Flink) { CromData = CONTAINING_RECORD(thisEntry, CROM_DATA, CromList); if (CromData->hCromData == R0_SetLocalHostProps3->hCromData) { RemoveEntryList(&CromData->CromList); break; } } WdfSpinLockRelease(deviceExtension->CromSpinLock); if (CromData) { if (CromData->Buffer) ExFreePool(CromData->Buffer); if (CromData->pMdl) IoFreeMdl(CromData->pMdl); ExFreePool(CromData); } } if (R0_SetLocalHostProps3) ExFreePool(R0_SetLocalHostProps3); } } Exit_SetLocalHostProperties: if (pIrb) { ExFreePool(pIrb); } //EXIT("t1394_SetLocalHostProperties", ntStatus); return(ntStatus); } // t1394_SetLocalHostProperties
/*++ Routine Description: This callback is invoked when the framework received WdfRequestTypeRead or WdfRequestTypeWrite request. This read/write is performed in stages of MAX_TRANSFER_SIZE. Once a stage of transfer is complete, then the request is circulated again, until the requested length of transfer is performed. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. This one represents the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework. Length - Length of the input/output buffer. Return Value: VOID --*/ VOID ReadWriteBulkEndPoints(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG Length, IN WDF_REQUEST_TYPE RequestType) { PMDL newMdl = NULL; PMDL requestMdl = NULL; PURB urb = NULL; WDFMEMORY urbMemory; ULONG totalLength = Length; ULONG stageLength = 0; ULONG urbFlags = 0; NTSTATUS status; ULONG_PTR virtualAddress = 0; PREQUEST_CONTEXT rwContext = NULL; PFILE_CONTEXT fileContext = NULL; WDFUSBPIPE pipe; WDF_USB_PIPE_INFORMATION pipeInfo; WDF_OBJECT_ATTRIBUTES objectAttribs; USBD_PIPE_HANDLE usbdPipeHandle; PDEVICE_CONTEXT deviceContext; WDF_REQUEST_SEND_OPTIONS sendOptions; PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - begins\n")); // First validate input parameters. deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); if (totalLength > deviceContext->MaximumTransferSize) { PSDrv_DbgPrint(1, ("Transfer length (%d) is bigger then MaximumTransferSize (%d)!\n", totalLength, deviceContext->MaximumTransferSize)); status = STATUS_INVALID_PARAMETER; goto Exit; } if ((RequestType != WdfRequestTypeRead) && (RequestType != WdfRequestTypeWrite)) { PSDrv_DbgPrint(1, ("RequestType has to be either Read or Write! (RequestType = %d)\n", RequestType)); status = STATUS_INVALID_PARAMETER; goto Exit; } // Get the pipe associate with this request. fileContext = GetFileContext(WdfRequestGetFileObject(Request)); pipe = fileContext->Pipe; WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); WdfUsbTargetPipeGetInformation(pipe, &pipeInfo); if((WdfUsbPipeTypeBulk != pipeInfo.PipeType) && (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType)) { PSDrv_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt! (PipeType = %d)\n", pipeInfo.PipeType)); status = STATUS_INVALID_DEVICE_REQUEST; goto Exit; } rwContext = GetRequestContext(Request); if(RequestType == WdfRequestTypeRead) { status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed! (Status = %x)\n", status)); goto Exit; } urbFlags |= USBD_TRANSFER_DIRECTION_IN; rwContext->Read = TRUE; PSDrv_DbgPrint(3, ("This is a read operation...\n")); } else { status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed! (Status = %x)\n", status)); goto Exit; } urbFlags |= USBD_TRANSFER_DIRECTION_OUT; rwContext->Read = FALSE; PSDrv_DbgPrint(3, ("This is a write operation...\n")); } urbFlags |= USBD_SHORT_TRANSFER_OK; virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl); // The transfer request is for totalLength. We can perform a max of MAX_TRANSFER_SIZE in each stage. if (totalLength > MAX_TRANSFER_SIZE) { stageLength = MAX_TRANSFER_SIZE; } else { stageLength = totalLength; } newMdl = IoAllocateMdl((PVOID)virtualAddress, totalLength, FALSE, FALSE, NULL); if (newMdl == NULL) { PSDrv_DbgPrint(1, ("IoAllocateMdl failed! (newMdl is NULL)\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } // Map the portion of user-buffer described by an mdl to another mdl IoBuildPartialMdl(requestMdl, newMdl, (PVOID)virtualAddress, stageLength); WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); objectAttribs.ParentObject = Request; status = WdfMemoryCreate(&objectAttribs, NonPagedPool, POOL_TAG, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), &urbMemory, (PVOID*)&urb); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfMemoryCreate for urbMemory failed! (Status = %x)\n", status)); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe); UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), usbdPipeHandle, NULL, newMdl, stageLength, urbFlags, NULL); status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfUsbTargetPipeFormatRequestForUrb failed! (Status = %x)\n", status)); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } WdfRequestSetCompletionRoutine(Request, ReadWriteCompletion, NULL); // Set REQUEST_CONTEXT parameters. rwContext->UrbMemory = urbMemory; rwContext->Mdl = newMdl; rwContext->Length = totalLength - stageLength; rwContext->Numxfer = 0; rwContext->VirtualAddress = virtualAddress + stageLength; // Set the timeout if (fileContext->nTimeOut != 0) { WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_MS(fileContext->nTimeOut)); PSDrv_DbgPrint(3, ("Pipe timeout is set to: %d\n", fileContext->nTimeOut)); if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), &sendOptions)) { status = WdfRequestGetStatus(Request); ASSERT(!NT_SUCCESS(status)); } } else { if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) { status = WdfRequestGetStatus(Request); ASSERT(!NT_SUCCESS(status)); } } Exit: if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); if (newMdl != NULL) { IoFreeMdl(newMdl); } } PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - ends\n")); return; }
VOID HidFx2CompleteReadReport( WDFDEVICE Device ) /*++ Routine Description This method handles the completion of the pended request for the IOCTL_HID_READ_REPORT Arguments: Device - Handle to a framework device. Return Value: None. --*/ { NTSTATUS status = STATUS_SUCCESS; WDFREQUEST request; PDEVICE_EXTENSION pDevContext = NULL; size_t bytesReturned = 0; #ifndef USE_ALTERNATE_HID_REPORT_DESCRIPTOR UCHAR toggledSwitch = 0; #endif // USE_ALTERNATE_HID_REPORT_DESCRIPTOR ULONG bytesToCopy = 0; PHIDFX2_INPUT_REPORT inputReport = NULL; pDevContext = GetDeviceContext(Device); // // Check if there are any pending requests in the Interrupt Message Queue. // If a request is found then complete the pending request. // status = WdfIoQueueRetrieveNextRequest(pDevContext->InterruptMsgQueue, &request); if (NT_SUCCESS(status)) { // // IOCTL_HID_READ_REPORT is METHOD_NEITHER so WdfRequestRetrieveOutputBuffer // will correctly retrieve buffer from Irp->UserBuffer. Remember that // HIDCLASS provides the buffer in the Irp->UserBuffer field // irrespective of the ioctl buffer type. However, framework is very // strict about type checking. You cannot get Irp->UserBuffer by using // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER // internal ioctl. // bytesToCopy = sizeof(HIDFX2_INPUT_REPORT); status = WdfRequestRetrieveOutputBuffer(request, bytesToCopy, &inputReport, &bytesReturned);// BufferLength if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfRequestRetrieveOutputBuffer failed with status: 0x%x\n", status); } else { #ifndef USE_ALTERNATE_HID_REPORT_DESCRIPTOR // // Map switch pack state. The lower 7 bits of switch pack // state are mapped to usages in consumer control collection // while the highest one bit is mapped to sleep usage in system // control collection // toggledSwitch = pDevContext->LatestToggledSwitch; if (toggledSwitch & CONSUMER_CONTROL_BUTTONS_BIT_MASK) { // //these are consumer control buttons // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "Consumer control SwitchState: 0x%x\n", toggledSwitch); inputReport->ReportId = CONSUMER_CONTROL_REPORT_ID; inputReport->SwitchStateAsByte = toggledSwitch; bytesReturned = bytesToCopy; } else if (toggledSwitch & SYSTEM_CONTROL_BUTTONS_BIT_MASK) { // // these are system control buttons // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "System Control SwitchState: 0x%x\n", toggledSwitch); inputReport->ReportId = SYSTEM_CONTROL_REPORT_ID; inputReport->SwitchStateAsByte = toggledSwitch; bytesReturned = bytesToCopy; } else { // // We can't be here since we already rejected the switch // state with no swicthes turned on // ASSERT(FALSE); } #else // // Using vendor collection reports instead of HID collections that integrate // into consumer and system control // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "Vendor SwitchState: 0x%x\n", pDevContext->CurrentSwitchState); inputReport->ReportId = DIP_SWITCHES_REPORT_ID; inputReport->SwitchStateAsByte = pDevContext->CurrentSwitchState; bytesReturned = bytesToCopy; #endif // USE_ALTERNATE_HID_REPORT_DESCRIPTOR } WdfRequestCompleteWithInformation(request, status, bytesReturned); } else if (status != STATUS_NO_MORE_ENTRIES) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfIoQueueRetrieveNextRequest status %08x\n", status); } return; }
VOID OsrFxEvtIoRead( __in WDFQUEUE Queue, __in WDFREQUEST Request, __in size_t Length ) /*++ Routine Description: Called by the framework when it receives Read or Write requests. Arguments: Queue - Default queue handle Request - Handle to the read/write request Lenght - Length of the data buffer associated with the request. The default property of the queue is to not dispatch zero lenght read & write requests to the driver and complete is with status success. So we will never get a zero length request. Return Value: --*/ { WDFUSBPIPE pipe; NTSTATUS status; WDFMEMORY reqMemory; PDEVICE_CONTEXT pDeviceContext; GUID activity = RequestToActivityId(Request); UNREFERENCED_PARAMETER(Queue); // // Log read start event, using request as activity id. // EventWriteReadStart(&activity, WdfIoQueueGetDevice(Queue), (ULONG)Length); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "-->OsrFxEvtIoRead\n"); // // First validate input parameters. // if (Length > TEST_BOARD_TRANSFER_BUFFER_SIZE) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Transfer exceeds %d\n", TEST_BOARD_TRANSFER_BUFFER_SIZE); status = STATUS_INVALID_PARAMETER; goto Exit; } pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); pipe = pDeviceContext->BulkReadPipe; status = WdfRequestRetrieveOutputMemory(Request, &reqMemory); if(!NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestRetrieveOutputMemory failed %!STATUS!\n", status); goto Exit; } // // The format call validates to make sure that you are reading or // writing to the right pipe type, sets the appropriate transfer flags, // creates an URB and initializes the request. // status = WdfUsbTargetPipeFormatRequestForRead(pipe, Request, reqMemory, NULL // Offsets ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfUsbTargetPipeFormatRequestForRead failed 0x%x\n", status); goto Exit; } WdfRequestSetCompletionRoutine( Request, EvtRequestReadCompletionRoutine, pipe); // // Send the request asynchronously. // if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) { // // Framework couldn't send the request for some reason. // TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestSend failed\n"); status = WdfRequestGetStatus(Request); goto Exit; } Exit: if (!NT_SUCCESS(status)) { // // log event read failed // EventWriteReadFail(&activity, WdfIoQueueGetDevice(Queue), status); WdfRequestCompleteWithInformation(Request, status, 0); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "<-- OsrFxEvtIoRead\n"); return; }
static VOID UsbChief_ReadEndPoint(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG totalLength) { PMDL newMdl=NULL, requestMdl = NULL; PURB urb = NULL; WDFMEMORY urbMemory; ULONG stageLength = 0; NTSTATUS status; ULONG_PTR virtualAddress = 0; PREQUEST_CONTEXT rwContext = NULL; PFILE_CONTEXT fileContext = NULL; WDFUSBPIPE pipe; WDF_USB_PIPE_INFORMATION pipeInfo; WDF_OBJECT_ATTRIBUTES objectAttribs; USBD_PIPE_HANDLE usbdPipeHandle; PDEVICE_CONTEXT deviceContext; UsbChief_DbgPrint(DEBUG_RW, ("UsbChief_DispatchReadWrite - begins\n")); deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); fileContext = GetFileContext(WdfRequestGetFileObject(Request)); pipe = fileContext->Pipe; WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); WdfUsbTargetPipeGetInformation(pipe, &pipeInfo); rwContext = GetRequestContext(Request); status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl); if(!NT_SUCCESS(status)){ UsbChief_DbgPrint(0, ("WdfRequestRetrieveOutputWdmMdl failed %x\n", status)); goto Exit; } virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl); if (totalLength > MAX_TRANSFER_SIZE) stageLength = MAX_TRANSFER_SIZE; else stageLength = totalLength; newMdl = IoAllocateMdl((PVOID) virtualAddress, totalLength, FALSE, FALSE, NULL); if (!newMdl) { UsbChief_DbgPrint(0, ("Failed to alloc mem for mdl\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } IoBuildPartialMdl(requestMdl, newMdl, (PVOID)virtualAddress, stageLength); WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); objectAttribs.ParentObject = Request; status = WdfMemoryCreate(&objectAttribs, NonPagedPool, POOL_TAG, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), &urbMemory, (PVOID*) &urb); if (!NT_SUCCESS(status)) { UsbChief_DbgPrint(0, ("Failed to alloc mem for urb\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe); UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), usbdPipeHandle, NULL, newMdl, stageLength, USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, NULL); status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL ); if (!NT_SUCCESS(status)) { UsbChief_DbgPrint(0, ("Failed to format requset for urb\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } WdfRequestSetCompletionRoutine(Request, UsbChief_ReadCompletion, NULL); rwContext->UrbMemory = urbMemory; rwContext->Mdl = newMdl; rwContext->Length = totalLength - stageLength; rwContext->Numxfer = 0; rwContext->VirtualAddress = virtualAddress + stageLength; if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) { status = WdfRequestGetStatus(Request); ASSERT(!NT_SUCCESS(status)); } Exit: if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); if (newMdl != NULL) { IoFreeMdl(newMdl); } } }
static VOID UsbChief_EvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { NTSTATUS Status; size_t Length = 0; PIOCTL_DATA data; PDEVICE_CONTEXT pDeviceContext; UCHAR test[4096]; UCHAR *config; WORD *version; URB Urb; WDF_USB_INTERFACE_SELECT_SETTING_PARAMS interfaceParams; ULONG i; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(Queue); PAGED_CODE(); pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); Length = 0; switch(IoControlCode) { case IOCTL_VENDOR_WRITE: if (InputBufferLength != sizeof(*data)) { UsbChief_DbgPrint(0, ("Invalid InputBuffer Size: %d/%d\n", InputBufferLength, sizeof(*data))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } Status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &data, &Length); if (!NT_SUCCESS(Status)) goto out; UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtIoDeviceControl: IOCTL_VENDOR_WRITE %x, Index %x, Value %x, Max Length %d, Buf %p\n", data->Request, data->Index, data->Value, data->Length, data->Buffer)); if (Length != sizeof(*data)) { UsbChief_DbgPrint(0, ("Failed to retrieve buffer: %d/%d\n", Length, sizeof(*data))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } memset(&Urb, 0, sizeof(Urb)); Urb.UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE; Urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); Urb.UrbControlVendorClassRequest.RequestTypeReservedBits = 0x40; Urb.UrbControlVendorClassRequest.TransferBufferLength = data->Length; Urb.UrbControlVendorClassRequest.TransferBuffer = (PVOID)data->Buffer; Urb.UrbControlVendorClassRequest.Request = data->Request; Urb.UrbControlVendorClassRequest.Value = data->Value; Urb.UrbControlVendorClassRequest.Index = data->Index; if (DebugLevel & DEBUG_IOCTL) { for(i = 0; i < data->Length; i++) DbgPrint("%02X ", ((PUCHAR)data->Buffer)[i]); DbgPrint("\n"); } Status = WdfUsbTargetDeviceSendUrbSynchronously(pDeviceContext->WdfUsbTargetDevice, NULL, NULL, &Urb); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfUsbTargetDeviceSendControlTransferSynchronously failed\n")); } break; case IOCTL_VENDOR_READ: if (InputBufferLength != sizeof(*data)) { UsbChief_DbgPrint(0, ("Invalid InputBuffer Size: %d/%d\n", InputBufferLength, sizeof(*data))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } Status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &data, &Length); if (!NT_SUCCESS(Status)) goto out; UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtIoDeviceControl: IOCTL_VENDOR_READ %x, Index %x, Value %x, Max Length %d, Buf %p\n", data->Request, data->Index, data->Value, data->Length, data->Buffer)); if (Length != sizeof(*data)) { UsbChief_DbgPrint(0, ("Failed to retrieve buffer: %d/%d\n", Length, sizeof(*data))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } if (data->Length > sizeof(test)) { Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } memset(&Urb, 0, sizeof(Urb)); Urb.UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE; Urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); Urb.UrbControlVendorClassRequest.RequestTypeReservedBits = 0xc0; Urb.UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK; Urb.UrbControlVendorClassRequest.TransferBufferLength = data->Length; Urb.UrbControlVendorClassRequest.TransferBuffer = test; Urb.UrbControlVendorClassRequest.Request = data->Request; Urb.UrbControlVendorClassRequest.Value = data->Value; Urb.UrbControlVendorClassRequest.Index = data->Index; Status = WdfUsbTargetDeviceSendUrbSynchronously(pDeviceContext->WdfUsbTargetDevice, NULL, NULL, &Urb); if (DebugLevel & DEBUG_IOCTL && NT_SUCCESS(Status)) { for(i = 0; i < Urb.UrbControlVendorClassRequest.TransferBufferLength; i++) DbgPrint("%02X ", ((PUCHAR)test)[i]); DbgPrint("\n"); } if (Urb.UrbControlVendorClassRequest.TransferBufferLength) memcpy((PVOID)data->Buffer, test, Urb.UrbControlVendorClassRequest.TransferBufferLength); Length = Urb.UrbControlVendorClassRequest.TransferBufferLength; break; case IOCTL_SELECT_CONFIGURATION: if (InputBufferLength != sizeof(*config)) { UsbChief_DbgPrint(0, ("Invalid InputBuffer Size: %d/%d\n", InputBufferLength, sizeof(*config))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } config = 0; Status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, (PVOID)&config, &Length); if (!NT_SUCCESS(Status)) goto out; if (Length != sizeof(*config)) { UsbChief_DbgPrint(0, ("Invalid Length: %d/%d\n", Length, sizeof(*config))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtDeviceControl: IOCTL_SELECT_CONFIGURATION %x\n", *config)); if (!pDeviceContext->UsbInterface) { Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING (&interfaceParams, *config); Status = WdfUsbInterfaceSelectSetting(pDeviceContext->UsbInterface, WDF_NO_OBJECT_ATTRIBUTES, &interfaceParams); break; case IOCTL_GET_FIRMWARE_VERSION: UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtDeviceControl: GET_FIRMWARE_VERSION\n")); Status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &version, &Length); if (!NT_SUCCESS(Status)) goto out; if (Length != sizeof(*version)) { UsbChief_DbgPrint(0, ("Invalid Length: %d/%d\n", Length, sizeof(*version))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } *version = pDeviceContext->UsbDeviceDescriptor.bcdDevice; break; default: UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtDeviceControl %08x (Device %x, Method %x) unknown\n", IoControlCode, DEVICE_TYPE_FROM_CTL_CODE(IoControlCode), METHOD_FROM_CTL_CODE(IoControlCode))); Status = STATUS_INVALID_DEVICE_REQUEST; break; } out: UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtDeviceControl: Status %08x, Length %d\n", Status, Length)); WdfRequestCompleteWithInformation(Request, Status, Length); }
NTSTATUS EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) { NTSTATUS status; WDFDEVICE device; // Device object PDEVICE_CONTEXT devCtx = NULL; // Pointer to a device context WDF_OBJECT_ATTRIBUTES attributes; // Object attribute WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; // PNP Power event callback WDF_DEVICE_PNP_CAPABILITIES pnpCapabilities; // UNREFERENCED_PARAMETER(Driver); /*Set the callback functions that will be executed on PNP and Power events*/ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // Init pnpPowerCallbacks pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceD0Entry = EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = EvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // Setup pnpPowerCallbacks WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); // Buffered IO type /*Initialize storage for the device context*/ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); /*Create a device instance.*/ status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfDeviceCreate failed with status 0x%08x\n", status)); return status; } /*Set the PNP capabilities of our device. we don't want an annoying popup if the device is pulled out of the USB slot.*/ WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCapabilities); pnpCapabilities.Removable = WdfTrue; // Can hot-unplug pnpCapabilities.SurpriseRemovalOK = WdfTrue; // WdfDeviceSetPnpCapabilities(device, &pnpCapabilities); devCtx = GetDeviceContext(device); /*Create a WDF memory object for the memory that is occupied by the WdfMemLEDArrayState variable in the device context. this way we have the value itself handy for debugging purposes, and we have a WDF memory handle that can be used for passing to the low level USB functions. this alleviates the need to getting the buffer at run time.*/ status = WdfMemoryCreatePreallocated(WDF_NO_OBJECT_ATTRIBUTES, &devCtx->D0LEDArrayState, sizeof(devCtx->D0LEDArrayState), &devCtx->WdfMemLEDArrayState); // for Debbug if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfMemoryCreatePreallocated failed with status 0x%08x\n", status)); return status; } // Create Queues for handling IO request status = CreateQueues(device, devCtx); if(!NT_SUCCESS(status)) return status; // Create Device Interface status = WdfDeviceCreateDeviceInterface(device, &GUID_DEV_IF_LEDSCTRL, NULL); if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfDeviceCreateDeviceInterface failed with status 0x%08x\n", status)); return status; } return status; }
NTSTATUS HidFx2EvtDeviceD0Entry( IN WDFDEVICE Device, IN WDF_POWER_DEVICE_STATE PreviousState ) /*++ Routine Description: EvtDeviceD0Entry event callback must perform any operations that are necessary before the specified device is used. It will be called every time the hardware needs to be (re-)initialized. This function is not marked pageable because this function is in the device power up path. When a function is marked pagable and the code section is paged out, it will generate a page fault which could impact the fast resume behavior because the client driver will have to wait until the system drivers can service this page fault. This function runs at PASSIVE_LEVEL, even though it is not paged. A driver can optionally make this function pageable if DO_POWER_PAGABLE is set. Even if DO_POWER_PAGABLE isn't set, this function still runs at PASSIVE_LEVEL. In this case, though, the function absolutely must not do anything that will cause a page fault. Arguments: Device - Handle to a framework device object. PreviousState - Device power state which the device was in most recently. If the device is being newly started, this will be PowerDeviceUnspecified. Return Value: NTSTATUS --*/ { PDEVICE_EXTENSION devContext = NULL; NTSTATUS status = STATUS_SUCCESS; UCHAR switchState = 0; devContext = GetDeviceContext(Device); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP, "HidFx2EvtDeviceD0Entry Enter - coming from %s\n", DbgDevicePowerString(PreviousState)); // // Retrieve the current switch state and store it in device context // status = HidFx2GetSwitchState(Device, &switchState); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Failed to get current swicth state, status: 0x%x\n", status); return status; } devContext->CurrentSwitchState = switchState; // // Start the target. This will start the continuous reader // status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(devContext->InterruptPipe)); if (NT_SUCCESS(status)) { devContext->IsPowerUpSwitchState = TRUE; } TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "HidFx2EvtDeviceD0Entry Exit, status: 0x%x\n", status); return status; }
NTSTATUS VioCryptDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDFDEVICE device; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES attributes; WDFQUEUE queue; WDF_IO_QUEUE_CONFIG queueConfig; WDF_INTERRUPT_CONFIG interruptConfig; PDEVICE_CONTEXT context; UNREFERENCED_PARAMETER(Driver); Trace(TRACE_LEVEL_VERBOSE, "[%s] -->", __FUNCTION__); PAGED_CODE(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = VioCryptDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = VioCryptDeviceReleaseHardware; pnpPowerCallbacks.EvtDeviceD0Entry = VioCryptDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = VioCryptDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); attributes.EvtCleanupCallback = VioCryptDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfDeviceCreate failed: status %X", __FUNCTION__, status); return status; } context = GetDeviceContext(device); RtlZeroMemory(context, sizeof(*context)); InitializeListHead(&context->PendingBuffers); WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, VioCryptInterruptIsr, VioCryptInterruptDpc); interruptConfig.EvtInterruptEnable = VioCryptInterruptEnable; interruptConfig.EvtInterruptDisable = VioCryptInterruptDisable; status = WdfInterruptCreate(device, &interruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &context->WdfInterrupt); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfInterruptCreate failed: status %X", __FUNCTION__, status); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfSpinLockCreate(&attributes, &context->VirtQueueLock); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfSpinLockCreate failed: status %X", __FUNCTION__, status); return status; } status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_VIOCRYPT, NULL); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfDeviceCreateDeviceInterface failed: status %X", __FUNCTION__, status); return status; } WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoDeviceControl = VioCryptIoControl; queueConfig.EvtIoStop = VioCryptIoStop; queueConfig.AllowZeroLengthRequests = FALSE; status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfIoQueueCreate failed: status %X", __FUNCTION__, status); return status; } status = WdfDeviceConfigureRequestDispatching(device, queue, WdfRequestTypeDeviceControl); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfDeviceConfigureRequestDispatching failed: status %X", __FUNCTION__, status); return status; } Trace(TRACE_LEVEL_VERBOSE, "[%s] <--", __FUNCTION__); return status; }
NTSTATUS HidFx2EvtDeviceD0Exit( IN WDFDEVICE Device, IN WDF_POWER_DEVICE_STATE TargetState ) /*++ Routine Description: This routine undoes anything done in EvtDeviceD0Entry. It is called whenever the device leaves the D0 state, which happens when the device is stopped, when it is removed, and when it is powered off. The device is still in D0 when this callback is invoked, which means that the driver can still touch hardware in this routine. EvtDeviceD0Exit event callback must perform any operations that are necessary before the specified device is moved out of the D0 state. If the driver needs to save hardware state before the device is powered down, then that should be done here. This function runs at PASSIVE_LEVEL, though it is generally not paged. A driver can optionally make this function pageable if DO_POWER_PAGABLE is set. Even if DO_POWER_PAGABLE isn't set, this function still runs at PASSIVE_LEVEL. In this case, though, the function absolutely must not do anything that will cause a page fault. Arguments: Device - Handle to a framework device object. TargetState - Device power state which the device will be put in once this callback is complete. Return Value: Success implies that the device can be used. Failure will result in the device stack being torn down. --*/ { PDEVICE_EXTENSION devContext; PAGED_CODE(); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP, "HidFx2EvtDeviceD0Exit Enter- moving to %s\n", DbgDevicePowerString(TargetState)); devContext = GetDeviceContext(Device); WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget( devContext->InterruptPipe), WdfIoTargetCancelSentIo); TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "HidFx2EvtDeviceD0Exit Exit\n"); return STATUS_SUCCESS; }
/****************************************************************************** WDF_IO_QUEUE_IO_DEVICE_CONTROL The IOCTL_SET_LOCAL_HOST_INFORMATION part of EvtIoDeviceControl. Tranform the Request into a SetLocalHostInformation, and pass it down to the local t1394_SetLocalHostProperties procedure. ******************************************************************************/ VOID t1394_EvtIoDeviceControl( /*IN*/WDFQUEUE Queue, /*IN*/WDFREQUEST Request, /*IN*/size_t OutputBufferLength, /*IN*/size_t InputBufferLength, /*IN*/ULONG IoControlCode ) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension; PVOID ioBuffer = NULL; WDFDEVICE device; size_t bufLength; //ENTER("t1394_EvtIoDeviceControl"); // TRACE(TL_TRACE, ("Request = 0x%p\n", Request)); device = WdfIoQueueGetDevice(Queue); deviceExtension = GetDeviceContext(device); // // Since all the IOCTLs handled here are buffered, WdfRequestRetrieveOutputBuffer & // WdfRequestRetrieveInputBuffer return the same buffer pointer. // So make sure you read all the information you need from // the buffer before you write to it. Also requiredLength of the buffer vary from // ioctl to ioctl, so we will pretend that we need zero length buffer and do the lenght // check later in the specific ioct case. // ntStatus = WdfRequestRetrieveInputBuffer(Request, 0, &ioBuffer, &bufLength); if( !NT_SUCCESS(ntStatus) || ioBuffer == NULL) { // TRACE(TL_ERROR, ("WdfRequestRetrieveInputBuffer failed 0x%x\n", ntStatus)); WdfRequestComplete(Request, ntStatus); return; } switch (IoControlCode) { case IOCTL_SET_LOCAL_HOST_INFORMATION: { PSET_LOCAL_HOST_INFORMATION SetLocalHostInformation; // TRACE(TL_TRACE, ("IOCTL_SET_LOCAL_HOST_INFORMATION\n")); if (InputBufferLength < sizeof(SET_LOCAL_HOST_INFORMATION)) { ntStatus = STATUS_BUFFER_TOO_SMALL; } else { SetLocalHostInformation = (PSET_LOCAL_HOST_INFORMATION)ioBuffer; if (InputBufferLength < (sizeof(SET_LOCAL_HOST_INFORMATION) + SetLocalHostInformation->ulBufferSize)) { ntStatus = STATUS_BUFFER_TOO_SMALL; } else { ntStatus = t1394_SetLocalHostProperties( device, Request, SetLocalHostInformation->nLevel, (PVOID)&SetLocalHostInformation->Information ); if (NT_SUCCESS(ntStatus)) WdfRequestSetInformation(Request, OutputBufferLength); } } } break; // IOCTL_SET_LOCAL_HOST_INFORMATION default: // TRACE(TL_ERROR, ("Invalid ioControlCode = 0x%x\n", IoControlCode)); ntStatus = STATUS_INVALID_PARAMETER; break; // default } // switch // only complete if the device is there if (ntStatus != STATUS_PENDING) { WdfRequestComplete(Request, ntStatus); } //EXIT("t1394_IoControl", ntStatus); return ; } // t1394_EvtIoDeviceControl
NTSTATUS HidFx2GetSwitchState( IN WDFDEVICE Device, OUT PUCHAR SwitchState ) /*++ Routine Description: This function gets the swicth state of teh USB device Arguments: Device - Handle to a framework device object. SwitchState - Pointer to a variable that receives the switch state Return Value: Success implies that the device can be used. Failure will result in the device stack being torn down. --*/ { PDEVICE_EXTENSION devContext = NULL; NTSTATUS status = STATUS_SUCCESS; WDF_MEMORY_DESCRIPTOR memDesc; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; ULONG bytesTransferred = 0; devContext = GetDeviceContext(Device); // // set the segment state on the USB device // WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestDeviceToHost, BmRequestToDevice, HIDFX2_READ_SWITCH_STATE, // Request 0, // Value 0); // Index WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, SwitchState, sizeof(UCHAR)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( devContext->UsbDevice, NULL, // Optional WDFREQUEST NULL, // PWDF_REQUEST_SEND_OPTIONS &controlSetupPacket, &memDesc, &bytesTransferred ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "GetSwitchState: Failed to read switch state - 0x%x \n", status); } else { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "GetSwitchState: Switch state is 0x%x\n", *SwitchState); } return status; }
NTSTATUS t1394_EvtDeviceAdd( /*IN*/WDFDRIVER Driver, /*IN*/PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension; PNODE_DEVICE_EXTENSION pNodeExt; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES fdoAttributes,lockAttributes; WDFDEVICE device; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_IO_TARGET_OPEN_PARAMS openParams; //UNREFERENCED_PARAMETER(Driver); //ENTER("t1394_PnpAddDevice"); // // 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. // // These two callbacks set up and tear down hardware state, // specifically that which only has to be done once. // pnpPowerCallbacks.EvtDevicePrepareHardware = t1394_EvtPrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = t1394_EvtReleaseHardware; pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup = t1394_EvtDeviceSelfManagedIoCleanup; pnpPowerCallbacks.EvtDeviceD0Entry = t1394_EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = t1394_EvtDeviceD0Exit; // // Register the PnP and power callbacks. Power policy related callbacks // will be registered// later in SotwareInit. // WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); if ( !NT_SUCCESS(status)) { //TRACE(TL_ERROR, ("WdfDeviceInitSetPnpPowerEventCallbacks failed %x\n", // status)); return status; } WdfDeviceInitSetExclusive(DeviceInit, FALSE); // // Specify the size and type of device context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, DEVICE_EXTENSION); status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device); if ( !NT_SUCCESS(status)) { //TRACE(TL_ERROR, ("WdfDeviceInitialize failed %x\n", status)); return status; } deviceExtension = GetDeviceContext (device); deviceExtension->WdfDevice = device; //TRACE(TL_TRACE, ("PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n", // WdfDeviceWdmGetPhysicalDevice (device), // WdfDeviceWdmGetDeviceObject (device), // WdfDeviceWdmGetAttachedDevice(device), // deviceExtension)); // // Tell the Framework that this device will need an interface so that // application can interact with it. // status = WdfDeviceCreateDeviceInterface( device, #if defined(_1394VDEV_DRIVER_) (LPGUID) &GUID_1394VDEV, #else (LPGUID) &GUID_1394DIAG, #endif NULL ); if (!NT_SUCCESS (status)) { //TRACE(TL_ERROR, ("WdfDeviceCreateDeviceInterface failed %x\n", status)); return status; } // // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so // that you don't get the popup in usermode (on Win2K) when you surprise // remove the device. // WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities(device, &pnpCaps); // save the device object we created as our physical device object deviceExtension->PhysicalDeviceObject = WdfDeviceWdmGetPhysicalDevice (device); if (deviceExtension->PhysicalDeviceObject == NULL) { //TRACE(TL_ERROR, ("WdfDeviceWdmGetPhysicalDevice: NULL DeviceObject\n")); return STATUS_UNSUCCESSFUL; } // // This is our default IoTarget representing the deviceobject // we are attached to. // deviceExtension->StackIoTarget = WdfDeviceGetIoTarget(device); deviceExtension->StackDeviceObject = WdfDeviceWdmGetAttachedDevice(device); if (deviceExtension->StackDeviceObject == NULL) { //TRACE(TL_ERROR, ("WdfDeviceWdmGetAttachedDevice: NULL DeviceObject\n")); return STATUS_UNSUCCESSFUL; } // Patch: this code is not in DDK 7600.16385.1 { // // Get the port device object from the passed in PhysicalDeviceObject // created by the 1394 stack for us. // Note: we can't use the top of the stack and get its device extension // in case there is a filter driver between us and our PDO. // //pNodeExt = WdfDeviceWdmGetPhysicalDevice(device)->DeviceExtension; //deviceExtension->PortDeviceObject = pNodeExt->PortDeviceObject; // Patch: this code is not in DDK 7600.16385.1 } //TRACE(TL_TRACE, ("PortDeviceObject = 0x%x\n", // deviceExtension->PortDeviceObject)); // // Create a automanaged queue for dispatching ioctl requests. // All other requests are automatically failed by the framework. // By creating an automanaged queue we don't have to worry about // PNP/Power synchronization. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &ioQueueConfig, WdfIoQueueDispatchParallel ); ioQueueConfig.EvtIoDeviceControl = t1394_EvtIoDeviceControl; status = WdfIoQueueCreate( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->IoctlQueue // queue handle ); if (!NT_SUCCESS (status)) { //TRACE(TL_ERROR, ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // // Create an additional queue to hold bus reset requests. // WDF_IO_QUEUE_CONFIG_INIT( &ioQueueConfig, WdfIoQueueDispatchManual ); status = WdfIoQueueCreate ( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->BusResetRequestsQueue ); if(!NT_SUCCESS (status)){ //TRACE(TL_ERROR, ("Error Creating Reset Request Queue 0x%x\n", // status)); return status; } // // Create another IoTarget representing PortDeviceObject so that // we can send async requests in rawmode directly to the port device. // WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(&openParams, pNodeExt->PortDeviceObject); status = WdfIoTargetCreate(device, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->PortDeviceIoTarget); if (!NT_SUCCESS (status)) { //TRACE(TL_ERROR, ("WdfIoTargetCreate failed 0x%x\n", status)); return status; } status = WdfIoTargetOpen(deviceExtension->PortDeviceIoTarget, &openParams); if (!NT_SUCCESS (status)) { //TRACE(TL_ERROR, ("WdfIoTargetCreate failed 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes); lockAttributes.ParentObject = device; // initialize the spinlock/list to store the bus reset irps... status = WdfSpinLockCreate(&lockAttributes,&deviceExtension->CromSpinLock ); if(!NT_SUCCESS(status)){ //TRACE(TL_ERROR, ("WdfSpinLockCreate CromSpinLock " // "failed 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes); lockAttributes.ParentObject = device; status = WdfSpinLockCreate(&lockAttributes, &deviceExtension->AsyncSpinLock ); if(!NT_SUCCESS(status)){ //TRACE(TL_ERROR, ("WdfSpinLockCreate AsyncSpinLock " // "failed 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes); lockAttributes.ParentObject = device; status = WdfSpinLockCreate(&lockAttributes, &deviceExtension->IsochSpinLock ); if(!NT_SUCCESS(status)){ //TRACE(TL_ERROR, ("WdfSpinLockCreate IsochSpinLock " // "failed 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes); lockAttributes.ParentObject = device; status = WdfSpinLockCreate(&lockAttributes, &deviceExtension->IsochResourceSpinLock ); if(!NT_SUCCESS(status)){ //TRACE(TL_ERROR, ("WdfSpinLockCreate IsochResourceSpinLock " // "failed 0x%x\n", status)); return status; } InitializeListHead(&deviceExtension->CromData); InitializeListHead(&deviceExtension->AsyncAddressData); InitializeListHead(&deviceExtension->IsochDetachData); InitializeListHead(&deviceExtension->IsochResourceData); //EXIT("t1394_PnpAddDevice", status); return(status); } // t1394_PnpAddDevice
NTSTATUS OsrFxEvtDevicePrepareHardware( WDFDEVICE Device, WDFCMRESLIST ResourceList, 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 and selecting descriptors. Arguments: Device - handle to a device Return Value: NT status value --*/ { NTSTATUS status; PDEVICE_CONTEXT pDeviceContext; WDF_USB_DEVICE_INFORMATION deviceInfo; ULONG waitWakeEnable; UNREFERENCED_PARAMETER(ResourceList); UNREFERENCED_PARAMETER(ResourceListTranslated); waitWakeEnable = FALSE; 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; } } // // Retrieve USBD version information, port driver capabilites and device // capabilites such as speed, power, etc. // WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo); status = WdfUsbTargetDeviceRetrieveInformation( pDeviceContext->UsbDevice, &deviceInfo); if (NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceHighSpeed: %s\n", (deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) ? "TRUE" : "FALSE"); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceSelfPowered: %s\n", (deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED) ? "TRUE" : "FALSE"); waitWakeEnable = deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceRemoteWakeable: %s\n", waitWakeEnable ? "TRUE" : "FALSE"); // // Save these for use later. // pDeviceContext->UsbDeviceTraits = deviceInfo.Traits; } status = SelectInterfaces(Device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "SelectInterfaces failed 0x%x\n", status); return status; } // // Enable wait-wake and idle timeout if the device supports it // if (waitWakeEnable) { status = OsrFxSetPowerPolicy(Device); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "OsrFxSetPowerPolicy failed %!STATUS!\n", status); return status; } } status = OsrFxConfigContReaderForInterruptEndPoint(pDeviceContext); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- EvtDevicePrepareHardware\n"); return status; }
VOID ReadWriteBulkEndPoints( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG Length, IN WDF_REQUEST_TYPE RequestType ) /*++ Routine Description: This callback is invoked when the framework received WdfRequestTypeRead or WdfRequestTypeWrite request. This read/write is performed in stages of MAX_TRANSFER_SIZE. Once a stage of transfer is complete, then the request is circulated again, until the requested length of transfer is performed. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. This one represents the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework. Length - Length of the input/output buffer. Return Value: VOID --*/ { PMDL newMdl=NULL, requestMdl = NULL; PURB urb = NULL; WDFMEMORY urbMemory; ULONG totalLength = Length; ULONG stageLength = 0; ULONG urbFlags = 0; NTSTATUS status; ULONG_PTR virtualAddress = 0; PREQUEST_CONTEXT rwContext = NULL; PFILE_CONTEXT fileContext = NULL; WDFUSBPIPE pipe; WDF_USB_PIPE_INFORMATION pipeInfo; WDF_OBJECT_ATTRIBUTES objectAttribs; USBD_PIPE_HANDLE usbdPipeHandle; PDEVICE_CONTEXT deviceContext; kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - begins\n")); // // First validate input parameters. // deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); if (totalLength > deviceContext->MaximumTransferSize) { kJtag_DbgPrint(1, ("Transfer length > circular buffer\n")); status = STATUS_INVALID_PARAMETER; goto Exit; } if ((RequestType != WdfRequestTypeRead) && (RequestType != WdfRequestTypeWrite)) { kJtag_DbgPrint(1, ("RequestType has to be either Read or Write\n")); status = STATUS_INVALID_PARAMETER; goto Exit; } // // Get the pipe associate with this request. // fileContext = GetFileContext(WdfRequestGetFileObject(Request)); pipe = fileContext->Pipe; WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); WdfUsbTargetPipeGetInformation(pipe, &pipeInfo); if((WdfUsbPipeTypeBulk != pipeInfo.PipeType) && (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType)) { kJtag_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt\n")); status = STATUS_INVALID_DEVICE_REQUEST; goto Exit; } rwContext = GetRequestContext(Request); if(RequestType == WdfRequestTypeRead) { status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl); if(!NT_SUCCESS(status)){ kJtag_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed %x\n", status)); goto Exit; } urbFlags |= USBD_TRANSFER_DIRECTION_IN; rwContext->Read = TRUE; kJtag_DbgPrint(3, ("Read operation\n")); } else { status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl); if(!NT_SUCCESS(status)){ kJtag_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed %x\n", status)); goto Exit; } urbFlags |= USBD_TRANSFER_DIRECTION_OUT; rwContext->Read = FALSE; kJtag_DbgPrint(3, ("Write operation\n")); } urbFlags |= USBD_SHORT_TRANSFER_OK; virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl); // // the transfer request is for totalLength. // we can perform a max of MAX_TRANSFER_SIZE // in each stage. // if (totalLength > MAX_TRANSFER_SIZE) { stageLength = MAX_TRANSFER_SIZE; } else { stageLength = totalLength; } newMdl = IoAllocateMdl((PVOID) virtualAddress, totalLength, FALSE, FALSE, NULL); if (newMdl == NULL) { kJtag_DbgPrint(1, ("Failed to alloc mem for mdl\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } // // map the portion of user-buffer described by an mdl to another mdl // IoBuildPartialMdl(requestMdl, newMdl, (PVOID) virtualAddress, stageLength); WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); objectAttribs.ParentObject = Request; status = WdfMemoryCreate(&objectAttribs, NonPagedPool, POOL_TAG, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), &urbMemory, (PVOID*) &urb); if (!NT_SUCCESS(status)) { kJtag_DbgPrint(1, ("Failed to alloc mem for urb\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe); UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), usbdPipeHandle, NULL, newMdl, stageLength, urbFlags, NULL); status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL ); if (!NT_SUCCESS(status)) { kJtag_DbgPrint(1, ("Failed to format requset for urb\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } WdfRequestSetCompletionRoutine(Request, ReadWriteCompletion, NULL); // // set REQUEST_CONTEXT parameters. // rwContext->UrbMemory = urbMemory; rwContext->Mdl = newMdl; rwContext->Length = totalLength - stageLength; rwContext->Numxfer = 0; rwContext->VirtualAddress = virtualAddress + stageLength; if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) { status = WdfRequestGetStatus(Request); ASSERT(!NT_SUCCESS(status)); } Exit: if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); if (newMdl != NULL) { IoFreeMdl(newMdl); } } kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - ends\n")); return; }
NTSTATUS OsrFxEvtDeviceAdd( WDFDRIVER Driver, 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; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_CONTEXT pDevContext; WDFQUEUE queue; GUID activity; 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 wdfusb pipe continuous reader // as we go in and out of the D0-working state. // pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = OsrFxEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); // // 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; } // // Setup the activity ID so that we can log events using it. // activity = DeviceToActivityId(device); // // Get the DeviceObject context by using accessor function specified in // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_CONTEXT. // pDevContext = GetDeviceContext(device); // // Get the device's friendly name and location so that we can use it in // error logging. If this fails then it will setup dummy strings. // GetDeviceEventLoggingNames(device); // // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so // that you don't get the popup in usermode (on Win2K) when you surprise // remove the device. // WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities(device, &pnpCaps); // // Create a parallel default queue and register an event callback to // receive ioctl requests. We will create separate queues for // handling read and write requests. All other requests will be // completed with error status automatically by the framework. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoDeviceControl = OsrFxEvtIoDeviceControl; status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);// pointer to default queue if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed %!STATUS!\n", status); goto Error; } // // We will create a separate sequential queue and configure it // to receive read requests. We also need to register a EvtIoStop // handler so that we can acknowledge requests that are pending // at the target driver. // WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoRead = OsrFxEvtIoRead; ioQueueConfig.EvtIoStop = OsrFxEvtIoStop; status = WdfIoQueueCreate( device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // queue handle ); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); goto Error; } status = WdfDeviceConfigureRequestDispatching( device, queue, WdfRequestTypeRead); if(!NT_SUCCESS (status)){ ASSERT(NT_SUCCESS(status)); TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status); goto Error; } // // We will create another sequential queue and configure it // to receive write requests. // WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoWrite = OsrFxEvtIoWrite; ioQueueConfig.EvtIoStop = OsrFxEvtIoStop; status = WdfIoQueueCreate( device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // queue handle ); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); goto Error; } status = WdfDeviceConfigureRequestDispatching( device, queue, WdfRequestTypeWrite); if(!NT_SUCCESS (status)){ ASSERT(NT_SUCCESS(status)); TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status); goto Error; } // // Register a manual I/O queue for handling Interrupt Message Read Requests. // This queue will be used for storing Requests that need to wait for an // interrupt to occur before they can be completed. // WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchManual); // // This queue is used for requests that dont directly access the device. The // requests in this queue are serviced only when the device is in a fully // powered state and sends an interrupt. So we can use a non-power managed // queue to park the requests since we dont care whether the device is idle // or fully powered up. // ioQueueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->InterruptMsgQueue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); goto Error; } // // Register a device interface so that app can find our device and talk to it. // status = WdfDeviceCreateDeviceInterface(device, (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2, NULL);// Reference String if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreateDeviceInterface failed %!STATUS!\n", status); goto Error; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- OsrFxEvtDeviceAdd\n"); return status; Error: // // Log fail to add device to the event log // EventWriteFailAddDevice(&activity, pDevContext->DeviceName, pDevContext->Location, status); return status; }
// this will Initialize DirectX graphics and its window void TSRD3D11GraphicsSubSystem::InitGraphics( TSRScreenMode& _mode ) { DXGI_SWAP_CHAIN_DESC SwapChainDesc; ZeroMemory( &SwapChainDesc, sizeof( SwapChainDesc ) ); unsigned int uiNumSamples = _mode.m_uiSamplesCountForMSAA; if ( uiNumSamples == 0 ) { uiNumSamples = 1; } D3D_RTV_DIMENSION RenderTargetViewDimension = D3D_RTV_DIMENSION_TEXTURE2D; D3D_DSV_DIMENSION DepthStencilViewDimension = D3D_DSV_DIMENSION_TEXTURE2D; if ( uiNumSamples > 1 ) { RenderTargetViewDimension = D3D_RTV_DIMENSION_TEXTURE2DMS; DepthStencilViewDimension = D3D_DSV_DIMENSION_TEXTURE2DMS; } if ( _mode.m_bBackBufferUsesDesktopResolution ) { m_uiBackBufferWidth = GetSystemMetrics( SM_CXFULLSCREEN ); m_uiBackBufferHeight = GetSystemMetrics( SM_CYFULLSCREEN ); } else { m_uiBackBufferWidth = TSRSystem()->m_DisplayMode.m_uiWidth; m_uiBackBufferHeight = TSRSystem()->m_DisplayMode.m_uiHeight; } SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; SwapChainDesc.BufferDesc.Width = m_uiBackBufferWidth; SwapChainDesc.BufferDesc.Height = m_uiBackBufferHeight; SwapChainDesc.BufferDesc.RefreshRate.Denominator = 60; SwapChainDesc.BufferDesc.RefreshRate.Numerator = 1; // SwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED; // SwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; SwapChainDesc.SampleDesc.Count = uiNumSamples; SwapChainDesc.SampleDesc.Quality = 0; SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; SwapChainDesc.BufferCount = 1; SwapChainDesc.OutputWindow = SystemWin32()->GetMainHWND(); SwapChainDesc.Windowed = TSRSystem()->m_DisplayMode.m_bIsWindowed ? TRUE : FALSE; SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; /*UINT uiNumAdapters = 0; IDXGIAdapter* pAdapter; std::vector <IDXGIAdapter*> vAdapters; std::vector <DXGI_ADAPTER_DESC> vAdapterDescriptors; DXGI_ADAPTER_DESC adapterDesc; IDXGIFactory * pFactory; HRESULT hrr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&pFactory) ); while(pFactory->EnumAdapters(uiNumAdapters, &pAdapter) != DXGI_ERROR_NOT_FOUND) { vAdapters.push_back(pAdapter); pAdapter->GetDesc( &adapterDesc ); vAdapterDescriptors.push_back( adapterDesc ); ++uiNumAdapters; } */ unsigned int uiDeviceCreationFlags = 0; #ifdef _DEBUG /// onwindows 10, deubg flag results in crash, so disabling it for now uiDeviceCreationFlags = 0;//D3D_CREATE_DEVICE_DEBUG; #endif #ifdef D3D10_RENDERER HRESULT hr = D3D10CreateDeviceAndSwapChain( NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, uiDeviceCreationFlags, D3D10_SDK_VERSION, &SwapChainDesc, &m_pSwapChain, &m_pD3DDevice ); #endif #ifdef D3D11_RENDERER D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); HRESULT hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, uiDeviceCreationFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &SwapChainDesc, &m_pSwapChain, &m_pD3DDevice, &m_FeatureLevel, &m_pD3DDeviceContext ); #endif // Create a render target view ID3DTexture2D* pBuffer; hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3DTexture2D ), ( LPVOID* ) &pBuffer ); if( FAILED( hr ) ) { assert( 0 && "Failed to get the back buffer from the swap chain" ); } D3D_RENDER_TARGET_VIEW_DESC DescRT; DescRT.Format = DXGI_FORMAT_R8G8B8A8_UNORM; DescRT.ViewDimension = RenderTargetViewDimension; DescRT.Texture2D.MipSlice = 0; hr = m_pD3DDevice->CreateRenderTargetView( pBuffer, &DescRT, &m_pColorBufferView ); pBuffer->Release(); if( FAILED( hr ) ) { assert( 0 && "Failed to create render target view" ); } // Create depth stencil texture D3D_TEXTURE2D_DESC descDepth; descDepth.Width = m_uiBackBufferWidth; descDepth.Height = m_uiBackBufferHeight; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D32_FLOAT; descDepth.SampleDesc.Count = uiNumSamples; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D_USAGE_DEFAULT; descDepth.BindFlags = D3D_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; hr = m_pD3DDevice->CreateTexture2D( &descDepth, NULL, &m_pDepthStencil ); if ( FAILED( hr ) ) { assert( 0 && "Failed to create the depth stencil target" ); } // Create the depth stencil view D3D_DEPTH_STENCIL_VIEW_DESC descDSV; ZeroMemory( &descDSV, sizeof( D3D_DEPTH_STENCIL_VIEW_DESC ) ); descDSV.Format = descDepth.Format; descDSV.ViewDimension = DepthStencilViewDimension; descDSV.Texture2D.MipSlice = 0; hr = m_pD3DDevice->CreateDepthStencilView( m_pDepthStencil, &descDSV, &m_pDepthStencilView ); if ( FAILED( hr ) ) { assert( 0 && "Failed to create the depth stencil view" ); } m_pActiveColorBufferViews[ 0 ] = m_pColorBufferView; m_pActiveColorBufferViews[ 1 ] = NULL; m_pActiveColorBufferViews[ 2 ] = NULL; m_pActiveColorBufferViews[ 3 ] = NULL; m_pActiveDepthStencilView = m_pDepthStencilView; GetDeviceContext()->OMSetRenderTargets( 1, m_pActiveColorBufferViews, m_pActiveDepthStencilView ); // set the projection matrix accordingly Resize( _mode.m_uiWidth, _mode.m_uiHeight ); m_pColorBufferTexture = pBuffer; /// Create staging selection buffer texture D3D_TEXTURE2D_DESC descSelectionBuffer; descSelectionBuffer.Width = m_uiBackBufferWidth; descSelectionBuffer.Height = m_uiBackBufferHeight; descSelectionBuffer.MipLevels = 1; descSelectionBuffer.ArraySize = 1; descSelectionBuffer.Format = DXGI_FORMAT_R8G8B8A8_UNORM; descSelectionBuffer.SampleDesc.Count = 1;//uiNumSamples; descSelectionBuffer.SampleDesc.Quality = 0; descSelectionBuffer.Usage = D3D_USAGE_STAGING; descSelectionBuffer.BindFlags = 0; descSelectionBuffer.CPUAccessFlags = D3D_CPU_ACCESS_READ ; descSelectionBuffer.MiscFlags = 0; hr = m_pD3DDevice->CreateTexture2D( &descSelectionBuffer, NULL, &m_pCpuBackBufferCopy ); if ( FAILED( hr ) ) { assert( 0 && "Failed to create the selection buffer" ); } m_pQueryIdleGPU = NULL; D3D_QUERY_DESC queryDesc; queryDesc.MiscFlags = 0; queryDesc.Query = D3D_QUERY_EVENT; m_pD3DDevice->CreateQuery( &queryDesc, &m_pQueryIdleGPU ); #ifdef D3D10_RENDERER TSRPrintln( "D3D10 initialized successfully" ); #endif #ifdef D3D11_RENDERER TSRPrintln( "D3D11 initialized successfully" ); #endif #ifdef D3D10_RENDERER TSRPrintln( "D3D10 initialized successfully" ); #endif }
NTSTATUS SelectInterfaces( __in WDFDEVICE Device ) /*++ Routine Description: This helper routine selects the configuration, interface and creates a context for every pipe (end point) in that interface. Arguments: Device - Handle to a framework device Return Value: NT status value --*/ { WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; NTSTATUS status; PDEVICE_CONTEXT pDeviceContext; WDFUSBPIPE pipe; WDF_USB_PIPE_INFORMATION pipeInfo; UCHAR index; UCHAR numberConfiguredPipes; PAGED_CODE(); pDeviceContext = GetDeviceContext(Device); WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams); status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceSelectConfig failed %!STATUS! \n", status); // // 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 ((pDeviceContext->UsbDeviceTraits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) == 0) { GUID activity = DeviceToActivityId(Device); 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" ); EventWriteSelectConfigFailure( &activity, pDeviceContext->DeviceName, pDeviceContext->Location, status ); } return status; } pDeviceContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; numberConfiguredPipes = configParams.Types.SingleInterface.NumberConfiguredPipes; // // Get pipe handles // for(index=0; index < numberConfiguredPipes; index++) { WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); pipe = WdfUsbInterfaceGetConfiguredPipe( pDeviceContext->UsbInterface, index, //PipeIndex, &pipeInfo ); // // Tell the framework that it's okay to read less than // MaximumPacketSize // WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pipe); if(WdfUsbPipeTypeInterrupt == pipeInfo.PipeType) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "Interrupt Pipe is 0x%p\n", pipe); pDeviceContext->InterruptPipe = pipe; } if(WdfUsbPipeTypeBulk == pipeInfo.PipeType && WdfUsbTargetPipeIsInEndpoint(pipe)) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "BulkInput Pipe is 0x%p\n", pipe); pDeviceContext->BulkReadPipe = pipe; } if(WdfUsbPipeTypeBulk == pipeInfo.PipeType && WdfUsbTargetPipeIsOutEndpoint(pipe)) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "BulkOutput Pipe is 0x%p\n", pipe); pDeviceContext->BulkWritePipe = pipe; } } // // If we didn't find all the 3 pipes, fail the start. // if(!(pDeviceContext->BulkWritePipe && pDeviceContext->BulkReadPipe && pDeviceContext->InterruptPipe)) { status = STATUS_INVALID_DEVICE_STATE; TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "Device is not configured properly %!STATUS!\n", status); return status; } return status; }
NTSTATUS kmdf1394_EvtDeviceAdd ( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES fdoAttributes,lockAttributes; WDFDEVICE device; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; UNREFERENCED_PARAMETER (Driver); PAGED_CODE(); Enter(); // // 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. // // These two callbacks set up and tear down hardware state, // specifically that which only has to be done once. // pnpPowerCallbacks.EvtDevicePrepareHardware = kmdf1394_EvtPrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = kmdf1394_EvtReleaseHardware; pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup = \ kmdf1394_EvtDeviceSelfManagedIoCleanup; pnpPowerCallbacks.EvtDeviceD0Entry = kmdf1394_EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = kmdf1394_EvtDeviceD0Exit; // // Register the PnP and power callbacks. Power policy related callbacks // will be registered// later in SotwareInit. // WdfDeviceInitSetPnpPowerEventCallbacks (DeviceInit, &pnpPowerCallbacks); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceInitSetPnpPowerEventCallbacks failed %!STATUS!\n", ntStatus); return ntStatus; } // // We'll allow multiple handles to be opened to this device driver // so we'll set exclusivity to FALSE. // WdfDeviceInitSetExclusive (DeviceInit, FALSE); // // Specify the size and type of device context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE (&fdoAttributes, DEVICE_EXTENSION); ntStatus = WdfDeviceCreate (&DeviceInit, &fdoAttributes, &device); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceInitialize failed %!STATUS!\n", ntStatus); return ntStatus; } deviceExtension = GetDeviceContext (device); deviceExtension->WdfDevice = device; DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n", WdfDeviceWdmGetPhysicalDevice (device), WdfDeviceWdmGetDeviceObject (device), WdfDeviceWdmGetAttachedDevice(device), deviceExtension); // // Tell the Framework that this device will need an interface so that // application can interact with it. // ntStatus = WdfDeviceCreateDeviceInterface ( device, (LPGUID) &GUID_KMDF_VDEV, NULL); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceCreateDeviceInterface failed %!STATUS!\n", ntStatus); return ntStatus; } // // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so // that you don't get the popup in usermode (on Win2K) when you surprise // remove the device. // WDF_DEVICE_PNP_CAPABILITIES_INIT (&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities (device, &pnpCaps); // // save the device object we created as our physical device object // deviceExtension->PhysicalDeviceObject = \ WdfDeviceWdmGetPhysicalDevice (device); if (NULL == deviceExtension->PhysicalDeviceObject) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceWdmGetPhysicalDevice: NULL DeviceObject\n"); return STATUS_UNSUCCESSFUL; } // // This is our default IoTarget representing the deviceobject // we are attached to. // deviceExtension->StackIoTarget = WdfDeviceGetIoTarget(device); deviceExtension->StackDeviceObject = WdfDeviceWdmGetAttachedDevice(device); if (NULL == deviceExtension->StackDeviceObject) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceWdmGetAttachedDevice: NULL DeviceObject\n"); return STATUS_UNSUCCESSFUL; } // // Create a automanaged queue for dispatching ioctl requests. // All other requests are automatically failed by the framework. // By creating an automanaged queue we don't have to worry about // PNP/Power synchronization. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoDeviceControl = kmdf1394_EvtIoDeviceControl; __analysis_assume(ioQueueConfig.EvtIoStop != 0); ntStatus = WdfIoQueueCreate ( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->IoctlQueue); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfIoQueueCreate failed %!STATUS!\n", ntStatus); return ntStatus; } // // Create an additional queue to hold bus reset requests. // WDF_IO_QUEUE_CONFIG_INIT (&ioQueueConfig, WdfIoQueueDispatchManual); __analysis_assume(ioQueueConfig.EvtIoStop != 0); ntStatus = WdfIoQueueCreate ( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->BusResetRequestsQueue); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Error Creating Reset Request Queue %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate (&lockAttributes,&deviceExtension->CromSpinLock); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate CromSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate ( &lockAttributes, &deviceExtension->AsyncSpinLock); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate AsyncSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate ( &lockAttributes, &deviceExtension->IsochSpinLock ); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate IsochSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate ( &lockAttributes, &deviceExtension->IsochResourceSpinLock); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate IsochResourceSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } InitializeListHead (&deviceExtension->CromData); InitializeListHead (&deviceExtension->AsyncAddressData); InitializeListHead (&deviceExtension->IsochDetachData); InitializeListHead (&deviceExtension->IsochResourceData); ExitS(ntStatus); return(ntStatus); } // kmdf1394_PnpAddDevice
VOID GetDeviceEventLoggingNames( __in WDFDEVICE Device ) /*++ Routine Description: Retrieve the friendly name and the location string into WDFMEMORY objects and store them in the device context. Arguments: Return Value: NT status --*/ { PDEVICE_CONTEXT pDevContext = GetDeviceContext(Device); WDF_OBJECT_ATTRIBUTES objectAttributes; WDFMEMORY deviceNameMemory = NULL; WDFMEMORY locationMemory = NULL; NTSTATUS status; PAGED_CODE(); // // We want both memory objects to be children of the device so they will // be deleted automatically when the device is removed. // WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); objectAttributes.ParentObject = Device; // // First get the length of the string. If the FriendlyName // is not there then get the lenght of device description. // status = WdfDeviceAllocAndQueryProperty(Device, DevicePropertyFriendlyName, NonPagedPool, &objectAttributes, &deviceNameMemory); if (!NT_SUCCESS(status)) { status = WdfDeviceAllocAndQueryProperty(Device, DevicePropertyDeviceDescription, NonPagedPool, &objectAttributes, &deviceNameMemory); } if (NT_SUCCESS(status)) { pDevContext->DeviceNameMemory = deviceNameMemory; pDevContext->DeviceName = WdfMemoryGetBuffer(deviceNameMemory, NULL); } else { pDevContext->DeviceNameMemory = NULL; pDevContext->DeviceName = L"(error retrieving name)"; } // // Retrieve the device location string. // status = WdfDeviceAllocAndQueryProperty(Device, DevicePropertyLocationInformation, NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, &locationMemory); if (NT_SUCCESS(status)) { pDevContext->LocationMemory = locationMemory; pDevContext->Location = WdfMemoryGetBuffer(locationMemory, NULL); } else { pDevContext->LocationMemory = NULL; pDevContext->Location = L"(error retrieving location)"; } return; }
NTSTATUS kmdf1394_GetLocalHostInformation( IN WDFDEVICE Device, IN WDFREQUEST Request, IN OUT PGET_LOCAL_HOST_INFORMATION GetLocalHostInfo) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device); PIRB pIrb = NULL; GET_LOCAL_HOST_INFO7 LocalHostInfo7 = {0}; GET_LOCAL_HOST_INFO6 LocalHostInfo6 = {0}; GET_LOCAL_HOST_INFO5 LocalHostInfo5 = {0}; ENTER("kmdf1394_GetLocalHostInformation"); TRACE(TL_TRACE, ("nLevel = 0x%x\n", GetLocalHostInfo->nLevel)); TRACE(TL_TRACE, ("Information = 0x%x\n", GetLocalHostInfo->Information)); pIrb = ExAllocatePoolWithTag (NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV); if (!pIrb) { TRACE(TL_ERROR, ("Failed to allocate pIrb!\n")); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory (pIrb, sizeof (IRB)); pIrb->FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO; pIrb->Flags = 0; pIrb->u.GetLocalHostInformation.nLevel = GetLocalHostInfo->nLevel; switch (GetLocalHostInfo->nLevel) { case GET_HOST_DMA_CAPABILITIES: { // // need to ensure that no one passed us an GET_LOCAL_HOST_INFO7 // structure that just piggy backed on the // GET_LOCAL_HOST_INFORMATION struct, if they did this will cause // data misalignment errors in 64 bit because 1394bus will be expecting that structure to // be aligned correctly // RtlCopyMemory (&LocalHostInfo7, GetLocalHostInfo->Information, sizeof (GET_LOCAL_HOST_INFO7)); pIrb->u.GetLocalHostInformation.Information = &LocalHostInfo7; TRACE( TL_TRACE, ("HostDmaCapabilities = 0x%p\n", LocalHostInfo7.HostDmaCapabilities)); TRACE(TL_TRACE, ("MaxDmaBufferSize High = 0x%x\n", LocalHostInfo7.MaxDmaBufferSize.HighPart)); TRACE(TL_TRACE, ("MaxDmaBufferSize Low = 0x%x\n", LocalHostInfo7.MaxDmaBufferSize.LowPart)); } break; case GET_HOST_CSR_CONTENTS: { LocalHostInfo6.CsrBaseAddress.Off_High = \ ((PGET_LOCAL_HOST_INFO6)GetLocalHostInfo->Information)->CsrBaseAddress.Off_High; LocalHostInfo6.CsrBaseAddress.Off_Low = \ ((PGET_LOCAL_HOST_INFO6)GetLocalHostInfo->Information)->CsrBaseAddress.Off_Low; LocalHostInfo6.CsrDataLength = \ ((PGET_LOCAL_HOST_INFO6)GetLocalHostInfo->Information)->CsrDataLength; // // Pointer math needed to correct size differential between // data structures on WIN64 only LocalHostInfo6.CsrDataBuffer // is UCHAR @ 4 bytes, Information->CsrDataBuffer is a PVIOD // @ 8 bytes // LocalHostInfo6.CsrDataBuffer = \ ((PCHAR)&(((PGET_LOCAL_HOST_INFO6)GetLocalHostInfo->Information)->CsrDataLength)) \ + sizeof (ULONG); pIrb->u.GetLocalHostInformation.Information = &LocalHostInfo6; TRACE(TL_TRACE, ("CsrBaseAddress.Off_High = 0x%x\n", LocalHostInfo6.CsrBaseAddress.Off_High)); TRACE(TL_TRACE, ("CsrBaseAddress.Off_Low = 0x%x\n", LocalHostInfo6.CsrBaseAddress.Off_Low)); TRACE(TL_TRACE, ("CsrDataLength = 0x%x\n", LocalHostInfo6.CsrDataLength)); TRACE(TL_TRACE, ("CsrDataBuffer = 0x%p\n", LocalHostInfo6.CsrDataBuffer)); } break; case GET_HOST_CONFIG_ROM: { // // need to ensure that no one passed us an GET_LOCAL_HOST_INFO5 // structure that just piggy backed on the // GET_LOCAL_HOST_INFORMATION struct, if they did this will cause // data misalignment errors in 64 bit because 1394bus will be expecting that structure to // be aligned correctly // RtlCopyMemory (&LocalHostInfo5, GetLocalHostInfo->Information, sizeof (GET_LOCAL_HOST_INFO5)); pIrb->u.GetLocalHostInformation.Information = &LocalHostInfo5; TRACE(TL_TRACE, ("ConfigRom = 0x%p\n", LocalHostInfo5.ConfigRom)); TRACE( TL_TRACE, ("ConfigRomLength = 0x%x\n", LocalHostInfo5.ConfigRomLength)); } break; default: { pIrb->u.GetLocalHostInformation.Information = \ GetLocalHostInfo->Information; } break; }// switch ntStatus = kmdf1394_SubmitIrpSynch( deviceExtension->StackIoTarget, Request, pIrb); if (!NT_SUCCESS (ntStatus)) { if (STATUS_INVALID_BUFFER_SIZE == ntStatus) { // // we have to set status=success, otherwise, we don't get // the size value passed up to ring 3. // ntStatus = STATUS_SUCCESS; GetLocalHostInfo->Status = 122; TRACE( TL_WARNING, ("Invalid Buffer Size. nLevel = 0x%x\n", GetLocalHostInfo->nLevel)); // // see if it's a config rom request or a csr request // if (GET_HOST_CONFIG_ROM == GetLocalHostInfo->nLevel) { // // it is, lets print out the size // TRACE( TL_TRACE, ("ConfigRomLength = 0x%x\n", LocalHostInfo5.ConfigRomLength)); // // need to set this in the information struct we were passed down // RtlCopyMemory( GetLocalHostInfo->Information, &LocalHostInfo5, sizeof (GET_LOCAL_HOST_INFO5)); } else if (GET_HOST_CSR_CONTENTS == GetLocalHostInfo->nLevel) { // // csr, print out size // TRACE( TL_TRACE, ("CsrDataLength needed = 0x%x\n", LocalHostInfo6.CsrDataLength)); // // need to set this in the information struct we were passed down // ((PGET_LOCAL_HOST_INFO6)GetLocalHostInfo->Information)->CsrDataLength = \ LocalHostInfo6.CsrDataLength; } else if (GET_HOST_DMA_CAPABILITIES == GetLocalHostInfo->nLevel) { // // copy the results of the struct passed down // RtlCopyMemory( GetLocalHostInfo->Information, &LocalHostInfo7, sizeof (GET_LOCAL_HOST_INFO7)); } } // if (STATUS_INVALID_BUFFER_SIZE == ntStatus) else { TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", ntStatus)); } } // if (!NT_SUCCESS (ntStatus)) else { GetLocalHostInfo->Status = 0; if (GET_HOST_UNIQUE_ID == GetLocalHostInfo->nLevel) { PGET_LOCAL_HOST_INFO1 LocalHostInfo1; LocalHostInfo1 = (PGET_LOCAL_HOST_INFO1)GetLocalHostInfo->Information; TRACE(TL_TRACE, ("UniqueId.LowPart = 0x%x\n", LocalHostInfo1->UniqueId.LowPart)); TRACE(TL_TRACE, ("UniqueId.HighPart = 0x%x\n", LocalHostInfo1->UniqueId.HighPart)); } else if (GET_HOST_CAPABILITIES == GetLocalHostInfo->nLevel) { PGET_LOCAL_HOST_INFO2 LocalHostInfo2; LocalHostInfo2 = (PGET_LOCAL_HOST_INFO2)GetLocalHostInfo->Information; TRACE(TL_TRACE, ("HostCapabilities = 0x%x\n", LocalHostInfo2->HostCapabilities)); TRACE(TL_TRACE, ("MaxAsyncReadRequest = 0x%x\n", LocalHostInfo2->MaxAsyncReadRequest)); TRACE(TL_TRACE, ("MaxAsyncWriteRequest = 0x%x\n", LocalHostInfo2->MaxAsyncWriteRequest)); } else if (GET_POWER_SUPPLIED == GetLocalHostInfo->nLevel) { PGET_LOCAL_HOST_INFO3 LocalHostInfo3; LocalHostInfo3 = (PGET_LOCAL_HOST_INFO3)GetLocalHostInfo->Information; TRACE(TL_TRACE, ("deciWattsSupplied = 0x%x\n", LocalHostInfo3->deciWattsSupplied)); TRACE(TL_TRACE, ("Voltage = 0x%x\n", LocalHostInfo3->Voltage)); } else if (GET_PHYS_ADDR_ROUTINE == GetLocalHostInfo->nLevel) { PGET_LOCAL_HOST_INFO4 LocalHostInfo4; LocalHostInfo4 = (PGET_LOCAL_HOST_INFO4)GetLocalHostInfo->Information; TRACE(TL_TRACE, ("Context = 0x%x\n", LocalHostInfo4->Context)); } else if (GET_HOST_CONFIG_ROM == GetLocalHostInfo->nLevel) { PGET_LOCAL_HOST_INFO5 pLocalHostInfo5; pLocalHostInfo5 = \ (PGET_LOCAL_HOST_INFO5)GetLocalHostInfo->Information; TRACE( TL_TRACE, ("ConfigRomLength = 0x%x\n", pLocalHostInfo5->ConfigRomLength)); } else if (GET_HOST_DMA_CAPABILITIES == GetLocalHostInfo->nLevel) { // // need to copy the results back into the original address space passed in // TRACE(TL_TRACE, ("HostDmaCapabilities = 0x%x\n", LocalHostInfo7.HostDmaCapabilities)); TRACE(TL_TRACE, ("MaxDmaBufferSize Low = 0x%x\n", LocalHostInfo7.MaxDmaBufferSize.LowPart)); TRACE(TL_TRACE, ("MaxDmaBufferSize High = 0x%x\n", LocalHostInfo7.MaxDmaBufferSize.HighPart)); RtlCopyMemory(GetLocalHostInfo->Information, &LocalHostInfo7, sizeof (GET_LOCAL_HOST_INFO7)); } else { TRACE( TL_WARNING, ("Returned success on invalid nLevel = 0x%x\n", GetLocalHostInfo->nLevel)); } } ExFreePoolWithTag(pIrb, POOLTAG_KMDF_VDEV); EXIT("kmdf1394_GetLocalHostInformation", ntStatus); return ntStatus; } // kmdf1394_GetLocalHostInformation
NTSTATUS OnPrepareHardware( _In_ WDFDEVICE FxDevice, _In_ WDFCMRESLIST FxResourcesRaw, _In_ WDFCMRESLIST FxResourcesTranslated ) /*++ Routine Description: This routine caches the SPB resource connection ID. Arguments: FxDevice - a handle to the framework device object FxResourcesRaw - list of translated hardware resources that the PnP manager has assigned to the device FxResourcesTranslated - list of raw hardware resources that the PnP manager has assigned to the device Return Value: Status --*/ { FuncEntry(TRACE_FLAG_WDFLOADING); PDEVICE_CONTEXT pDevice = GetDeviceContext(FxDevice); BOOLEAN fSpbResourceFound = FALSE; NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; UNREFERENCED_PARAMETER(FxResourcesRaw); // // Parse the peripheral's resources. // ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); for (ULONG i = 0; i < resourceCount; i++) { PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; UCHAR Class; UCHAR Type; pDescriptor = WdfCmResourceListGetDescriptor( FxResourcesTranslated, i); switch (pDescriptor->Type) { case CmResourceTypeConnection: // // Look for I2C or SPI resource and save connection ID. // Class = pDescriptor->u.Connection.Class; Type = pDescriptor->u.Connection.Type; if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) { if (fSpbResourceFound == FALSE) { status = STATUS_SUCCESS; pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart; pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart; fSpbResourceFound = TRUE; Trace( TRACE_LEVEL_INFORMATION, TRACE_FLAG_WDFLOADING, "SPB resource found with ID=0x%llx", pDevice->I2CContext.I2cResHubId.QuadPart); } else { Trace( TRACE_LEVEL_WARNING, TRACE_FLAG_WDFLOADING, "Duplicate SPB resource found with ID=0x%llx", pDevice->I2CContext.I2cResHubId.QuadPart); } } break; default: // // Ignoring all other resource types. // break; } } // // An SPB resource is required. // if (fSpbResourceFound == FALSE) { status = STATUS_NOT_FOUND; Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "SPB resource not found - %!STATUS!", status); } status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error in Spb initialization - %!STATUS!", status); return status; } FuncExit(TRACE_FLAG_WDFLOADING); return status; }