2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: USB block storage device driver.
5 * COPYRIGHT: 2005-2006 James Tabor
6 * 2011-2012 Michael Martin (michael.martin@reactos.org)
7 * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
17 USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
19 DPRINT1("Dumping Device Descriptor %p\n", DeviceDescriptor
);
20 DPRINT1("bLength %x\n", DeviceDescriptor
->bLength
);
21 DPRINT1("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
22 DPRINT1("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
23 DPRINT1("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
24 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
25 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
26 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
27 DPRINT1("idVendor %x\n", DeviceDescriptor
->idVendor
);
28 DPRINT1("idProduct %x\n", DeviceDescriptor
->idProduct
);
29 DPRINT1("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
30 DPRINT1("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
31 DPRINT1("iProduct %x\n", DeviceDescriptor
->iProduct
);
32 DPRINT1("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
33 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
37 USBSTOR_FdoHandleDeviceRelations(
38 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
41 ULONG DeviceCount
= 0;
43 PDEVICE_RELATIONS DeviceRelations
;
44 PIO_STACK_LOCATION IoStack
;
46 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
48 // check if relation type is BusRelations
49 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= BusRelations
)
51 // FDO always only handles bus relations
52 return USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
55 // go through array and count device objects
56 for (Index
= 0; Index
< max(DeviceExtension
->MaxLUN
, 1); Index
++)
58 if (DeviceExtension
->ChildPDO
[Index
])
64 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
) + (DeviceCount
> 1 ? (DeviceCount
-1) * sizeof(PDEVICE_OBJECT
) : 0));
67 return STATUS_INSUFFICIENT_RESOURCES
;
71 for (Index
= 0; Index
< max(DeviceExtension
->MaxLUN
, 1); Index
++)
73 if (DeviceExtension
->ChildPDO
[Index
])
76 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceExtension
->ChildPDO
[Index
];
79 ObReferenceObject(DeviceExtension
->ChildPDO
[Index
]);
81 DeviceRelations
->Count
++;
85 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
87 return STATUS_SUCCESS
;
91 USBSTOR_FdoHandleRemoveDevice(
92 IN PDEVICE_OBJECT DeviceObject
,
93 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
99 DPRINT("Handling FDO removal %p\n", DeviceObject
);
101 // FIXME: wait for devices finished processing
102 for (Index
= 0; Index
< 16; Index
++)
104 if (DeviceExtension
->ChildPDO
[Index
] != NULL
)
106 DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension
->ChildPDO
[Index
], DeviceExtension
->ChildPDO
[Index
]->ReferenceCount
, DeviceExtension
->ChildPDO
[Index
]->AttachedDevice
);
107 IoDeleteDevice(DeviceExtension
->ChildPDO
[Index
]);
111 // Send the IRP down the stack
112 IoSkipCurrentIrpStackLocation(Irp
);
113 Status
= IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
115 // Detach from the device stack
116 IoDetachDevice(DeviceExtension
->LowerDeviceObject
);
118 IoDeleteDevice(DeviceObject
);
124 USBSTOR_FdoHandleStartDevice(
125 IN PDEVICE_OBJECT DeviceObject
,
126 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
129 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc
;
133 // forward irp to lower device
134 Status
= USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
135 if (!NT_SUCCESS(Status
))
137 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status
);
141 // initialize irp queue
142 USBSTOR_QueueInitialize(DeviceExtension
);
144 // first get device & configuration & string descriptor
145 Status
= USBSTOR_GetDescriptors(DeviceObject
);
146 if (!NT_SUCCESS(Status
))
148 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status
);
152 USBSTOR_DumpDeviceDescriptor(DeviceExtension
->DeviceDescriptor
);
155 // Check that this device uses bulk transfers and is SCSI
157 InterfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)DeviceExtension
->ConfigurationDescriptor
+ sizeof(USB_CONFIGURATION_DESCRIPTOR
));
158 ASSERT(InterfaceDesc
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
159 ASSERT(InterfaceDesc
->bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
161 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc
->bInterfaceSubClass
);
162 if (InterfaceDesc
->bInterfaceProtocol
!= 0x50)
164 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
165 return STATUS_NOT_SUPPORTED
;
168 if (InterfaceDesc
->bInterfaceSubClass
!= 0x06)
170 // FIXME: need to pad CDBs to 12 byte
171 // mode select commands must be translated from 1AH / 15h to 5AH / 55h
172 DPRINT1("[USBSTOR] Error: need to pad CDBs\n");
173 return STATUS_NOT_IMPLEMENTED
;
176 // now select an interface
177 Status
= USBSTOR_SelectConfigurationAndInterface(DeviceObject
, DeviceExtension
);
178 if (!NT_SUCCESS(Status
))
180 // failed to get device descriptor
181 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status
);
185 // check if we got a bulk in + bulk out endpoint
186 Status
= USBSTOR_GetPipeHandles(DeviceExtension
);
187 if (!NT_SUCCESS(Status
))
189 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status
);
193 Status
= USBSTOR_GetMaxLUN(DeviceExtension
->LowerDeviceObject
, DeviceExtension
);
194 if (!NT_SUCCESS(Status
))
196 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status
);
200 // now create for each LUN a device object, 1 minimum
203 Status
= USBSTOR_CreatePDO(DeviceObject
, Index
);
205 if (!NT_SUCCESS(Status
))
207 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index
, Status
);
212 DeviceExtension
->InstanceCount
++;
214 } while(Index
< DeviceExtension
->MaxLUN
);
218 // finally get usb device interface
220 Status
= USBSTOR_GetBusInterface(DeviceExtension
->LowerDeviceObject
, &DeviceExtension
->BusInterface
);
221 if (!NT_SUCCESS(Status
))
224 // failed to device interface
226 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status
);
231 //IoStartTimer(DeviceObject);
233 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
234 return STATUS_SUCCESS
;
238 USBSTOR_FdoHandlePnp(
239 IN PDEVICE_OBJECT DeviceObject
,
242 PIO_STACK_LOCATION IoStack
;
243 PFDO_DEVICE_EXTENSION DeviceExtension
;
246 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
247 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
248 ASSERT(DeviceExtension
->Common
.IsFDO
);
250 switch(IoStack
->MinorFunction
)
252 case IRP_MN_SURPRISE_REMOVAL
:
254 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject
);
255 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
257 // forward irp to next device object
258 IoSkipCurrentIrpStackLocation(Irp
);
259 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
261 case IRP_MN_QUERY_DEVICE_RELATIONS
:
263 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject
);
264 Status
= USBSTOR_FdoHandleDeviceRelations(DeviceExtension
, Irp
);
267 case IRP_MN_STOP_DEVICE
:
269 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
270 IoStopTimer(DeviceObject
);
271 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
273 // forward irp to next device object
274 IoSkipCurrentIrpStackLocation(Irp
);
275 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
277 case IRP_MN_REMOVE_DEVICE
:
279 DPRINT("IRP_MN_REMOVE_DEVICE\n");
281 return USBSTOR_FdoHandleRemoveDevice(DeviceObject
, DeviceExtension
, Irp
);
283 case IRP_MN_QUERY_CAPABILITIES
:
285 // FIXME: set custom capabilities
286 IoSkipCurrentIrpStackLocation(Irp
);
287 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
289 case IRP_MN_QUERY_STOP_DEVICE
:
290 case IRP_MN_QUERY_REMOVE_DEVICE
:
294 // we can if nothing is pending
296 if (DeviceExtension
->IrpPendingCount
!= 0 ||
297 DeviceExtension
->ActiveSrb
!= NULL
)
302 /* We have pending requests */
303 DPRINT1("Failing removal/stop request due to pending requests present\n");
304 Status
= STATUS_UNSUCCESSFUL
;
308 /* We're all clear */
309 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
311 IoSkipCurrentIrpStackLocation(Irp
);
312 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
316 case IRP_MN_START_DEVICE
:
318 Status
= USBSTOR_FdoHandleStartDevice(DeviceObject
, DeviceExtension
, Irp
);
323 // forward irp to next device object
324 IoSkipCurrentIrpStackLocation(Irp
);
325 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
329 if (Status
!= STATUS_PENDING
)
331 Irp
->IoStatus
.Status
= Status
;
332 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);