[USBEHCI_NEW]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 3 May 2011 00:15:23 +0000 (00:15 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 3 May 2011 00:15:23 +0000 (00:15 +0000)
- 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

drivers/usb/CMakeLists.txt
drivers/usb/usbehci_new/hcd_controller.cpp
drivers/usb/usbehci_new/misc.cpp
drivers/usb/usbstor/CMakeLists.txt
drivers/usb/usbstor/descriptor.c [new file with mode: 0644]
drivers/usb/usbstor/fdo.c [new file with mode: 0644]
drivers/usb/usbstor/misc.c [new file with mode: 0644]
drivers/usb/usbstor/pdo.c [new file with mode: 0644]
drivers/usb/usbstor/usbstor.c
drivers/usb/usbstor/usbstor.h

index 2d351a6..10f7020 100644 (file)
@@ -2,5 +2,5 @@
 add_subdirectory(nt4compat)
 add_subdirectory(usbd)
 add_subdirectory(usbehci_new)
-#add_subdirectory(usbhub) Compiles, just skipped in trunk
-#add_subdirectory(usbstor) Compiles, just skipped in trunk
+add_subdirectory(usbhub)
+add_subdirectory(usbstor)
\ No newline at end of file
index 9146dae..5a6318e 100644 (file)
@@ -44,7 +44,6 @@ public:
 
     // local functions
     NTSTATUS CreateFDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
-    NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
     NTSTATUS SetSymbolicLink(BOOLEAN Enable);
 
     // constructor / destructor
index ff8a833..56c35cc 100644 (file)
@@ -80,8 +80,11 @@ SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
     return Status;
 }
 
-NTSTATUS NTAPI
-GetBusInterface(PDEVICE_OBJECT DeviceObject, PBUS_INTERFACE_STANDARD busInterface)
+NTSTATUS
+NTAPI
+GetBusInterface(
+    PDEVICE_OBJECT DeviceObject, 
+    PBUS_INTERFACE_STANDARD busInterface)
 {
     KEVENT Event;
     NTSTATUS Status;
index 041ce39..83d1f01 100644 (file)
@@ -3,8 +3,8 @@ add_definitions(-DDEBUG_MODE)
 
 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)
-add_importlibs(usbstor ntoskrnl hal)
+add_importlibs(usbstor ntoskrnl hal usbd)
 add_cab_target(usbstor 2)
diff --git a/drivers/usb/usbstor/descriptor.c b/drivers/usb/usbstor/descriptor.c
new file mode 100644 (file)
index 0000000..7ed4364
--- /dev/null
@@ -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;
+}
\ No newline at end of file
diff --git a/drivers/usb/usbstor/fdo.c b/drivers/usb/usbstor/fdo.c
new file mode 100644 (file)
index 0000000..6145ef4
--- /dev/null
@@ -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;
+}
diff --git a/drivers/usb/usbstor/misc.c b/drivers/usb/usbstor/misc.c
new file mode 100644 (file)
index 0000000..70b9427
--- /dev/null
@@ -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;
+
+}
diff --git a/drivers/usb/usbstor/pdo.c b/drivers/usb/usbstor/pdo.c
new file mode 100644 (file)
index 0000000..e742af2
--- /dev/null
@@ -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;
+}
index ef8cd7e..1f1c07e 100644 (file)
@@ -5,6 +5,7 @@
  * PURPOSE:     USB block storage device driver.
  * PROGRAMMERS:
  *              James Tabor
+                Johannes Anderwald
  */
 
 /* INCLUDES ******************************************************************/
 
 /* PUBLIC AND PRIVATE FUNCTIONS **********************************************/
 
-NTSTATUS NTAPI
-IrpStub(IN PDEVICE_OBJECT DeviceObject,
-        IN PIRP Irp)
+NTSTATUS
+NTAPI
+USBSTOR_AddDevice(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PDEVICE_OBJECT PhysicalDeviceObject)
 {
-    NTSTATUS Status = STATUS_NOT_SUPPORTED;
-    Irp->IoStatus.Status = Status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    return Status;
-}
+    NTSTATUS Status;
+    PDEVICE_OBJECT DeviceObject;
+    PFDO_DEVICE_EXTENSION DeviceExtension;
 
-NTSTATUS NTAPI
-AddDevice(IN PDRIVER_OBJECT DriverObject,
-          IN PDEVICE_OBJECT pdo)
-{
+    //
+    // lets create the device
+    //
+    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;
 }
 
-VOID NTAPI
-DriverUnload(PDRIVER_OBJECT DriverObject)
+VOID
+NTAPI
+USBSTOR_Unload(
+    PDRIVER_OBJECT DriverObject)
 {
+    //
+    // no-op
+    //
 }
 
-VOID NTAPI
-StartIo(PUSBSTOR_DEVICE_EXTENSION DeviceExtension,
-        PIRP Irp)
+VOID
+NTAPI
+USBSTOR_StartIo(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
 {
+    //
+    // implement me
+    //
+    UNIMPLEMENTED
 }
 
-static NTSTATUS NTAPI
-DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS
+NTAPI
+USBSTOR_DispatchClose(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
 {
+    //
+    // function always succeeds ;)
+    //
     Irp->IoStatus.Information = 0;
     Irp->IoStatus.Status = STATUS_SUCCESS;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
     return STATUS_SUCCESS;
 }
 
-static NTSTATUS NTAPI
-DispatchCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-{
-    return STATUS_SUCCESS;
-}
 
-static NTSTATUS NTAPI
-DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS
+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;
 }
 
 
-static NTSTATUS NTAPI
-DispatchScsi(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS
+NTAPI
+USBSTOR_DispatchScsi(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
 {
-    return STATUS_SUCCESS;
-}
+    UNIMPLEMENTED
 
-static NTSTATUS NTAPI
-DispatchReadWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-{
+    Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
     return STATUS_SUCCESS;
 }
 
-static NTSTATUS NTAPI
-DispatchSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS
+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
-DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS
+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
-DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
+NTSTATUS
+NTAPI
+USBSTOR_DispatchPower(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
 {
-    DPRINT1("USBSTOR: IRP_MJ_POWER unimplemented\n");
+    UNIMPLEMENTED
+
     Irp->IoStatus.Information = 0;
     Irp->IoStatus.Status = STATUS_SUCCESS;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -101,37 +219,62 @@ DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
 
 
 
-/*
- * Standard DriverEntry method.
- */
-NTSTATUS NTAPI
-DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
+NTSTATUS
+NTAPI
+DriverEntry(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PUNICODE_STRING RegPath)
 {
-    ULONG i;
 
-    DPRINT("********* USB Storage *********\n");
+    DPRINT1("********* USB Storage *********\n");
+
+    //
+    // driver unload routine
+    //
+    DriverObject->DriverUnload = USBSTOR_Unload;
+
+    //
+    // add device function
+    //
+    DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice;
+
+    //
+    // driver start i/o routine
+    //
+    DriverObject->DriverStartIo = USBSTOR_StartIo;
+
 
-    DriverObject->DriverUnload = DriverUnload;
-    DriverObject->DriverExtension->AddDevice = AddDevice;
+    //
+    // create / close
+    //
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = USBSTOR_DispatchClose;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBSTOR_DispatchClose;
 
-    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
-        DriverObject->MajorFunction[i] = IrpStub;
+    //
+    // scsi pass through requests
+    //
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBSTOR_DispatchDeviceControl;
 
-    DriverObject->DriverStartIo = (PVOID)StartIo;
+    //
+    // irp dispatch read / write
+    //
+    DriverObject->MajorFunction[IRP_MJ_READ] = USBSTOR_DispatchReadWrite;
+    DriverObject->MajorFunction[IRP_MJ_WRITE] = USBSTOR_DispatchReadWrite;
 
-    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 queue ioctl
+    //
+    DriverObject->MajorFunction[IRP_MJ_SCSI] = USBSTOR_DispatchScsi;
 
-    /* Scsi Miniport support */
-    DriverObject->MajorFunction[IRP_MJ_SCSI] = DispatchScsi;
-    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchSystemControl;
+    //
+    // pnp processing
+    //
+    DriverObject->MajorFunction[IRP_MJ_PNP] = USBSTOR_DispatchPnp;
 
-    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
-    DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
+    //
+    // power processing
+    //
+    DriverObject->MajorFunction[IRP_MJ_POWER] = USBSTOR_DispatchPower;
 
     return STATUS_SUCCESS;
 }
index 9793db7..9ffc3fc 100644 (file)
@@ -1,8 +1,19 @@
+
+#pragma once
+
 #include <ntddk.h>
+#define NDEBUG
+#include <debug.h>
 #include <usbdi.h>
+#include <hubbusif.h>
+#include <usbbusif.h>
+#include <usbioctl.h>
 #include <usbiodef.h>
-#include <initguid.h>
-#include <debug.h>
+#include <usb.h>
+#include <usbdlib.h>
+#include <stdio.h>
+#include <wdmguid.h>
+
 
 #define USB_STOR_TAG 'sbsu'
 #define USB_MAXCHILDREN              (16)
@@ -13,71 +24,117 @@ IoAttachDeviceToDeviceStackSafe(
   IN PDEVICE_OBJECT TargetDevice,
   OUT PDEVICE_OBJECT *AttachedToDeviceObject);
 
-typedef struct _USBSTOR_DEVICE_EXTENSION
+typedef struct _COMMON_DEVICE_EXTENSION
 {
-       BOOLEAN IsFDO;
-       struct usb_device* dev;
-       PDEVICE_OBJECT LowerDevice;
+    BOOLEAN IsFDO;
 
-       PDEVICE_OBJECT Children[USB_MAXCHILDREN];
+}COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
 
-       /* Fields valid only when IsFDO == FALSE */
-       UNICODE_STRING DeviceDescription; // REG_SZ
-       UNICODE_STRING DeviceId;          // REG_SZ
-       UNICODE_STRING InstanceId;        // REG_SZ
-       UNICODE_STRING HardwareIds;       // REG_MULTI_SZ
-       UNICODE_STRING CompatibleIds;     // REG_MULTI_SZ
-       UNICODE_STRING SymbolicLinkName;
-} USBSTOR_DEVICE_EXTENSION, *PUSBSTOR_DEVICE_EXTENSION;
+typedef struct
+{
+    COMMON_DEVICE_EXTENSION Common;                                                      // common device extension
+
+    PDEVICE_OBJECT FunctionalDeviceObject;                                               // functional device object
+    PDEVICE_OBJECT PhysicalDeviceObject;                                                 // physical device object
+    PDEVICE_OBJECT LowerDeviceObject;                                                    // lower device object
+    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
-UsbStorCleanup(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
 
-/* fdo.c */
-NTSTATUS NTAPI
-UsbStorPnpFdo(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
+//
+// max lun command identifier
+//
+#define USB_BULK_GET_MAX_LUN             0xFE
 
+//---------------------------------------------------------------------
+//
+// fdo.c routines
+//
 NTSTATUS
-UsbStorDeviceControlFdo(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
+USBSTOR_FdoHandlePnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN OUT PIRP Irp);
+
+//---------------------------------------------------------------------
+//
+// pdo.c routines
+//
+NTSTATUS
+USBSTOR_PdoHandlePnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN OUT PIRP Irp);
 
-/* misc.c */
 NTSTATUS
-ForwardIrpAndWait(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
+USBSTOR_CreatePDO(
+    IN PDEVICE_OBJECT DeviceObject,
+    OUT PDEVICE_OBJECT *ChildDeviceObject);
+
+//---------------------------------------------------------------------
+//
+// misc.c routines
+//
+NTSTATUS
+NTAPI
+USBSTOR_SyncForwardIrp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN OUT PIRP Irp);
 
-NTSTATUS NTAPI
-ForwardIrpAndForget(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
+NTSTATUS
+NTAPI
+USBSTOR_GetBusInterface(
+    IN PDEVICE_OBJECT DeviceObject,
+    OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface);
+
+PVOID
+AllocateItem(
+    IN POOL_TYPE PoolType, 
+    IN ULONG ItemSize);
+
+VOID
+FreeItem(
+    IN PVOID Item);
 
 NTSTATUS
-UsbStorDuplicateUnicodeString(
-       OUT PUNICODE_STRING Destination,
-       IN PUNICODE_STRING Source,
-       IN POOL_TYPE PoolType);
+USBSTOR_SyncUrbRequest(
+    IN PDEVICE_OBJECT DeviceObject,
+    OUT PURB UrbRequest);
 
 NTSTATUS
-UsbStorInitMultiSzString(
-       OUT PUNICODE_STRING Destination,
-       ... /* list of PCSZ */);
+USBSTOR_GetMaxLUN(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PFDO_DEVICE_EXTENSION DeviceExtension);
 
-/* pdo.c */
-NTSTATUS NTAPI
-UsbStorPnpPdo(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
+
+//---------------------------------------------------------------------
+//
+// descriptor.c routines
+//
+
+NTSTATUS
+USBSTOR_GetDescriptors(
+    IN PDEVICE_OBJECT DeviceObject);
+
+NTSTATUS
+USBSTOR_SelectConfigurationAndInterface(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PFDO_DEVICE_EXTENSION DeviceExtension);
 
 NTSTATUS
-UsbStorDeviceControlPdo(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp);
+USBSTOR_GetPipeHandles(
+    IN PFDO_DEVICE_EXTENSION DeviceExtension);