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)
8 * 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
20 USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
22 DPRINT("Dumping Device Descriptor %p\n", DeviceDescriptor
);
23 DPRINT("bLength %x\n", DeviceDescriptor
->bLength
);
24 DPRINT("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
25 DPRINT("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
26 DPRINT("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
27 DPRINT("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
28 DPRINT("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
29 DPRINT("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
30 DPRINT("idVendor %x\n", DeviceDescriptor
->idVendor
);
31 DPRINT("idProduct %x\n", DeviceDescriptor
->idProduct
);
32 DPRINT("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
33 DPRINT("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
34 DPRINT("iProduct %x\n", DeviceDescriptor
->iProduct
);
35 DPRINT("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
36 DPRINT("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
41 USBSTOR_FdoHandleDeviceRelations(
42 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
45 INT32 DeviceCount
= 0;
47 PDEVICE_RELATIONS DeviceRelations
;
48 PIO_STACK_LOCATION IoStack
;
50 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
52 // FDO always only handles bus relations
53 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
== BusRelations
)
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
= ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
) + (DeviceCount
- 1) * sizeof(PDEVICE_OBJECT
), USB_STOR_TAG
);
67 Irp
->IoStatus
.Information
= 0;
68 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
69 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
70 return STATUS_INSUFFICIENT_RESOURCES
;
73 DeviceRelations
->Count
= 0;
76 for (Index
= 0; Index
< max(DeviceExtension
->MaxLUN
, 1); Index
++)
78 if (DeviceExtension
->ChildPDO
[Index
])
81 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceExtension
->ChildPDO
[Index
];
84 ObReferenceObject(DeviceExtension
->ChildPDO
[Index
]);
86 DeviceRelations
->Count
++;
90 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
91 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
94 IoCopyCurrentIrpStackLocationToNext(Irp
);
96 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
100 USBSTOR_FdoHandleRemoveDevice(
101 IN PDEVICE_OBJECT DeviceObject
,
102 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
108 DPRINT("Handling FDO removal %p\n", DeviceObject
);
110 // FIXME: wait for devices finished processing
111 for (Index
= 0; Index
< USB_MAXCHILDREN
; Index
++)
113 if (DeviceExtension
->ChildPDO
[Index
] != NULL
)
115 DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension
->ChildPDO
[Index
], DeviceExtension
->ChildPDO
[Index
]->ReferenceCount
, DeviceExtension
->ChildPDO
[Index
]->AttachedDevice
);
116 IoDeleteDevice(DeviceExtension
->ChildPDO
[Index
]);
120 // Freeing everything in DeviceExtension
122 DeviceExtension
->DeviceDescriptor
&&
123 DeviceExtension
->ConfigurationDescriptor
&&
124 DeviceExtension
->InterfaceInformation
&&
125 DeviceExtension
->ResetDeviceWorkItem
128 ExFreePoolWithTag(DeviceExtension
->DeviceDescriptor
, USB_STOR_TAG
);
129 ExFreePoolWithTag(DeviceExtension
->ConfigurationDescriptor
, USB_STOR_TAG
);
130 ExFreePoolWithTag(DeviceExtension
->InterfaceInformation
, USB_STOR_TAG
);
131 IoFreeWorkItem(DeviceExtension
->ResetDeviceWorkItem
);
133 if (DeviceExtension
->SerialNumber
)
135 ExFreePoolWithTag(DeviceExtension
->SerialNumber
, USB_STOR_TAG
);
138 // Send the IRP down the stack
139 IoSkipCurrentIrpStackLocation(Irp
);
140 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
141 Status
= IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
143 // Detach from the device stack
144 IoDetachDevice(DeviceExtension
->LowerDeviceObject
);
146 IoDeleteDevice(DeviceObject
);
152 USBSTOR_FdoHandleStartDevice(
153 IN PDEVICE_OBJECT DeviceObject
,
154 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
157 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc
;
160 PIO_WORKITEM WorkItem
;
162 // forward irp to lower device
163 if (!IoForwardIrpSynchronously(DeviceExtension
->LowerDeviceObject
, Irp
))
165 return STATUS_UNSUCCESSFUL
;
168 Status
= Irp
->IoStatus
.Status
;
169 if (!NT_SUCCESS(Status
))
171 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status
);
175 if (!DeviceExtension
->ResetDeviceWorkItem
)
177 WorkItem
= IoAllocateWorkItem(DeviceObject
);
178 DeviceExtension
->ResetDeviceWorkItem
= WorkItem
;
182 return STATUS_INSUFFICIENT_RESOURCES
;
186 // initialize irp queue
187 USBSTOR_QueueInitialize(DeviceExtension
);
189 // first get device & configuration & string descriptor
190 Status
= USBSTOR_GetDescriptors(DeviceObject
);
191 if (!NT_SUCCESS(Status
))
193 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status
);
198 USBSTOR_DumpDeviceDescriptor(DeviceExtension
->DeviceDescriptor
);
201 // Check that this device uses bulk transfers and is SCSI
203 InterfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)DeviceExtension
->ConfigurationDescriptor
+ sizeof(USB_CONFIGURATION_DESCRIPTOR
));
204 ASSERT(InterfaceDesc
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
205 ASSERT(InterfaceDesc
->bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
207 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc
->bInterfaceSubClass
);
208 if (InterfaceDesc
->bInterfaceProtocol
!= USB_PROTOCOL_BULK
)
210 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
211 return STATUS_NOT_SUPPORTED
;
214 if (InterfaceDesc
->bInterfaceSubClass
== USB_SUBCLASS_UFI
)
216 DPRINT1("USB Floppy devices are not supported\n");
217 return STATUS_NOT_SUPPORTED
;
220 // now select an interface
221 Status
= USBSTOR_SelectConfigurationAndInterface(DeviceObject
, DeviceExtension
);
222 if (!NT_SUCCESS(Status
))
224 // failed to get device descriptor
225 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status
);
229 // check if we got a bulk in + bulk out endpoint
230 Status
= USBSTOR_GetPipeHandles(DeviceExtension
);
231 if (!NT_SUCCESS(Status
))
233 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status
);
237 Status
= USBSTOR_GetMaxLUN(DeviceExtension
->LowerDeviceObject
, DeviceExtension
);
238 if (!NT_SUCCESS(Status
))
240 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status
);
244 // now create for each LUN a device object, 1 minimum
247 Status
= USBSTOR_CreatePDO(DeviceObject
, Index
);
249 if (!NT_SUCCESS(Status
))
251 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index
, Status
);
256 DeviceExtension
->InstanceCount
++;
258 } while(Index
< DeviceExtension
->MaxLUN
);
262 // finally get usb device interface
264 Status
= USBSTOR_GetBusInterface(DeviceExtension
->LowerDeviceObject
, &DeviceExtension
->BusInterface
);
265 if (!NT_SUCCESS(Status
))
268 // failed to device interface
270 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status
);
275 //IoStartTimer(DeviceObject);
277 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
278 return STATUS_SUCCESS
;
282 USBSTOR_FdoHandlePnp(
283 IN PDEVICE_OBJECT DeviceObject
,
286 PIO_STACK_LOCATION IoStack
;
287 PFDO_DEVICE_EXTENSION DeviceExtension
;
290 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
291 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
292 ASSERT(DeviceExtension
->Common
.IsFDO
);
294 switch(IoStack
->MinorFunction
)
296 case IRP_MN_SURPRISE_REMOVAL
:
298 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject
);
299 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
301 // forward irp to next device object
302 IoSkipCurrentIrpStackLocation(Irp
);
303 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
305 case IRP_MN_QUERY_DEVICE_RELATIONS
:
307 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p Type: %u\n", DeviceObject
, IoStack
->Parameters
.QueryDeviceRelations
.Type
);
308 return USBSTOR_FdoHandleDeviceRelations(DeviceExtension
, Irp
);
310 case IRP_MN_STOP_DEVICE
:
312 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
313 IoStopTimer(DeviceObject
);
314 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
316 // forward irp to next device object
317 IoSkipCurrentIrpStackLocation(Irp
);
318 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
320 case IRP_MN_REMOVE_DEVICE
:
322 DPRINT("IRP_MN_REMOVE_DEVICE\n");
324 return USBSTOR_FdoHandleRemoveDevice(DeviceObject
, DeviceExtension
, Irp
);
326 case IRP_MN_QUERY_CAPABILITIES
:
328 // FIXME: set custom capabilities
329 IoSkipCurrentIrpStackLocation(Irp
);
330 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
332 case IRP_MN_QUERY_STOP_DEVICE
:
333 case IRP_MN_QUERY_REMOVE_DEVICE
:
335 if (DeviceExtension
->IrpPendingCount
!= 0 || DeviceExtension
->ActiveSrb
!= NULL
)
337 /* We have pending requests */
338 DPRINT1("Failing removal/stop request due to pending requests present\n");
339 Status
= STATUS_UNSUCCESSFUL
;
343 /* We're all clear */
344 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
346 IoSkipCurrentIrpStackLocation(Irp
);
347 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
351 case IRP_MN_START_DEVICE
:
353 Status
= USBSTOR_FdoHandleStartDevice(DeviceObject
, DeviceExtension
, Irp
);
358 // forward irp to next device object
359 IoSkipCurrentIrpStackLocation(Irp
);
360 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
364 if (Status
!= STATUS_PENDING
)
366 Irp
->IoStatus
.Status
= Status
;
367 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);