diff --git a/drivers/usb/CMakeLists.txt b/drivers/usb/CMakeLists.txt index 2d351a61899..10f7020771b 100644 --- a/drivers/usb/CMakeLists.txt +++ b/drivers/usb/CMakeLists.txt @@ -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 diff --git a/drivers/usb/usbehci_new/hcd_controller.cpp b/drivers/usb/usbehci_new/hcd_controller.cpp index 9146dae4b60..5a6318e1b5f 100644 --- a/drivers/usb/usbehci_new/hcd_controller.cpp +++ b/drivers/usb/usbehci_new/hcd_controller.cpp @@ -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 diff --git a/drivers/usb/usbehci_new/misc.cpp b/drivers/usb/usbehci_new/misc.cpp index ff8a833786c..56c35cc806b 100644 --- a/drivers/usb/usbehci_new/misc.cpp +++ b/drivers/usb/usbehci_new/misc.cpp @@ -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; diff --git a/drivers/usb/usbstor/CMakeLists.txt b/drivers/usb/usbstor/CMakeLists.txt index 041ce3947b1..83d1f011e1c 100644 --- a/drivers/usb/usbstor/CMakeLists.txt +++ b/drivers/usb/usbstor/CMakeLists.txt @@ -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 index 00000000000..7ed4364b28b --- /dev/null +++ b/drivers/usb/usbstor/descriptor.c @@ -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 index 00000000000..6145ef48a36 --- /dev/null +++ b/drivers/usb/usbstor/fdo.c @@ -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 index 00000000000..70b942771e4 --- /dev/null +++ b/drivers/usb/usbstor/misc.c @@ -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 index 00000000000..e742af21760 --- /dev/null +++ b/drivers/usb/usbstor/pdo.c @@ -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; +} diff --git a/drivers/usb/usbstor/usbstor.c b/drivers/usb/usbstor/usbstor.c index ef8cd7e307e..1f1c07e2e85 100644 --- a/drivers/usb/usbstor/usbstor.c +++ b/drivers/usb/usbstor/usbstor.c @@ -5,6 +5,7 @@ * PURPOSE: USB block storage device driver. * PROGRAMMERS: * James Tabor + Johannes Anderwald */ /* INCLUDES ******************************************************************/ @@ -15,84 +16,201 @@ /* 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) { + UNIMPLEMENTED + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } -static NTSTATUS NTAPI -DispatchReadWrite(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 -DispatchSystemControl(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 -DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) +NTSTATUS +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.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"); - 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; - DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchSystemControl; + // + // create / close + // + 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; } diff --git a/drivers/usb/usbstor/usbstor.h b/drivers/usb/usbstor/usbstor.h index 9793db758b9..9ffc3fc75f9 100644 --- a/drivers/usb/usbstor/usbstor.h +++ b/drivers/usb/usbstor/usbstor.h @@ -1,8 +1,19 @@ + +#pragma once + #include -#include -#include -#include +#define NDEBUG #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #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); +// +// max lun command identifier +// +#define USB_BULK_GET_MAX_LUN 0xFE -/* fdo.c */ -NTSTATUS NTAPI -UsbStorPnpFdo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); +//--------------------------------------------------------------------- +// +// fdo.c routines +// +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 -UsbStorDeviceControlFdo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); +USBSTOR_CreatePDO( + IN PDEVICE_OBJECT DeviceObject, + OUT PDEVICE_OBJECT *ChildDeviceObject); -/* misc.c */ +//--------------------------------------------------------------------- +// +// misc.c routines +// NTSTATUS -ForwardIrpAndWait( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS NTAPI -ForwardIrpAndForget( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); +NTAPI +USBSTOR_SyncForwardIrp( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PIRP Irp); NTSTATUS -UsbStorDuplicateUnicodeString( - OUT PUNICODE_STRING Destination, - IN PUNICODE_STRING Source, - IN POOL_TYPE PoolType); +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 -UsbStorInitMultiSzString( - OUT PUNICODE_STRING Destination, - ... /* list of PCSZ */); - -/* pdo.c */ -NTSTATUS NTAPI -UsbStorPnpPdo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); +USBSTOR_SyncUrbRequest( + IN PDEVICE_OBJECT DeviceObject, + OUT PURB UrbRequest); NTSTATUS -UsbStorDeviceControlPdo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); +USBSTOR_GetMaxLUN( + IN PDEVICE_OBJECT DeviceObject, + 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);