mirror of
https://github.com/reactos/reactos.git
synced 2024-09-12 13:54:41 +00:00
![Johannes Anderwald](/assets/img/avatar_default.png)
- Don't free device descriptor if it failed to acquire it - Don't move out of usb configuration array. Found by special pool - Fix bug when storing interface information which lead to a overwrite - Implement retrieving generic type for device - Fix bugs in QueryDeviceId - Implement querying hardware ids - Implement querying instance ids - With these changes, usbstor now initializes and create pdo, which is also enumerated - Needs more code / fixes so that disk.sys attaches to usbstor - WIP svn path=/branches/usb-bringup/; revision=51575
362 lines
7.3 KiB
C
362 lines
7.3 KiB
C
/*
|
|
* PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: drivers/usb/usbstor/misc.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"
|
|
|
|
//
|
|
// driver verifier
|
|
//
|
|
IO_COMPLETION_ROUTINE SyncForwardIrpCompletionRoutine;
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBSTOR_SyncForwardIrpCompletionRoutine(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp,
|
|
PVOID Context)
|
|
{
|
|
if (Irp->PendingReturned)
|
|
{
|
|
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
|
|
}
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBSTOR_SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
KEVENT Event;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// initialize event
|
|
//
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
//
|
|
// copy irp stack location
|
|
//
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
|
|
//
|
|
// set completion routine
|
|
//
|
|
IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
|
|
|
|
|
|
//
|
|
// call driver
|
|
//
|
|
Status = IoCallDriver(DeviceObject, Irp);
|
|
|
|
//
|
|
// check if pending
|
|
//
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
//
|
|
// wait for the request to finish
|
|
//
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
//
|
|
// copy status code
|
|
//
|
|
Status = Irp->IoStatus.Status;
|
|
}
|
|
|
|
//
|
|
// done
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBSTOR_GetBusInterface(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface)
|
|
{
|
|
KEVENT Event;
|
|
NTSTATUS Status;
|
|
PIRP Irp;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
PIO_STACK_LOCATION Stack;
|
|
|
|
//
|
|
// sanity checks
|
|
//
|
|
ASSERT(DeviceObject);
|
|
ASSERT(BusInterface);
|
|
|
|
|
|
//
|
|
// initialize event
|
|
//
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
|
|
//
|
|
// create irp
|
|
//
|
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
|
|
DeviceObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&Event,
|
|
&IoStatus);
|
|
|
|
//
|
|
// was irp built
|
|
//
|
|
if (Irp == NULL)
|
|
{
|
|
//
|
|
// no memory
|
|
//
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// initialize request
|
|
//
|
|
Stack=IoGetNextIrpStackLocation(Irp);
|
|
Stack->MajorFunction = IRP_MJ_PNP;
|
|
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
|
Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
|
|
Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&USB_BUS_INTERFACE_USBDI_GUID;
|
|
Stack->Parameters.QueryInterface.Version = 2;
|
|
Stack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
|
|
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
|
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
//
|
|
// call driver
|
|
//
|
|
Status= IoCallDriver(DeviceObject, Irp);
|
|
|
|
//
|
|
// did operation complete
|
|
//
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
//
|
|
// wait for completion
|
|
//
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
//
|
|
// collect status
|
|
//
|
|
Status=IoStatus.Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
USBSTOR_SyncUrbRequest(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
OUT PURB UrbRequest)
|
|
{
|
|
PIRP Irp;
|
|
PIO_STACK_LOCATION IoStack;
|
|
KEVENT Event;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// allocate irp
|
|
//
|
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
|
if (!Irp)
|
|
{
|
|
//
|
|
// no memory
|
|
//
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// initialize event
|
|
//
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
|
|
//
|
|
// get next stack location
|
|
//
|
|
IoStack = IoGetNextIrpStackLocation(Irp);
|
|
|
|
//
|
|
// initialize stack location
|
|
//
|
|
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
|
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
|
|
IoStack->Parameters.Others.Argument1 = (PVOID)UrbRequest;
|
|
IoStack->Parameters.DeviceIoControl.InputBufferLength = UrbRequest->UrbHeader.Length;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
//
|
|
// setup completion routine
|
|
//
|
|
IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
|
|
|
|
//
|
|
// call driver
|
|
//
|
|
Status = IoCallDriver(DeviceObject, Irp);
|
|
|
|
//
|
|
// check if request is pending
|
|
//
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
//
|
|
// wait for completion
|
|
//
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
//
|
|
// update status
|
|
//
|
|
Status = Irp->IoStatus.Status;
|
|
}
|
|
|
|
//
|
|
// free irp
|
|
//
|
|
IoFreeIrp(Irp);
|
|
|
|
//
|
|
// done
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
PVOID
|
|
AllocateItem(
|
|
IN POOL_TYPE PoolType,
|
|
IN ULONG ItemSize)
|
|
{
|
|
//
|
|
// allocate item
|
|
//
|
|
PVOID Item = ExAllocatePoolWithTag(PoolType, ItemSize, USB_STOR_TAG);
|
|
|
|
if (Item)
|
|
{
|
|
//
|
|
// zero item
|
|
//
|
|
RtlZeroMemory(Item, ItemSize);
|
|
}
|
|
|
|
//
|
|
// return element
|
|
//
|
|
return Item;
|
|
}
|
|
|
|
VOID
|
|
FreeItem(
|
|
IN PVOID Item)
|
|
{
|
|
//
|
|
// free item
|
|
//
|
|
ExFreePoolWithTag(Item, USB_STOR_TAG);
|
|
}
|
|
|
|
NTSTATUS
|
|
USBSTOR_GetMaxLUN(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PFDO_DEVICE_EXTENSION DeviceExtension)
|
|
{
|
|
PURB Urb;
|
|
PUCHAR Buffer;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// first allocate urb
|
|
//
|
|
Urb = (PURB)AllocateItem(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
|
|
if (!Urb)
|
|
{
|
|
//
|
|
// no memory
|
|
//
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// allocate 1-byte buffer
|
|
//
|
|
Buffer = (PUCHAR)AllocateItem(NonPagedPool, sizeof(UCHAR));
|
|
if (!Buffer)
|
|
{
|
|
//
|
|
// no memory
|
|
//
|
|
FreeItem(Buffer);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// initialize vendor request
|
|
//
|
|
Urb->UrbControlVendorClassRequest.Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
|
|
Urb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_CLASS_INTERFACE;
|
|
Urb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN;
|
|
Urb->UrbControlVendorClassRequest.TransferBufferLength = 1;
|
|
Urb->UrbControlVendorClassRequest.TransferBuffer = Buffer;
|
|
Urb->UrbControlVendorClassRequest.Request = USB_BULK_GET_MAX_LUN;
|
|
|
|
//
|
|
// submit request
|
|
//
|
|
Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
|
|
|
|
//
|
|
// free urb
|
|
//
|
|
FreeItem(Urb);
|
|
|
|
DPRINT1("MaxLUN: %x\n", *Buffer);
|
|
|
|
if (*Buffer > 0xF)
|
|
{
|
|
//
|
|
// invalid response documented in usb mass storage specification
|
|
//
|
|
Status = STATUS_DEVICE_DATA_ERROR;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// store maxlun
|
|
//
|
|
DeviceExtension->MaxLUN = *Buffer;
|
|
}
|
|
|
|
//
|
|
// free buffer
|
|
//
|
|
FreeItem(Buffer);
|
|
|
|
//
|
|
// done
|
|
//
|
|
return Status;
|
|
|
|
}
|