You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
9.8 KiB
363 lines
9.8 KiB
/*++
|
|
|
|
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;
|
|
}
|