mirror of
https://github.com/reactos/reactos.git
synced 2024-11-02 21:09:15 +00:00
332 lines
8.5 KiB
C
332 lines
8.5 KiB
C
|
/*
|
||
|
* PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
|
||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||
|
* FILE: drivers/usb/usbstor/fdo.c
|
||
|
* PURPOSE: USB block storage device driver.
|
||
|
* PROGRAMMERS:
|
||
|
* James Tabor
|
||
|
* Michael Martin (michael.martin@reactos.org)
|
||
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||
|
*/
|
||
|
|
||
|
#include "usbstor.h"
|
||
|
|
||
|
VOID
|
||
|
USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
|
||
|
{
|
||
|
DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
|
||
|
DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
|
||
|
DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
|
||
|
DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
|
||
|
DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
|
||
|
DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
|
||
|
DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
|
||
|
DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
|
||
|
DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
|
||
|
DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
|
||
|
DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
|
||
|
DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
|
||
|
DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
|
||
|
DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
|
||
|
DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
USBSTOR_FdoHandleDeviceRelations(
|
||
|
IN PFDO_DEVICE_EXTENSION DeviceExtension,
|
||
|
IN OUT PIRP Irp)
|
||
|
{
|
||
|
ULONG DeviceCount = 0;
|
||
|
ULONG Index;
|
||
|
PDEVICE_RELATIONS DeviceRelations;
|
||
|
PIO_STACK_LOCATION IoStack;
|
||
|
|
||
|
//
|
||
|
// get current irp stack location
|
||
|
//
|
||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||
|
|
||
|
//
|
||
|
// check if relation type is BusRelations
|
||
|
//
|
||
|
if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
|
||
|
{
|
||
|
//
|
||
|
// FDO always only handles bus relations
|
||
|
//
|
||
|
return USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// go through array and count device objects
|
||
|
//
|
||
|
for(Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
|
||
|
{
|
||
|
if (DeviceExtension->ChildPDO[Index])
|
||
|
{
|
||
|
//
|
||
|
// child pdo
|
||
|
//
|
||
|
DeviceCount++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// allocate device relations
|
||
|
//
|
||
|
DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
|
||
|
if (!DeviceRelations)
|
||
|
{
|
||
|
//
|
||
|
// no memory
|
||
|
//
|
||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// add device objects
|
||
|
//
|
||
|
for(Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
|
||
|
{
|
||
|
if (DeviceExtension->ChildPDO[Index])
|
||
|
{
|
||
|
//
|
||
|
// store child pdo
|
||
|
//
|
||
|
DeviceRelations->Objects[DeviceRelations->Count] = DeviceExtension->ChildPDO[Index];
|
||
|
|
||
|
//
|
||
|
// add reference
|
||
|
//
|
||
|
ObReferenceObject(DeviceExtension->ChildPDO[Index]);
|
||
|
|
||
|
//
|
||
|
// increment count
|
||
|
//
|
||
|
DeviceRelations->Count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// store result
|
||
|
//
|
||
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
||
|
|
||
|
//
|
||
|
// request completed successfully
|
||
|
//
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
USBSTOR_FdoHandleStartDevice(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PFDO_DEVICE_EXTENSION DeviceExtension,
|
||
|
IN OUT PIRP Irp)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
UCHAR Index = 0;
|
||
|
|
||
|
//
|
||
|
// forward irp to lower device
|
||
|
//
|
||
|
Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// failed to start
|
||
|
//
|
||
|
DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// first get device & configuration & string descriptor
|
||
|
//
|
||
|
Status = USBSTOR_GetDescriptors(DeviceObject);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// failed to get device descriptor
|
||
|
//
|
||
|
DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// dump device descriptor
|
||
|
//
|
||
|
USBSTOR_DumpDeviceDescriptor(DeviceExtension->DeviceDescriptor);
|
||
|
|
||
|
//
|
||
|
// now select an interface
|
||
|
//
|
||
|
Status = USBSTOR_SelectConfigurationAndInterface(DeviceObject, DeviceExtension);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// failed to get device descriptor
|
||
|
//
|
||
|
DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// check if we got a bulk in + bulk out endpoint
|
||
|
//
|
||
|
Status = USBSTOR_GetPipeHandles(DeviceExtension);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// failed to get pipe handles descriptor
|
||
|
//
|
||
|
DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get num of lun which are supported
|
||
|
//
|
||
|
Status = USBSTOR_GetMaxLUN(DeviceExtension->LowerDeviceObject, DeviceExtension);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// failed to get max LUN
|
||
|
//
|
||
|
DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// now create for each LUN a device object, 1 minimum
|
||
|
//
|
||
|
do
|
||
|
{
|
||
|
//
|
||
|
// create pdo
|
||
|
//
|
||
|
Status = USBSTOR_CreatePDO(DeviceObject, &DeviceExtension->ChildPDO[Index]);
|
||
|
|
||
|
//
|
||
|
// check for failure
|
||
|
//
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// failed to create child pdo
|
||
|
//
|
||
|
DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index, Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// increment pdo index
|
||
|
//
|
||
|
Index++;
|
||
|
|
||
|
}while(Index < DeviceExtension->MaxLUN);
|
||
|
|
||
|
//
|
||
|
// finally get usb device interface
|
||
|
//
|
||
|
Status = USBSTOR_GetBusInterface(DeviceExtension->LowerDeviceObject, &DeviceExtension->BusInterface);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
//
|
||
|
// failed to device interface
|
||
|
//
|
||
|
DPRINT1("USBSTOR_FdoHandleStartDevice failed to device interface %x\n", Status);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// fdo is now initialized
|
||
|
//
|
||
|
DPRINT1("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
USBSTOR_FdoHandlePnp(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN OUT PIRP Irp)
|
||
|
{
|
||
|
PIO_STACK_LOCATION IoStack;
|
||
|
PFDO_DEVICE_EXTENSION DeviceExtension;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
//
|
||
|
// get current stack location
|
||
|
//
|
||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||
|
|
||
|
//
|
||
|
// get device extension
|
||
|
//
|
||
|
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||
|
|
||
|
//
|
||
|
// sanity check
|
||
|
//
|
||
|
ASSERT(DeviceExtension->Common.IsFDO);
|
||
|
|
||
|
switch(IoStack->MinorFunction)
|
||
|
{
|
||
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||
|
{
|
||
|
Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
|
||
|
break;
|
||
|
}
|
||
|
case IRP_MN_STOP_DEVICE:
|
||
|
DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
|
||
|
Status = STATUS_NOT_SUPPORTED;
|
||
|
break;
|
||
|
case IRP_MN_REMOVE_DEVICE:
|
||
|
DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_REMOVE_DEVICE unimplemented\n");
|
||
|
Status = STATUS_NOT_SUPPORTED;
|
||
|
break;
|
||
|
case IRP_MN_QUERY_CAPABILITIES:
|
||
|
{
|
||
|
//
|
||
|
// just forward irp to lower device
|
||
|
//
|
||
|
Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
|
||
|
break;
|
||
|
}
|
||
|
case IRP_MN_START_DEVICE:
|
||
|
{
|
||
|
Status = USBSTOR_FdoHandleStartDevice(DeviceObject, DeviceExtension, Irp);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// forward irp to next device object
|
||
|
//
|
||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||
|
return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// complete request
|
||
|
//
|
||
|
if (Status != STATUS_PENDING)
|
||
|
{
|
||
|
//
|
||
|
// store result
|
||
|
//
|
||
|
Irp->IoStatus.Status = Status;
|
||
|
|
||
|
//
|
||
|
// complete request
|
||
|
//
|
||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// done processing
|
||
|
//
|
||
|
return Status;
|
||
|
}
|