VOID UsbSamp_EvtReadWriteWorkItem( _In_ WDFWORKITEM WorkItem ) { PWORKITEM_CONTEXT pItemContext; NTSTATUS status; UsbSamp_DbgPrint(3, ("ReadWriteWorkItem called\n")); pItemContext = GetWorkItemContext(WorkItem); status = ResetPipe(pItemContext->Pipe); if (!NT_SUCCESS(status)) { UsbSamp_DbgPrint(1, ("ResetPipe failed 0x%x\n", status)); status = ResetDevice(pItemContext->Device); if (!NT_SUCCESS(status)){ UsbSamp_DbgPrint(1, ("ResetDevice failed 0x%x\n", status)); } } WdfObjectDelete(WorkItem); return; }
// // Reset All Pipes // BOOL BOT_ResetAllPipes( PUSBMSC_DEVICE pUsbDevice ) { BOOL bRc = FALSE; DWORD dwErr; INIT_DT; DEBUGMSG(ZONE_TRACE,(TEXT("USBMSC>BOT_ResetAllPipes\n"))); START_DT // 0. reset endpoint 0 dwErr = ResetDefaultEndpoint(pUsbDevice->UsbFuncs, pUsbDevice->hUsbDevice); if ( ERROR_SUCCESS == dwErr ) { // 1. reset BulkIn endpoint if ( ResetPipe(pUsbDevice->UsbFuncs, pUsbDevice->BulkIn.hPipe, USB_NO_WAIT) ) { // 2. reset BulkOut endpoint if ( ResetPipe(pUsbDevice->UsbFuncs, pUsbDevice->BulkOut.hPipe, USB_NO_WAIT) ) { bRc = TRUE; } } } BOT_ResetEvent(pUsbDevice->hEP0Event); BOT_ResetEvent(pUsbDevice->BulkIn.hEvent); BOT_ResetEvent(pUsbDevice->BulkOut.hEvent); STOP_DT( TEXT("BOT_ResetAllPipes"), 10, pUsbDevice->Timeouts.Reset ); DEBUGMSG(ZONE_TRACE,(TEXT("USBMSC<BOT_ResetAllPipes:%d\n"), bRc)); return bRc; }
/*++ Routine Description: This event is called when the framework receives IRP_MJ_DEVICE_CONTROL requests from the system. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. OutputBufferLength - length of the request's output buffer, if an output buffer is available. InputBufferLength - length of the request's input buffer, if an input buffer is available. IoControlCode - the driver-defined or system-defined I/O control code (IOCTL) that is associated with the request. Return Value: VOID --*/ VOID PSDrv_EvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { WDFDEVICE device; PVOID ioBuffer; size_t bufLength; NTSTATUS status; PDEVICE_CONTEXT pDevContext; PFILE_CONTEXT pFileContext; ULONG length = 0; PSUSBDRV_PIPE_PROPERTY* pPipeProp; PSUSBDRV_CONTROL_TRANSFER* pControlTransfer; PSUSBDRV_DRIVER_VERSION* pDriverVersion; PSUSBDRV_INTERFACE_PROPERTY* pInterfaceProperty; unsigned int* pnDeviceSpeed; WDFMEMORY WdfMem = NULL; PUCHAR pControlBuffer; WDFMEMORY WdfMemOut = NULL; WDF_USB_INTERFACE_SELECT_SETTING_PARAMS selectSettingParams; UNREFERENCED_PARAMETER(InputBufferLength); PSDrv_DbgPrint(3, ("PSDrv_EvtIoDeviceControl - begins\n")); PAGED_CODE(); // initialize variables device = WdfIoQueueGetDevice(Queue); pDevContext = GetDeviceContext(device); switch(IoControlCode) { case IOCTL_PSDRV_RESET_PIPE: PSDrv_DbgPrint(3, ("IOControl: ResetPipe\n")); pFileContext = GetFileContext(WdfRequestGetFileObject(Request)); if (pFileContext->Pipe == NULL) { PSDrv_DbgPrint(3, ("Invalid pipe!\n")); status = STATUS_INVALID_PARAMETER; } else { status = ResetPipe(pFileContext->Pipe); } break; case IOCTL_PSDRV_ABORT_PIPE: PSDrv_DbgPrint(3, ("IOControl: AbortPipe\n")); pFileContext = GetFileContext(WdfRequestGetFileObject(Request)); if (pFileContext->Pipe == NULL) { PSDrv_DbgPrint(3, ("Invalid pipe!\n")); status = STATUS_INVALID_PARAMETER; } else { status = AbortPipe(pFileContext->Pipe); } break; case IOCTL_PSDRV_GET_CONFIG_DESCRIPTOR: PSDrv_DbgPrint(3, ("IOControl: GetConfigDescriptor\n")); if (pDevContext->UsbConfigurationDescriptor) { length = pDevContext->UsbConfigurationDescriptor->wTotalLength; status = WdfRequestRetrieveOutputBuffer(Request, length, &ioBuffer, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } RtlCopyMemory(ioBuffer, pDevContext->UsbConfigurationDescriptor, length); status = STATUS_SUCCESS; } else { PSDrv_DbgPrint(3, ("UsbConfigurationDescriptor is NULL!\n")); status = STATUS_INVALID_DEVICE_STATE; } break; case IOCTL_PSDRV_RESET_DEVICE: PSDrv_DbgPrint(3, ("IOControl: ResetDevice\n")); status = ResetDevice(device); break; case IOCTL_PSDRV_CONTROL_TRANSFER: PSDrv_DbgPrint(3, ("IOControl: ControlTransfer\n")); //Get a pointer to the input buffer status = WdfRequestRetrieveInputMemory(Request, &WdfMem); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMem == NULL) { PSDrv_DbgPrint(1, ("WdfMem is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pControlTransfer = WdfMemoryGetBuffer(WdfMem, NULL); if (pControlTransfer == NULL) { PSDrv_DbgPrint(1, ("pControlTransfer is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } //Get a pointer to the output buffer if (OutputBufferLength != 0) { status = WdfRequestRetrieveOutputMemory(Request, &WdfMemOut); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMemOut == NULL) { PSDrv_DbgPrint(1, ("WdfMemOut is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pControlBuffer = WdfMemoryGetBuffer(WdfMemOut, NULL); if (pControlBuffer == NULL) { PSDrv_DbgPrint(1, ("pControlBuffer is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } } else { PSDrv_DbgPrint(1, ("This control request has no buffer...\n")); pControlBuffer = NULL; } // Call the control transfer function status = ControlTransfer(pDevContext, pControlTransfer, pControlBuffer, OutputBufferLength, &length); break; case IOCTL_PSDRV_SET_PIPE_PROPERTY: PSDrv_DbgPrint(3, ("IOControl: SetPipeProperty\n")); status = WdfRequestRetrieveInputMemory(Request, &WdfMem); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMem == NULL) { PSDrv_DbgPrint(1, ("WdfMem is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pPipeProp = WdfMemoryGetBuffer(WdfMem, NULL); if (pPipeProp == NULL) { PSDrv_DbgPrint(1, ("pPipeProp is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pFileContext = GetFileContext(WdfRequestGetFileObject(Request)); if (pFileContext->Pipe == NULL) { PSDrv_DbgPrint(3, ("Invalid pipe!\n")); status = STATUS_INVALID_PARAMETER; } else { status = SetPipeProperty(pFileContext, pPipeProp); } break; case IOCTL_PSDRV_SET_INTERFACE: PSDrv_DbgPrint(3, ("IOControl: SetInterface\n")); status = WdfRequestRetrieveInputMemory(Request, &WdfMem); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMem == NULL) { PSDrv_DbgPrint(1, ("WdfMem is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pInterfaceProperty = WdfMemoryGetBuffer(WdfMem, NULL); if (pInterfaceProperty == NULL) { PSDrv_DbgPrint(1, ("pInterfaceProperty is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } PSDrv_DbgPrint(3, ("SetInterface: Going to change AltIF to %d...\n", pInterfaceProperty->nAltIF)); WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&selectSettingParams, pInterfaceProperty->nAltIF); status = WdfUsbInterfaceSelectSetting(pDevContext->UsbInterface, WDF_NO_OBJECT_ATTRIBUTES, &selectSettingParams); if (status == STATUS_SUCCESS) { pDevContext->nCurrIf = 0; pDevContext->nCurrAltIf = pInterfaceProperty->nAltIF; PSDrv_DbgPrint(3, ("SetInterface: AltIF is now %d...\n", pInterfaceProperty->nAltIF)); } break; case IOCTL_PSDRV_GET_INTERFACE: PSDrv_DbgPrint(3, ("IOControl: GetInterface\n")); length = sizeof(PSUSBDRV_INTERFACE_PROPERTY); status = WdfRequestRetrieveOutputBuffer(Request, length, &pInterfaceProperty, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } pInterfaceProperty->nIF = pDevContext->nCurrIf; pInterfaceProperty->nAltIF = pDevContext->nCurrAltIf; status = STATUS_SUCCESS; break; case IOCTL_PSDRV_GET_DRIVER_VERSION: PSDrv_DbgPrint(3, ("IOControl: GetDriverVersion\n")); length = sizeof(PSUSBDRV_DRIVER_VERSION); status = WdfRequestRetrieveOutputBuffer(Request, length, &pDriverVersion, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } pDriverVersion->nMajor = PSUSBDRV_MAJOR_VERSION; pDriverVersion->nMinor = PSUSBDRV_MINOR_VERSION; pDriverVersion->nMaintenance = PSUSBDRV_MAINTENANCE_VERSION; pDriverVersion->nBuild = PSUSBDRV_BUILD_VERSION; status = STATUS_SUCCESS; break; case IOCTL_PSDRV_GET_DEVICE_SPEED: PSDrv_DbgPrint(3, ("IOControl: GetDeviceSpeed\n")); length = sizeof(unsigned int); status = WdfRequestRetrieveOutputBuffer(Request, length, &pnDeviceSpeed, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (pDevContext->IsDeviceHighSpeed == TRUE) { *pnDeviceSpeed = PSUSBDRV_DEVICE_HIGH_SPEED; } else { *pnDeviceSpeed = PSUSBDRV_DEVICE_FULL_SPEED; } break; default: PSDrv_DbgPrint(3, ("Unknown IOControl! (ControlCode = %x)\n", IoControlCode)); status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation(Request, status, length); PSDrv_DbgPrint(3, ("PSDrv_EvtIoDeviceControl - ends\n")); return; }
VOID Rio500_EvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_DEVICE_CONTROL requests from the system. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. OutputBufferLength - length of the request's output buffer, if an output buffer is available. InputBufferLength - length of the request's input buffer, if an input buffer is available. IoControlCode - the driver-defined or system-defined I/O control code (IOCTL) that is associated with the request. Return Value: VOID --*/ { WDFDEVICE device; PVOID ioBuffer; PRIO_IOCTL_BLOCK ioBufferRio; size_t bufLength; NTSTATUS status; PDEVICE_CONTEXT pDevContext; ULONG length = 0; URB urb; PMDL pMdl = NULL; WDF_MEMORY_DESCRIPTOR memoryDesc; #ifdef _WIN64 BOOLEAN isWowRequest = FALSE; #endif // _WIN64 UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); Rio500_DbgPrint(3, ("Entered Rio500_DispatchDevCtrl\n")); PAGED_CODE(); // // initialize variables // device = WdfIoQueueGetDevice(Queue); pDevContext = GetDeviceContext(device); switch(IoControlCode) { case IOCTL_RIO500_RESET_PIPE: status = ResetPipe(pDevContext->ReadPipe); if (NT_SUCCESS(status)) { status = ResetPipe(pDevContext->WritePipe); } break; case IOCTL_RIO500_GET_CONFIG_DESCRIPTOR: if (pDevContext->UsbConfigurationDescriptor) { length = pDevContext->UsbConfigurationDescriptor->wTotalLength; status = WdfRequestRetrieveOutputBuffer(Request, length, &ioBuffer, &bufLength); if (!NT_SUCCESS(status)) { Rio500_DbgPrint(1, ("WdfRequestRetrieveInputBuffer failed\n")); break; } RtlCopyMemory(ioBuffer, pDevContext->UsbConfigurationDescriptor, length); status = STATUS_SUCCESS; } else { status = STATUS_INVALID_DEVICE_STATE; } break; case IOCTL_RIO500_RESET_DEVICE: status = ResetDevice(device); break; case IOCTL_RIO500_RIO_COMMAND: #ifdef _WIN64 if (IoIs32bitProcess(NULL)) { bufLength = sizeof(RIO_IOCTL_BLOCK) - sizeof(DWORD32); isWowRequest = TRUE; } else #endif // _WIN64 { bufLength = sizeof(RIO_IOCTL_BLOCK); } status = WdfRequestRetrieveInputBuffer( Request, bufLength, &ioBufferRio, NULL ); if (NT_SUCCESS(status)) { #ifdef _WIN64 if (isWowRequest) { ioBuffer = (PVOID)ioBufferRio->MsgData.DataWow; } else #endif // _WIN64 { ioBuffer = ioBufferRio->MsgData.Data; } if (ioBufferRio->MsgLength != 0 && ioBuffer != NULL) { pMdl = IoAllocateMdl( ioBuffer, ioBufferRio->MsgLength, FALSE, FALSE, NULL ); MmProbeAndLockPages(pMdl, (KPROCESSOR_MODE)KernelMode, IoModifyAccess); } memset(&urb, 0, sizeof(urb)); urb.UrbControlVendorClassRequest.Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); urb.UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE; urb.UrbControlVendorClassRequest.TransferBuffer = NULL; urb.UrbControlVendorClassRequest.RequestTypeReservedBits = 0x00; urb.UrbControlVendorClassRequest.TransferBufferLength = ioBufferRio->MsgLength; urb.UrbControlVendorClassRequest.TransferBufferMDL = pMdl; urb.UrbControlVendorClassRequest.Request = ioBufferRio->RequestCode; urb.UrbControlVendorClassRequest.Value = ioBufferRio->MsgValue; urb.UrbControlVendorClassRequest.Index = ioBufferRio->MsgIndex; urb.UrbControlVendorClassRequest.TransferFlags = USBD_SHORT_TRANSFER_OK; if (ioBufferRio->RequestType & 0x80) { urb.UrbControlVendorClassRequest.TransferFlags |= USBD_TRANSFER_DIRECTION_IN; } urb.UrbControlVendorClassRequest.UrbLink = NULL; WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDesc, &urb, sizeof(urb)); status = WdfIoTargetSendInternalIoctlOthersSynchronously( WdfDeviceGetIoTarget(device), Request, IOCTL_INTERNAL_USB_SUBMIT_URB, &memoryDesc, NULL, NULL, NULL, NULL ); if (pMdl != NULL) { MmUnlockPages(pMdl); IoFreeMdl(pMdl); } } break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation(Request, status, length); Rio500_DbgPrint(3, ("Exit Rio500_DispatchDevCtrl\n")); }