mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
[USBEHCI_NEW]
- Remove function declaration [USBSTOR] - Start on usbstor driver (USB Mass Storage Driver) - Implement reading device descriptor / configuration descriptor - Implement scanning of configuration descriptor for bulk in / bulk out endpoints - Implement selecting configuration and interface and verify selected interface - Implement reading max lun and create child device object for each lun - Handle PnP requests for functional device object - Implement support routines to send urb's to lower device object (usbhub) - Start implementing PDO routines svn path=/branches/usb-bringup/; revision=51563
This commit is contained in:
parent
bca978808b
commit
991d02daa5
10 changed files with 1750 additions and 126 deletions
|
@ -2,5 +2,5 @@
|
||||||
add_subdirectory(nt4compat)
|
add_subdirectory(nt4compat)
|
||||||
add_subdirectory(usbd)
|
add_subdirectory(usbd)
|
||||||
add_subdirectory(usbehci_new)
|
add_subdirectory(usbehci_new)
|
||||||
#add_subdirectory(usbhub) Compiles, just skipped in trunk
|
add_subdirectory(usbhub)
|
||||||
#add_subdirectory(usbstor) Compiles, just skipped in trunk
|
add_subdirectory(usbstor)
|
|
@ -44,7 +44,6 @@ public:
|
||||||
|
|
||||||
// local functions
|
// local functions
|
||||||
NTSTATUS CreateFDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
|
NTSTATUS CreateFDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
|
||||||
NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
|
|
||||||
NTSTATUS SetSymbolicLink(BOOLEAN Enable);
|
NTSTATUS SetSymbolicLink(BOOLEAN Enable);
|
||||||
|
|
||||||
// constructor / destructor
|
// constructor / destructor
|
||||||
|
|
|
@ -80,8 +80,11 @@ SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS
|
||||||
GetBusInterface(PDEVICE_OBJECT DeviceObject, PBUS_INTERFACE_STANDARD busInterface)
|
NTAPI
|
||||||
|
GetBusInterface(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PBUS_INTERFACE_STANDARD busInterface)
|
||||||
{
|
{
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
|
@ -3,8 +3,8 @@ add_definitions(-DDEBUG_MODE)
|
||||||
|
|
||||||
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
||||||
|
|
||||||
add_library(usbstor SHARED usbstor.c usbstor.rc)
|
add_library(usbstor SHARED descriptor.c fdo.c misc.c pdo.c usbstor.c usbstor.rc)
|
||||||
|
|
||||||
set_module_type(usbstor kernelmodedriver)
|
set_module_type(usbstor kernelmodedriver)
|
||||||
add_importlibs(usbstor ntoskrnl hal)
|
add_importlibs(usbstor ntoskrnl hal usbd)
|
||||||
add_cab_target(usbstor 2)
|
add_cab_target(usbstor 2)
|
||||||
|
|
516
drivers/usb/usbstor/descriptor.c
Normal file
516
drivers/usb/usbstor/descriptor.c
Normal file
|
@ -0,0 +1,516 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/usb/usbstor/descriptor.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"
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
USBSTOR_GetDescriptor(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN UCHAR DescriptorType,
|
||||||
|
IN ULONG DescriptorLength,
|
||||||
|
IN UCHAR DescriptorIndex,
|
||||||
|
IN LANGID LanguageId,
|
||||||
|
OUT PVOID *OutDescriptor)
|
||||||
|
{
|
||||||
|
PURB Urb;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PVOID Descriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
ASSERT(DeviceObject);
|
||||||
|
ASSERT(OutDescriptor);
|
||||||
|
ASSERT(DescriptorLength);
|
||||||
|
|
||||||
|
//
|
||||||
|
// first allocate descriptor buffer
|
||||||
|
//
|
||||||
|
Descriptor = AllocateItem(NonPagedPool, DescriptorLength);
|
||||||
|
if (!Descriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate urb
|
||||||
|
//
|
||||||
|
Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB));
|
||||||
|
if (!Urb)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
FreeItem(Descriptor);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize urb
|
||||||
|
//
|
||||||
|
Urb->UrbHeader.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
|
||||||
|
Urb->UrbHeader.Length = sizeof(URB);
|
||||||
|
Urb->UrbControlDescriptorRequest.DescriptorType = DescriptorType;
|
||||||
|
Urb->UrbControlDescriptorRequest.TransferBuffer = Descriptor;
|
||||||
|
Urb->UrbControlDescriptorRequest.TransferBufferLength = DescriptorLength;
|
||||||
|
Urb->UrbControlDescriptorRequest.Index = DescriptorIndex;
|
||||||
|
Urb->UrbControlDescriptorRequest.LanguageId = LanguageId;
|
||||||
|
|
||||||
|
//
|
||||||
|
// submit urb
|
||||||
|
//
|
||||||
|
Status = USBSTOR_SyncUrbRequest(DeviceObject, Urb);
|
||||||
|
|
||||||
|
//
|
||||||
|
// free urb
|
||||||
|
//
|
||||||
|
FreeItem(Urb);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
*OutDescriptor = Descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_GetDescriptors(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PFDO_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
USHORT DescriptorLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// first get device descriptor
|
||||||
|
//
|
||||||
|
Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_DEVICE_DESCRIPTOR_TYPE, sizeof(USB_DEVICE_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->DeviceDescriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to get device descriptor
|
||||||
|
//
|
||||||
|
FreeItem(DeviceExtension->DeviceDescriptor);
|
||||||
|
DeviceExtension->DeviceDescriptor = NULL;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// now get basic configuration descriptor
|
||||||
|
//
|
||||||
|
Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, sizeof(USB_CONFIGURATION_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to get configuration descriptor
|
||||||
|
//
|
||||||
|
FreeItem(DeviceExtension->DeviceDescriptor);
|
||||||
|
DeviceExtension->DeviceDescriptor = NULL;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// backup length
|
||||||
|
//
|
||||||
|
DescriptorLength = DeviceExtension->ConfigurationDescriptor->wTotalLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// release basic descriptor
|
||||||
|
//
|
||||||
|
FreeItem(DeviceExtension->ConfigurationDescriptor);
|
||||||
|
DeviceExtension->ConfigurationDescriptor = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate full descriptor
|
||||||
|
//
|
||||||
|
Status = USBSTOR_GetDescriptor(DeviceExtension->LowerDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, DescriptorLength, 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to get configuration descriptor
|
||||||
|
//
|
||||||
|
FreeItem(DeviceExtension->DeviceDescriptor);
|
||||||
|
DeviceExtension->DeviceDescriptor = NULL;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: scan string descriptors
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
USBSTOR_ScanConfigurationDescriptor(
|
||||||
|
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||||
|
OUT PUSB_INTERFACE_DESCRIPTOR * OutInterfaceDescriptor,
|
||||||
|
OUT PUSB_ENDPOINT_DESCRIPTOR * InEndpointDescriptor,
|
||||||
|
OUT PUSB_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor)
|
||||||
|
{
|
||||||
|
PUSB_CONFIGURATION_DESCRIPTOR CurrentDescriptor;
|
||||||
|
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
ASSERT(ConfigurationDescriptor);
|
||||||
|
ASSERT(OutInterfaceDescriptor);
|
||||||
|
ASSERT(InEndpointDescriptor);
|
||||||
|
ASSERT(OutEndpointDescriptor);
|
||||||
|
|
||||||
|
//
|
||||||
|
// nullify pointers
|
||||||
|
//
|
||||||
|
*OutInterfaceDescriptor = NULL;
|
||||||
|
*InEndpointDescriptor = NULL;
|
||||||
|
*OutEndpointDescriptor = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// start scanning
|
||||||
|
//
|
||||||
|
CurrentDescriptor = ConfigurationDescriptor;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// check current descriptor type
|
||||||
|
//
|
||||||
|
if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// found interface descriptor
|
||||||
|
//
|
||||||
|
if (*OutInterfaceDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// we only process the first interface descriptor as ms does -> see documentation
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// store interface descriptor
|
||||||
|
//
|
||||||
|
*OutInterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)CurrentDescriptor;
|
||||||
|
}
|
||||||
|
else if (CurrentDescriptor->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// convert to endpoint descriptor
|
||||||
|
//
|
||||||
|
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)CurrentDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(*OutInterfaceDescriptor);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get endpoint type
|
||||||
|
//
|
||||||
|
if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// bulk endpoint type
|
||||||
|
//
|
||||||
|
if (USB_ENDPOINT_DIRECTION_IN(EndpointDescriptor->bEndpointAddress))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// bulk in
|
||||||
|
//
|
||||||
|
*InEndpointDescriptor = EndpointDescriptor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// bulk out
|
||||||
|
//
|
||||||
|
*OutEndpointDescriptor = EndpointDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// interrupt endpoint type
|
||||||
|
//
|
||||||
|
UNIMPLEMENTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// move to next descriptor
|
||||||
|
//
|
||||||
|
CurrentDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)CurrentDescriptor + CurrentDescriptor->bLength);
|
||||||
|
|
||||||
|
//
|
||||||
|
// was it the last descriptor
|
||||||
|
//
|
||||||
|
if ((ULONG_PTR)CurrentDescriptor > ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// reached last descriptor
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}while(TRUE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if everything has been found
|
||||||
|
//
|
||||||
|
if (*OutInterfaceDescriptor == NULL || *InEndpointDescriptor == NULL || *OutEndpointDescriptor == NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to find interface / endpoint descriptor
|
||||||
|
//
|
||||||
|
DPRINT1("USBSTOR_ScanConfigurationDescriptor: Failed to find InterfaceDescriptor %p InEndpointDescriptor %p OutEndpointDescriptor %p\n", *OutInterfaceDescriptor, *InEndpointDescriptor, *OutEndpointDescriptor);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// completed successfully
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
|
||||||
|
{
|
||||||
|
DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
|
||||||
|
DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
|
||||||
|
DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
|
||||||
|
DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
|
||||||
|
DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
|
||||||
|
DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
|
||||||
|
DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
|
||||||
|
DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
|
||||||
|
DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_SelectConfigurationAndInterface(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PFDO_DEVICE_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||||
|
PUSB_ENDPOINT_DESCRIPTOR InEndpointDescriptor, OutEndpointDescriptor;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PURB Urb;
|
||||||
|
PUSBD_INTERFACE_LIST_ENTRY InterfaceList;
|
||||||
|
|
||||||
|
//
|
||||||
|
// now scan configuration descriptors
|
||||||
|
//
|
||||||
|
Status = USBSTOR_ScanConfigurationDescriptor(DeviceExtension->ConfigurationDescriptor, &InterfaceDescriptor, &InEndpointDescriptor, &OutEndpointDescriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to scan
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// now allocate one interface entry and terminating null entry
|
||||||
|
//
|
||||||
|
InterfaceList = (PUSBD_INTERFACE_LIST_ENTRY)AllocateItem(PagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * 2);
|
||||||
|
if (!InterfaceList)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize interface list entry
|
||||||
|
//
|
||||||
|
InterfaceList[0].InterfaceDescriptor = InterfaceDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// now allocate the urb
|
||||||
|
//
|
||||||
|
Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, InterfaceList);
|
||||||
|
if (!Urb)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
FreeItem(InterfaceList);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(InterfaceList[0].Interface);
|
||||||
|
|
||||||
|
//
|
||||||
|
// submit urb
|
||||||
|
//
|
||||||
|
Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to set configuration
|
||||||
|
//
|
||||||
|
DPRINT1("USBSTOR_SelectConfiguration failed to set interface %x\n", Status);
|
||||||
|
FreeItem(InterfaceList);
|
||||||
|
FreeItem(Urb);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// backup interface information
|
||||||
|
//
|
||||||
|
DeviceExtension->InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)AllocateItem(NonPagedPool, Urb->UrbSelectConfiguration.Interface.Length);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate interface information structure
|
||||||
|
//
|
||||||
|
FreeItem(InterfaceList);
|
||||||
|
FreeItem(Urb);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy interface information
|
||||||
|
//
|
||||||
|
RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectConfiguration.Interface, Urb->UrbSelectConfiguration.Interface.Length);
|
||||||
|
|
||||||
|
//
|
||||||
|
// store pipe handle
|
||||||
|
//
|
||||||
|
DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// now prepare interface urb
|
||||||
|
//
|
||||||
|
UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting);
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy interface information structure back - as offset for SelectConfiguration / SelectInterface request do differ
|
||||||
|
//
|
||||||
|
RtlCopyMemory(&Urb->UrbSelectInterface.Interface, DeviceExtension->InterfaceInformation, DeviceExtension->InterfaceInformation->Length);
|
||||||
|
|
||||||
|
//
|
||||||
|
// now select the interface
|
||||||
|
//
|
||||||
|
Status = USBSTOR_SyncUrbRequest(DeviceExtension->LowerDeviceObject, Urb);
|
||||||
|
|
||||||
|
//
|
||||||
|
// did it succeeed
|
||||||
|
//
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// update configuration info
|
||||||
|
//
|
||||||
|
RtlCopyMemory(DeviceExtension->InterfaceInformation, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectConfiguration.Interface.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// free interface list & urb
|
||||||
|
//
|
||||||
|
FreeItem(InterfaceList);
|
||||||
|
FreeItem(Urb);
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_GetPipeHandles(
|
||||||
|
IN PFDO_DEVICE_EXTENSION DeviceExtension)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
BOOLEAN BulkInFound = FALSE, BulkOutFound = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// no enumerate all pipes and extract bulk-in / bulk-out pipe handle
|
||||||
|
//
|
||||||
|
for(Index = 0; Index < DeviceExtension->InterfaceInformation->NumberOfPipes; Index++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// check pipe type
|
||||||
|
//
|
||||||
|
if (DeviceExtension->InterfaceInformation->Pipes[Index].PipeType == UsbdPipeTypeBulk)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// check direction
|
||||||
|
//
|
||||||
|
if (USB_ENDPOINT_DIRECTION_IN(DeviceExtension->InterfaceInformation->Pipes[Index].EndpointAddress))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// bulk in pipe
|
||||||
|
//
|
||||||
|
DeviceExtension->BulkInPipeIndex = Index;
|
||||||
|
|
||||||
|
//
|
||||||
|
// there should not be another bulk in pipe
|
||||||
|
//
|
||||||
|
ASSERT(BulkInFound == FALSE);
|
||||||
|
BulkInFound = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// bulk out pipe
|
||||||
|
//
|
||||||
|
DeviceExtension->BulkOutPipeIndex = Index;
|
||||||
|
|
||||||
|
//
|
||||||
|
// there should not be another bulk out pipe
|
||||||
|
//
|
||||||
|
ASSERT(BulkOutFound == FALSE);
|
||||||
|
BulkOutFound = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if both bulk pipes have been found
|
||||||
|
//
|
||||||
|
if (!BulkInFound || !BulkOutFound)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// WTF? usb port driver does not give us bulk pipe access
|
||||||
|
//
|
||||||
|
DPRINT1("USBSTOR_GetPipeHandles> BulkInFound %d BulkOutFound %d missing!!!\n", BulkInFound, BulkOutFound);
|
||||||
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// device is configured
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
331
drivers/usb/usbstor/fdo.c
Normal file
331
drivers/usb/usbstor/fdo.c
Normal file
|
@ -0,0 +1,331 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
359
drivers/usb/usbstor/misc.c
Normal file
359
drivers/usb/usbstor/misc.c
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
}
|
216
drivers/usb/usbstor/pdo.c
Normal file
216
drivers/usb/usbstor/pdo.c
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/usb/usbstor/pdo.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"
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_PdoHandleDeviceRelations(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN OUT PIRP Irp)
|
||||||
|
{
|
||||||
|
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 != TargetDeviceRelation)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// PDO handles only target device relation
|
||||||
|
//
|
||||||
|
return Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate device relations
|
||||||
|
//
|
||||||
|
DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
|
||||||
|
if (!DeviceRelations)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize device relations
|
||||||
|
//
|
||||||
|
DeviceRelations->Count = 1;
|
||||||
|
DeviceRelations->Objects[0] = DeviceObject;
|
||||||
|
ObReferenceObject(DeviceObject);
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
||||||
|
|
||||||
|
//
|
||||||
|
// completed successfully
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_PdoHandlePnp(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN OUT PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PPDO_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(DeviceExtension->Common.IsFDO == FALSE);
|
||||||
|
|
||||||
|
switch(IoStack->MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||||
|
{
|
||||||
|
Status = USBSTOR_PdoHandleDeviceRelations(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_DEVICE_TEXT:
|
||||||
|
DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_DEVICE_TEXT unimplemented\n");
|
||||||
|
Status = STATUS_NOT_SUPPORTED;
|
||||||
|
break;
|
||||||
|
case IRP_MN_QUERY_ID:
|
||||||
|
DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID unimplemented\n");
|
||||||
|
Status = STATUS_NOT_SUPPORTED;
|
||||||
|
break;
|
||||||
|
case IRP_MN_REMOVE_DEVICE:
|
||||||
|
DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_REMOVE_DEVICE unimplemented\n");
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
case IRP_MN_QUERY_CAPABILITIES:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// just forward irp to lower device
|
||||||
|
//
|
||||||
|
Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_START_DEVICE:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no-op for PDO
|
||||||
|
//
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// do nothing
|
||||||
|
//
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete request
|
||||||
|
//
|
||||||
|
if (Status != STATUS_PENDING)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete request
|
||||||
|
//
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done processing
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_CreatePDO(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
OUT PDEVICE_OBJECT *ChildDeviceObject)
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT PDO;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// create child device object
|
||||||
|
//
|
||||||
|
Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_MASS_STORAGE, 0, FALSE, &PDO);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to create device
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// patch the stack size
|
||||||
|
//
|
||||||
|
PDO->StackSize = DeviceObject->StackSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDO->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize device extension
|
||||||
|
//
|
||||||
|
RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
|
||||||
|
PDODeviceExtension->Common.IsFDO = FALSE;
|
||||||
|
PDODeviceExtension->LowerDeviceObject = DeviceObject;
|
||||||
|
|
||||||
|
//
|
||||||
|
// set device flags
|
||||||
|
//
|
||||||
|
PDO->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device is initialized
|
||||||
|
//
|
||||||
|
PDO->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
|
//
|
||||||
|
// output device object
|
||||||
|
//
|
||||||
|
*ChildDeviceObject = PDO;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
* PURPOSE: USB block storage device driver.
|
* PURPOSE: USB block storage device driver.
|
||||||
* PROGRAMMERS:
|
* PROGRAMMERS:
|
||||||
* James Tabor
|
* James Tabor
|
||||||
|
Johannes Anderwald
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
@ -15,84 +16,201 @@
|
||||||
|
|
||||||
/* PUBLIC AND PRIVATE FUNCTIONS **********************************************/
|
/* PUBLIC AND PRIVATE FUNCTIONS **********************************************/
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS
|
||||||
IrpStub(IN PDEVICE_OBJECT DeviceObject,
|
NTAPI
|
||||||
IN PIRP Irp)
|
USBSTOR_AddDevice(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PDEVICE_OBJECT PhysicalDeviceObject)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_NOT_SUPPORTED;
|
NTSTATUS Status;
|
||||||
Irp->IoStatus.Status = Status;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
PFDO_DEVICE_EXTENSION DeviceExtension;
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
//
|
||||||
AddDevice(IN PDRIVER_OBJECT DriverObject,
|
// lets create the device
|
||||||
IN PDEVICE_OBJECT pdo)
|
//
|
||||||
{
|
Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION), 0, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &DeviceObject);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check for success
|
||||||
|
//
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("USBSTOR_AddDevice: Failed to create FDO Status %x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(DeviceExtension);
|
||||||
|
|
||||||
|
//
|
||||||
|
// zero device extension
|
||||||
|
//
|
||||||
|
RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize device extension
|
||||||
|
//
|
||||||
|
DeviceExtension->Common.IsFDO = TRUE;
|
||||||
|
DeviceExtension->FunctionalDeviceObject = DeviceObject;
|
||||||
|
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
||||||
|
DeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
|
||||||
|
|
||||||
|
//
|
||||||
|
// did attaching fail
|
||||||
|
//
|
||||||
|
if (!DeviceExtension->LowerDeviceObject)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// device removed
|
||||||
|
//
|
||||||
|
IoDeleteDevice(DeviceObject);
|
||||||
|
|
||||||
|
return STATUS_DEVICE_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// set device flags
|
||||||
|
//
|
||||||
|
DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device is initialized
|
||||||
|
//
|
||||||
|
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID NTAPI
|
VOID
|
||||||
DriverUnload(PDRIVER_OBJECT DriverObject)
|
NTAPI
|
||||||
|
USBSTOR_Unload(
|
||||||
|
PDRIVER_OBJECT DriverObject)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// no-op
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID NTAPI
|
VOID
|
||||||
StartIo(PUSBSTOR_DEVICE_EXTENSION DeviceExtension,
|
NTAPI
|
||||||
PIRP Irp)
|
USBSTOR_StartIo(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// implement me
|
||||||
|
//
|
||||||
|
UNIMPLEMENTED
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS NTAPI
|
NTSTATUS
|
||||||
DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
NTAPI
|
||||||
|
USBSTOR_DispatchClose(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// function always succeeds ;)
|
||||||
|
//
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS NTAPI
|
|
||||||
DispatchCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
||||||
{
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS NTAPI
|
NTSTATUS
|
||||||
DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
NTAPI
|
||||||
|
USBSTOR_DispatchDeviceControl(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS NTAPI
|
NTSTATUS
|
||||||
DispatchScsi(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
NTAPI
|
||||||
|
USBSTOR_DispatchScsi(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS NTAPI
|
NTSTATUS
|
||||||
DispatchReadWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
NTAPI
|
||||||
|
USBSTOR_DispatchReadWrite(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS;
|
//
|
||||||
|
// read write ioctl is not supported
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS NTAPI
|
NTSTATUS
|
||||||
DispatchSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
NTAPI
|
||||||
|
USBSTOR_DispatchPnp(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS;
|
PCOMMON_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get common device extension
|
||||||
|
//
|
||||||
|
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// is it for the FDO
|
||||||
|
//
|
||||||
|
if (DeviceExtension->IsFDO)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// dispatch pnp request to fdo pnp handler
|
||||||
|
//
|
||||||
|
return USBSTOR_FdoHandlePnp(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// dispatch request to pdo pnp handler
|
||||||
|
//
|
||||||
|
return USBSTOR_PdoHandlePnp(DeviceObject, Irp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS NTAPI
|
NTSTATUS
|
||||||
DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
NTAPI
|
||||||
|
USBSTOR_DispatchPower(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS;
|
UNIMPLEMENTED
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS NTAPI
|
|
||||||
DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
|
|
||||||
{
|
|
||||||
DPRINT1("USBSTOR: IRP_MJ_POWER unimplemented\n");
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
@ -101,37 +219,62 @@ DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
NTSTATUS
|
||||||
* Standard DriverEntry method.
|
NTAPI
|
||||||
*/
|
DriverEntry(
|
||||||
NTSTATUS NTAPI
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
|
IN PUNICODE_STRING RegPath)
|
||||||
{
|
{
|
||||||
ULONG i;
|
|
||||||
|
|
||||||
DPRINT("********* USB Storage *********\n");
|
DPRINT1("********* USB Storage *********\n");
|
||||||
|
|
||||||
DriverObject->DriverUnload = DriverUnload;
|
//
|
||||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
// driver unload routine
|
||||||
|
//
|
||||||
|
DriverObject->DriverUnload = USBSTOR_Unload;
|
||||||
|
|
||||||
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
//
|
||||||
DriverObject->MajorFunction[i] = IrpStub;
|
// add device function
|
||||||
|
//
|
||||||
|
DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice;
|
||||||
|
|
||||||
DriverObject->DriverStartIo = (PVOID)StartIo;
|
//
|
||||||
|
// driver start i/o routine
|
||||||
|
//
|
||||||
|
DriverObject->DriverStartIo = USBSTOR_StartIo;
|
||||||
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchClose;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadWrite;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchReadWrite;
|
|
||||||
|
|
||||||
/* Scsi Miniport support */
|
//
|
||||||
DriverObject->MajorFunction[IRP_MJ_SCSI] = DispatchScsi;
|
// create / close
|
||||||
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchSystemControl;
|
//
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = USBSTOR_DispatchClose;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBSTOR_DispatchClose;
|
||||||
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
//
|
||||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
// scsi pass through requests
|
||||||
|
//
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBSTOR_DispatchDeviceControl;
|
||||||
|
|
||||||
|
//
|
||||||
|
// irp dispatch read / write
|
||||||
|
//
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_READ] = USBSTOR_DispatchReadWrite;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = USBSTOR_DispatchReadWrite;
|
||||||
|
|
||||||
|
//
|
||||||
|
// scsi queue ioctl
|
||||||
|
//
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_SCSI] = USBSTOR_DispatchScsi;
|
||||||
|
|
||||||
|
//
|
||||||
|
// pnp processing
|
||||||
|
//
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_PNP] = USBSTOR_DispatchPnp;
|
||||||
|
|
||||||
|
//
|
||||||
|
// power processing
|
||||||
|
//
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_POWER] = USBSTOR_DispatchPower;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,19 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <ntddk.h>
|
#include <ntddk.h>
|
||||||
#include <usbdi.h>
|
#define NDEBUG
|
||||||
#include <usbiodef.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <usbdi.h>
|
||||||
|
#include <hubbusif.h>
|
||||||
|
#include <usbbusif.h>
|
||||||
|
#include <usbioctl.h>
|
||||||
|
#include <usbiodef.h>
|
||||||
|
#include <usb.h>
|
||||||
|
#include <usbdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <wdmguid.h>
|
||||||
|
|
||||||
|
|
||||||
#define USB_STOR_TAG 'sbsu'
|
#define USB_STOR_TAG 'sbsu'
|
||||||
#define USB_MAXCHILDREN (16)
|
#define USB_MAXCHILDREN (16)
|
||||||
|
@ -13,71 +24,117 @@ IoAttachDeviceToDeviceStackSafe(
|
||||||
IN PDEVICE_OBJECT TargetDevice,
|
IN PDEVICE_OBJECT TargetDevice,
|
||||||
OUT PDEVICE_OBJECT *AttachedToDeviceObject);
|
OUT PDEVICE_OBJECT *AttachedToDeviceObject);
|
||||||
|
|
||||||
typedef struct _USBSTOR_DEVICE_EXTENSION
|
typedef struct _COMMON_DEVICE_EXTENSION
|
||||||
{
|
{
|
||||||
BOOLEAN IsFDO;
|
BOOLEAN IsFDO;
|
||||||
struct usb_device* dev;
|
|
||||||
PDEVICE_OBJECT LowerDevice;
|
|
||||||
|
|
||||||
PDEVICE_OBJECT Children[USB_MAXCHILDREN];
|
}COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
|
||||||
|
|
||||||
/* Fields valid only when IsFDO == FALSE */
|
typedef struct
|
||||||
UNICODE_STRING DeviceDescription; // REG_SZ
|
{
|
||||||
UNICODE_STRING DeviceId; // REG_SZ
|
COMMON_DEVICE_EXTENSION Common; // common device extension
|
||||||
UNICODE_STRING InstanceId; // REG_SZ
|
|
||||||
UNICODE_STRING HardwareIds; // REG_MULTI_SZ
|
PDEVICE_OBJECT FunctionalDeviceObject; // functional device object
|
||||||
UNICODE_STRING CompatibleIds; // REG_MULTI_SZ
|
PDEVICE_OBJECT PhysicalDeviceObject; // physical device object
|
||||||
UNICODE_STRING SymbolicLinkName;
|
PDEVICE_OBJECT LowerDeviceObject; // lower device object
|
||||||
} USBSTOR_DEVICE_EXTENSION, *PUSBSTOR_DEVICE_EXTENSION;
|
USB_BUS_INTERFACE_USBDI_V2 BusInterface; // bus interface of device
|
||||||
|
PUSB_DEVICE_DESCRIPTOR DeviceDescriptor; // usb device descriptor
|
||||||
|
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; // usb configuration descriptor
|
||||||
|
PUSBD_INTERFACE_INFORMATION InterfaceInformation; // usb interface information
|
||||||
|
USBD_CONFIGURATION_HANDLE ConfigurationHandle; // usb configuration handle
|
||||||
|
UCHAR BulkInPipeIndex; // bulk in pipe index
|
||||||
|
UCHAR BulkOutPipeIndex; // bulk out pipe index
|
||||||
|
UCHAR MaxLUN; // max lun for device
|
||||||
|
PDEVICE_OBJECT ChildPDO[16]; // max 16 child pdo devices
|
||||||
|
}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
COMMON_DEVICE_EXTENSION Common;
|
||||||
|
PDEVICE_OBJECT LowerDeviceObject; // points to FDO
|
||||||
|
|
||||||
|
}PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
|
||||||
/* cleanup.c */
|
//
|
||||||
NTSTATUS NTAPI
|
// max lun command identifier
|
||||||
UsbStorCleanup(
|
//
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
#define USB_BULK_GET_MAX_LUN 0xFE
|
||||||
IN PIRP Irp);
|
|
||||||
|
|
||||||
/* fdo.c */
|
//---------------------------------------------------------------------
|
||||||
NTSTATUS NTAPI
|
//
|
||||||
UsbStorPnpFdo(
|
// fdo.c routines
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
//
|
||||||
IN PIRP Irp);
|
NTSTATUS
|
||||||
|
USBSTOR_FdoHandlePnp(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN OUT PIRP Irp);
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// pdo.c routines
|
||||||
|
//
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_PdoHandlePnp(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN OUT PIRP Irp);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
UsbStorDeviceControlFdo(
|
USBSTOR_CreatePDO(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp);
|
OUT PDEVICE_OBJECT *ChildDeviceObject);
|
||||||
|
|
||||||
/* misc.c */
|
//---------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// misc.c routines
|
||||||
|
//
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ForwardIrpAndWait(
|
NTAPI
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
USBSTOR_SyncForwardIrp(
|
||||||
IN PIRP Irp);
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN OUT PIRP Irp);
|
||||||
NTSTATUS NTAPI
|
|
||||||
ForwardIrpAndForget(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
UsbStorDuplicateUnicodeString(
|
NTAPI
|
||||||
OUT PUNICODE_STRING Destination,
|
USBSTOR_GetBusInterface(
|
||||||
IN PUNICODE_STRING Source,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN POOL_TYPE PoolType);
|
OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface);
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
AllocateItem(
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
IN ULONG ItemSize);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FreeItem(
|
||||||
|
IN PVOID Item);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
UsbStorInitMultiSzString(
|
USBSTOR_SyncUrbRequest(
|
||||||
OUT PUNICODE_STRING Destination,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
... /* list of PCSZ */);
|
OUT PURB UrbRequest);
|
||||||
|
|
||||||
/* pdo.c */
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
UsbStorPnpPdo(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
UsbStorDeviceControlPdo(
|
USBSTOR_GetMaxLUN(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp);
|
IN PFDO_DEVICE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// descriptor.c routines
|
||||||
|
//
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_GetDescriptors(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_SelectConfigurationAndInterface(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PFDO_DEVICE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
USBSTOR_GetPipeHandles(
|
||||||
|
IN PFDO_DEVICE_EXTENSION DeviceExtension);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue