/*++ Copyright (c) Microsoft Corporation Module Name: OCRW.C Abstract: This source file contains the dispatch routines which handle opening, closing, reading, and writing to the device, i.e.: IRP_MJ_CREATE IRP_MJ_CLOSE IRP_MJ_READ IRP_MJ_WRITE Environment: kernel mode Revision History: Sept 01 : KenRay --*/ //***************************************************************************** // I N C L U D E S //***************************************************************************** #include "genusb.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, GenUSB_Create) #pragma alloc_text(PAGE, GenUSB_Close) #pragma alloc_text(PAGE, GenUSB_Read) #pragma alloc_text(PAGE, GenUSB_Write) #endif //****************************************************************************** // // GenUSB_Create() // // Dispatch routine which handles IRP_MJ_CREATE // //****************************************************************************** NTSTATUS GenUSB_Create ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION deviceExtension; NTSTATUS status; DBGPRINT(2, ("enter: GenUSB_Create\n")); DBGFBRK(DBGF_BRK_CREATE); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; LOGENTRY(deviceExtension, 'CREA', DeviceObject, Irp, 0); status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp); if (!NT_SUCCESS(status)) { Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // While there are several readers of the IsStarted state, it is only // set at the end of GenUSB_StartDevice. if (!deviceExtension->IsStarted) { LOGENTRY(deviceExtension, 'IOns', DeviceObject, Irp, 0); status = STATUS_DEVICE_NOT_CONNECTED; } else if (1 != InterlockedIncrement (&deviceExtension->OpenedCount)) { InterlockedDecrement (&deviceExtension->OpenedCount); status = STATUS_SHARING_VIOLATION; } else { status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; } IoReleaseRemoveLock (&deviceExtension->RemoveLock, Irp); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); DBGPRINT(2, ("exit: GenUSB_Create\n")); LOGENTRY(deviceExtension, 'crea', 0, 0, 0); return status; } //****************************************************************************** // // GenUSB_Close() // // Dispatch routine which handles IRP_MJ_CLOSE // //****************************************************************************** NTSTATUS GenUSB_Close ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION deviceExtension; // // Never check the remove lock, or started for close. // DBGPRINT(2, ("enter: GenUSB_Close\n")); DBGFBRK(DBGF_BRK_CLOSE); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; LOGENTRY(deviceExtension, 'CLOS', DeviceObject, Irp, 0); GenUSB_DeselectConfiguration (deviceExtension, TRUE); InterlockedDecrement (&deviceExtension->OpenedCount); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DBGPRINT(2, ("exit: GenUSB_Close\n")); LOGENTRY(deviceExtension, 'clos', 0, 0, 0); return STATUS_SUCCESS; } //****************************************************************************** // // GenUSB_ReadWrite() // // Dispatch routine which handles IRP_MJ_READ and IRP_MJ_WRITE // //****************************************************************************** NTSTATUS GenUSB_ReadComplete ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Unused, IN USBD_STATUS UrbStatus, IN ULONG Length ) { PDEVICE_EXTENSION deviceExtension; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; LOGENTRY(deviceExtension, 'RedC', Irp, Length, UrbStatus); IoReleaseRemoveLock (&deviceExtension->RemoveLock, Irp); Irp->IoStatus.Information = Length; return Irp->IoStatus.Status; } NTSTATUS GenUSB_Read ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS status; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpSp; DBGPRINT(2, ("enter: GenUSB_Read\n")); DBGFBRK(DBGF_BRK_READWRITE); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; LOGENTRY(deviceExtension, 'R ', DeviceObject, Irp, 0); status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp); if (!NT_SUCCESS(status)) { Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // While there are several readers of the IsStarted state, it is only // set at the end of GenUSB_StartDevice. if (!deviceExtension->IsStarted) { LOGENTRY(deviceExtension, 'IOns', DeviceObject, Irp, 0); status = STATUS_DEVICE_NOT_CONNECTED; goto GenUSB_ReadReject; } irpSp = IoGetCurrentIrpStackLocation (Irp); if (0 != irpSp->Parameters.Read.ByteOffset.QuadPart) { status = STATUS_NOT_IMPLEMENTED; goto GenUSB_ReadReject; } // // After talking extensively with JD, he tells me that I do not need // to queue requests for power downs or query stop. If that is the // case then even if the device power state isn't PowerDeviceD0 we // can still allow trasfers. This, of course, is a property of the // brand new port driver that went into XP. // // if (DeviceExtension->DevicePowerState != PowerDeviceD0) // { // } // // // BUGBUG if we ever implement IDLE, we need to turn the device // back on here. // return GenUSB_TransmitReceive ( deviceExtension, Irp, deviceExtension->ReadInterface, deviceExtension->ReadPipe, USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, NULL, Irp->MdlAddress, irpSp->Parameters.Read.Length, NULL, GenUSB_ReadComplete); GenUSB_ReadReject: Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); IoReleaseRemoveLock (&deviceExtension->RemoveLock, Irp); DBGPRINT(2, ("exit: GenUSB_Read %08X\n", status)); LOGENTRY(deviceExtension, 'r ', status, 0, 0); return status; } NTSTATUS GenUSB_WriteComplete ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Unused, IN USBD_STATUS UrbStatus, IN ULONG Length ) { PDEVICE_EXTENSION deviceExtension; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; LOGENTRY(deviceExtension, 'WrtC', Irp, Length, UrbStatus); IoReleaseRemoveLock (&deviceExtension->RemoveLock, Irp); Irp->IoStatus.Information = Length; return Irp->IoStatus.Status; } NTSTATUS GenUSB_Write ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS status; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpSp; DBGPRINT(2, ("enter: GenUSB_Write\n")); DBGFBRK(DBGF_BRK_READWRITE); deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; LOGENTRY(deviceExtension, 'W ', DeviceObject, Irp, 0); status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp); if (!NT_SUCCESS(status)) { Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // While there are several readers of the IsStarted state, it is only // set at the end of GenUSB_StartDevice. if (!deviceExtension->IsStarted) { LOGENTRY(deviceExtension, 'IOns', DeviceObject, Irp, 0); status = STATUS_DEVICE_NOT_CONNECTED; goto GenUSB_WriteReject; } irpSp = IoGetCurrentIrpStackLocation (Irp); if (0 != irpSp->Parameters.Write.ByteOffset.QuadPart) { status = STATUS_NOT_IMPLEMENTED; goto GenUSB_WriteReject; } // // After talking extensively with JD, he tells me that I do not need // to queue requests for power downs or query stop. If that is the // case then even if the device power state isn't PowerDeviceD0 we // can still allow trasfers. This, of course, is a property of the // brand new port driver that went into XP. // // if (DeviceExtension->DevicePowerState != PowerDeviceD0) // { // } // // // BUGBUG if we ever implement IDLE, we need to turn the device // back on here. // return GenUSB_TransmitReceive ( deviceExtension, Irp, deviceExtension->WriteInterface, deviceExtension->WritePipe, USBD_TRANSFER_DIRECTION_OUT, NULL, Irp->MdlAddress, irpSp->Parameters.Read.Length, NULL, GenUSB_WriteComplete); GenUSB_WriteReject: Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); IoReleaseRemoveLock (&deviceExtension->RemoveLock, Irp); DBGPRINT(2, ("exit: GenUSB_Write %08X\n", status)); LOGENTRY(deviceExtension, 'w ', status, 0, 0); return status; }