// ========================================================================= NTSTATUS QueueIRPToThread( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION devExt; NTSTATUS status; PIO_STACK_LOCATION irpSp; DEBUGOUTHASHDRV(DEBUGLEV_ENTER, ("QueueIrpToThread\n")); devExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; status = STATUS_PENDING; // Note: IoCsqInsertIrp marks the IRP pending. IoCsqInsertIrp(&devExt->CancelSafeQueue, Irp, NULL); // A semaphore remains signaled as long as its count is greater than // zero, and non-signaled when the count is zero. Following function // increments the semaphore count by 1. KeReleaseSemaphore( &devExt->IRPQueueSemaphore, 0, // No priority boost 1, // Increment semaphore by 1 FALSE // No WaitForXxx after this call ); DEBUGOUTHASHDRV(DEBUGLEV_EXIT, ("QueueIrpToThread\n")); return status; }
NTSTATUS NTAPI DispatchReadWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp) { /* According to the cancel sample in the DDK, IoCsqInsertIrp() marks the irp pending */ /* However, I think it's wrong. */ IoMarkIrpPending(Irp); IoCsqInsertIrp(&Csq, Irp, 0); return STATUS_PENDING; }
NTSTATUS FileRead(__in BASE_FILE * File, __in PIRP Irp, __in PIO_STACK_LOCATION IrpStack) { CSFBR_FILE_DATA *FileData = (CSFBR_FILE_DATA *) BaseFileGetPrivate(File); UNREFERENCED_PARAMETER(IrpStack); ASSERT(Irp->MdlAddress); TRACE_MSG(TRACE_LEVEL_INFO, TRACE_FLAG_DEFAULT, "Read %u bytes\n", IrpStack->Parameters.Write.Length); IoCsqInsertIrp(&FileData->csq, Irp, NULL); NotifyReceivedPacket(File); return STATUS_PENDING; }
NTSTATUS NTAPI ReadWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp) /* * FUNCTION: Dispatch routine called for read or write IRPs * ARGUMENTS: * RETURNS: * STATUS_PENDING if the IRP is queued * STATUS_INVALID_PARAMETER if IRP is set up wrong * NOTES: * - This function validates arguments to the IRP and then queues it * - Note that this function is implicitly serialized by the queue logic. Only * one of these at a time is active in the system, no matter how many processors * and threads we have. * - This function stores the DeviceObject in the IRP's context area before dropping * it onto the irp queue */ { TRACE_(FLOPPY, "ReadWrite called\n"); ASSERT(DeviceObject); ASSERT(Irp); if(!Irp->MdlAddress) { WARN_(FLOPPY, "ReadWrite(): MDL not found in IRP - Completing with STATUS_INVALID_PARAMETER\n"); Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INVALID_PARAMETER; } /* * Queue the irp to the thread. * The de-queue thread will look in DriverContext[0] for the Device Object. */ Irp->Tail.Overlay.DriverContext[0] = DeviceObject; IoCsqInsertIrp(&Csq, Irp, NULL); return STATUS_PENDING; }
NTSTATUS INTERNAL ReadReport( __in PDEVICE_EXTENSION DevExt, __in PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION irpsp = NULL; irpsp = IoGetCurrentIrpStackLocation(Irp); TEnter(Func,("(DevExt=%p,Irp=%p,IrpSp=%p)\n", DevExt, Irp, irpsp)); TAssert(Irp->UserBuffer != NULL); if (irpsp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(HID_INPUT_REPORT)) { status = STATUS_INVALID_BUFFER_SIZE; LogError(ERRLOG_INVALID_BUFFER_SIZE, status, UNIQUE_ERRID(0x60), NULL, NULL); TWarn(("invalid input report size (len=%d).\n", irpsp->Parameters.DeviceIoControl.OutputBufferLength)); } else { IoCsqInsertIrp(&DevExt->IrpQueue, Irp, NULL); status = STATUS_PENDING; } TExit(Func,("=%x\n", status)); return status; } //ReadReport
NTSTATUS USBPcapBufferHandleReadIrp(PIRP pIrp, PDEVICE_EXTENSION pDevExt, PUINT32 pBytesRead) { PDEVICE_EXTENSION pRootExt; PUSBPCAP_ROOTHUB_DATA pRootData; PVOID buffer; UINT32 bufferLength; UINT32 bytesRead; NTSTATUS status; KIRQL irql; PIO_STACK_LOCATION pStack = NULL; pStack = IoGetCurrentIrpStackLocation(pIrp); *pBytesRead = 0; if (pStack->Parameters.Read.Length == 0) { return STATUS_SUCCESS; } pRootExt = (PDEVICE_EXTENSION)pDevExt->context.control.pRootHubObject->DeviceExtension; pRootData = pRootExt->context.usb.pDeviceData->pRootData; if (pRootData->buffer == NULL) { return STATUS_UNSUCCESSFUL; } /* * Since control device has DO_DIRECT_IO bit set the MDL is already * probed and locked */ buffer = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); if (buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } else { bufferLength = MmGetMdlByteCount(pIrp->MdlAddress); } /* Get data from data queue, if there is no data we put * this IRP to Cancel-Safe queue and return status pending * otherwise complete this IRP then return SUCCESS */ KeAcquireSpinLock(&pRootData->bufferLock, &irql); bytesRead = USBPcapBufferRead(pRootData, buffer, bufferLength); KeReleaseSpinLock(&pRootData->bufferLock, irql); *pBytesRead = bytesRead; if (bytesRead == 0) { IoCsqInsertIrp(&pDevExt->context.control.ioCsq, pIrp, NULL); return STATUS_PENDING; } return STATUS_SUCCESS; }
NTSTATUS CsampRead( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Routine Description: Read disptach routine Arguments: DeviceObject - pointer to a device object. Irp - pointer to current Irp Return Value: NT status code. --*/ { NTSTATUS status; PDEVICE_EXTENSION devExtension; PIO_STACK_LOCATION irpStack; LARGE_INTEGER currentTime; PFILE_CONTEXT fileContext; PVOID readBuffer; BOOLEAN inCriticalRegion; PAGED_CODE(); CSAMP_KDPRINT(("CsampRead Enter:0x%p\n", Irp)); devExtension = DeviceObject->DeviceExtension; inCriticalRegion = FALSE; irpStack = IoGetCurrentIrpStackLocation(Irp); ASSERT(irpStack->FileObject != NULL); fileContext = irpStack->FileObject->FsContext; status = IoAcquireRemoveLock(&fileContext->FileRundownLock, Irp); if (!NT_SUCCESS(status)) { // // Lock is in a removed state. That means we have already received // cleaned up request for this handle. // Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } // // First make sure there is enough room. // if (irpStack->Parameters.Read.Length < sizeof(INPUT_DATA)) { Irp->IoStatus.Status = status = STATUS_BUFFER_TOO_SMALL; Irp->IoStatus.Information = 0; IoReleaseRemoveLock(&fileContext->FileRundownLock, Irp); IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // // FOR TESTING: // Initialize the data to mod 2 of some random number. // With this value you can control the number of times the // Irp will be queued before completion. Check // CsampPollDevice routine to know how this works. // KeQuerySystemTime(¤tTime); readBuffer = Irp->AssociatedIrp.SystemBuffer; *((PULONG)readBuffer) = ((currentTime.LowPart/13)%2); // // To avoid the thread from being suspended after it has queued the IRP and // before it signalled the semaphore, we will enter critical region. // ASSERT(KeGetCurrentIrql() <= APC_LEVEL); KeEnterCriticalRegion(); inCriticalRegion = TRUE; // // Queue the IRP and return STATUS_PENDING after signalling the // polling thread. // Note: IoCsqInsertIrp marks the IRP pending. // IoCsqInsertIrp(&devExtension->CancelSafeQueue, Irp, NULL); // // Do not touch the IRP once it has been queued because another thread // could remove the IRP and complete it before this one gets to run. // // // A semaphore remains signaled as long as its count is greater than // zero, and non-signaled when the count is zero. Following function // increments the semaphore count by 1. // KeReleaseSemaphore(&devExtension->IrpQueueSemaphore, 0,// No priority boost 1,// Increment semaphore by 1 FALSE );// No WaitForXxx after this call if (inCriticalRegion == TRUE) { KeLeaveCriticalRegion(); } // // We don't hold the lock for IRP that's pending in the list because this // lock is meant to rundown currently dispatching threads when the cleanup // is handled. // IoReleaseRemoveLock(&fileContext->FileRundownLock, Irp); return STATUS_PENDING; }
NTSTATUS NTAPI USBPORT_HandleSubmitURB(IN PDEVICE_OBJECT PdoDevice, IN PIRP Irp, IN PURB Urb) { PUSBPORT_RHDEVICE_EXTENSION PdoExtension; PDEVICE_OBJECT FdoDevice; PUSBPORT_DEVICE_EXTENSION FdoExtension; USHORT Function; PUSBPORT_DEVICE_HANDLE DeviceHandle; NTSTATUS Status = STATUS_NOT_IMPLEMENTED; ASSERT(Urb); PdoExtension = PdoDevice->DeviceExtension; FdoDevice = PdoExtension->FdoDevice; FdoExtension = FdoDevice->DeviceExtension; Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; Urb->UrbHeader.UsbdFlags = 0; Function = Urb->UrbHeader.Function; if (Function > URB_FUNCTION_MAX) { Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_INVALID_URB_FUNCTION); DPRINT1("USBPORT_HandleSubmitURB: Unknown URB function - %x !!!\n", Function); return Status; } if (FdoExtension->TimerFlags & USBPORT_TMFLAG_RH_SUSPENDED) { DPRINT1("USBPORT_HandleSubmitURB: Bad Request\n"); USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_DEVICE_GONE); Irp->IoStatus.Status = STATUS_PENDING; IoMarkIrpPending(Irp); IoCsqInsertIrp(&FdoExtension->BadRequestIoCsq, Irp, NULL); return STATUS_PENDING; } DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle; if (!DeviceHandle) { DeviceHandle = &PdoExtension->DeviceHandle; Urb->UrbHeader.UsbdDeviceHandle = DeviceHandle; } if (!USBPORT_ValidateDeviceHandle(PdoExtension->FdoDevice, DeviceHandle)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid device handle\n"); Irp->IoStatus.Status = STATUS_PENDING; IoMarkIrpPending(Irp); IoCsqInsertIrp(&FdoExtension->BadRequestIoCsq, Irp, NULL); return STATUS_PENDING; } InterlockedIncrement(&DeviceHandle->DeviceHandleLock); DPRINT_URB("USBPORT_HandleSubmitURB: Function - 0x%02X, DeviceHandle - %p\n", Function, Urb->UrbHeader.UsbdDeviceHandle); switch (Function) { case URB_FUNCTION_ISOCH_TRANSFER: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_ISOCH_TRANSFER UNIMPLEMENTED. FIXME. \n"); break; case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: case URB_FUNCTION_CONTROL_TRANSFER: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, FALSE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleDataTransfers(Urb); break; case URB_FUNCTION_VENDOR_DEVICE: case URB_FUNCTION_VENDOR_INTERFACE: case URB_FUNCTION_VENDOR_ENDPOINT: case URB_FUNCTION_CLASS_DEVICE: case URB_FUNCTION_CLASS_INTERFACE: case URB_FUNCTION_CLASS_ENDPOINT: case URB_FUNCTION_CLASS_OTHER: case URB_FUNCTION_VENDOR_OTHER: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleVendorOrClass(Irp, Urb); break; case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE: case URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT: case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT: case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE: case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleGetSetDescriptor(Irp, Urb); break; case URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR (0x2A) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_INVALID_URB_FUNCTION); case URB_FUNCTION_GET_STATUS_FROM_DEVICE: case URB_FUNCTION_GET_STATUS_FROM_INTERFACE: case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT: case URB_FUNCTION_GET_STATUS_FROM_OTHER: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleGetStatus(Irp, Urb); break; case URB_FUNCTION_SELECT_CONFIGURATION: Status = USBPORT_HandleSelectConfiguration(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_SELECT_INTERFACE: Status = USBPORT_HandleSelectInterface(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_GET_CONFIGURATION: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleGetConfiguration(Urb); break; case URB_FUNCTION_GET_INTERFACE: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_INTERFACE (0x27) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_INVALID_URB_FUNCTION); case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: Status = USBPORT_SyncResetPipeAndClearStall(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_SYNC_RESET_PIPE: Status = USBPORT_ResetPipe(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_SYNC_CLEAR_STALL: Status = USBPORT_ClearStall(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_ABORT_PIPE: Status = USBPORT_AbortPipe(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_SET_FEATURE_TO_DEVICE: case URB_FUNCTION_SET_FEATURE_TO_INTERFACE: case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT: case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE: case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT: case URB_FUNCTION_CLEAR_FEATURE_TO_OTHER: case URB_FUNCTION_SET_FEATURE_TO_OTHER: Status = USBPORT_ValidateURB(FdoDevice, Irp, Urb, TRUE, TRUE); if (!NT_SUCCESS(Status)) { DPRINT1("USBPORT_HandleSubmitURB: Not valid URB\n"); break; } Status = USBPORT_HandleSetOrClearFeature(Urb); break; case URB_FUNCTION_GET_CURRENT_FRAME_NUMBER: Status = USBPORT_HandleGetCurrentFrame(PdoExtension->FdoDevice, Irp, Urb); break; case URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL (0x03) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED); case URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL (0x04) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED); case URB_FUNCTION_GET_FRAME_LENGTH: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_GET_FRAME_LENGTH (0x05) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED); case URB_FUNCTION_SET_FRAME_LENGTH: DPRINT1("USBPORT_HandleSubmitURB: URB_FUNCTION_SET_FRAME_LENGTH (0x06) NOT_SUPPORTED\n"); return USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_NOT_SUPPORTED); default: DPRINT1("USBPORT_HandleSubmitURB: Unknown URB Function - %x\n", Function); //URB_FUNCTION_RESERVED_0X0016 //URB_FUNCTION_RESERVE_0X001D //URB_FUNCTION_RESERVE_0X002B //URB_FUNCTION_RESERVE_0X002C //URB_FUNCTION_RESERVE_0X002D //URB_FUNCTION_RESERVE_0X002E //URB_FUNCTION_RESERVE_0X002F break; } if (Status == STATUS_PENDING) { return Status; } if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_ALLOCATED_TRANSFER) { PUSBPORT_TRANSFER Transfer; Transfer = Urb->UrbControlTransfer.hca.Reserved8[0]; Urb->UrbControlTransfer.hca.Reserved8[0] = NULL; Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_TRANSFER; ExFreePoolWithTag(Transfer, USB_PORT_TAG); } InterlockedDecrement(&DeviceHandle->DeviceHandleLock); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }