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 Status
= USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
164 if (!NT_SUCCESS(Status
))
166 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status
);
170 if (!DeviceExtension
->ResetDeviceWorkItem
)
172 WorkItem
= IoAllocateWorkItem(DeviceObject
);
173 DeviceExtension
->ResetDeviceWorkItem
= WorkItem
;
177 return STATUS_INSUFFICIENT_RESOURCES
;
181 // initialize irp queue
182 USBSTOR_QueueInitialize(DeviceExtension
);
184 // first get device & configuration & string descriptor
185 Status
= USBSTOR_GetDescriptors(DeviceObject
);
186 if (!NT_SUCCESS(Status
))
188 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status
);
193 USBSTOR_DumpDeviceDescriptor(DeviceExtension
->DeviceDescriptor
);
196 // Check that this device uses bulk transfers and is SCSI
198 InterfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)DeviceExtension
->ConfigurationDescriptor
+ sizeof(USB_CONFIGURATION_DESCRIPTOR
));
199 ASSERT(InterfaceDesc
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
200 ASSERT(InterfaceDesc
->bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
202 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc
->bInterfaceSubClass
);
203 if (InterfaceDesc
->bInterfaceProtocol
!= USB_PROTOCOL_BULK
)
205 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
206 return STATUS_NOT_SUPPORTED
;
209 if (InterfaceDesc
->bInterfaceSubClass
== USB_SUBCLASS_UFI
)
211 DPRINT1("USB Floppy devices are not supported\n");
212 return STATUS_NOT_SUPPORTED
;
215 // now select an interface
216 Status
= USBSTOR_SelectConfigurationAndInterface(DeviceObject
, DeviceExtension
);
217 if (!NT_SUCCESS(Status
))
219 // failed to get device descriptor
220 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status
);
224 // check if we got a bulk in + bulk out endpoint
225 Status
= USBSTOR_GetPipeHandles(DeviceExtension
);
226 if (!NT_SUCCESS(Status
))
228 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status
);
232 Status
= USBSTOR_GetMaxLUN(DeviceExtension
->LowerDeviceObject
, DeviceExtension
);
233 if (!NT_SUCCESS(Status
))
235 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status
);
239 // now create for each LUN a device object, 1 minimum
242 Status
= USBSTOR_CreatePDO(DeviceObject
, Index
);
244 if (!NT_SUCCESS(Status
))
246 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index
, Status
);
251 DeviceExtension
->InstanceCount
++;
253 } while(Index
< DeviceExtension
->MaxLUN
);
257 // finally get usb device interface
259 Status
= USBSTOR_GetBusInterface(DeviceExtension
->LowerDeviceObject
, &DeviceExtension
->BusInterface
);
260 if (!NT_SUCCESS(Status
))
263 // failed to device interface
265 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status
);
270 //IoStartTimer(DeviceObject);
272 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
273 return STATUS_SUCCESS
;
277 USBSTOR_FdoHandlePnp(
278 IN PDEVICE_OBJECT DeviceObject
,
281 PIO_STACK_LOCATION IoStack
;
282 PFDO_DEVICE_EXTENSION DeviceExtension
;
285 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
286 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
287 ASSERT(DeviceExtension
->Common
.IsFDO
);
289 switch(IoStack
->MinorFunction
)
291 case IRP_MN_SURPRISE_REMOVAL
:
293 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject
);
294 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
296 // forward irp to next device object
297 IoSkipCurrentIrpStackLocation(Irp
);
298 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
300 case IRP_MN_QUERY_DEVICE_RELATIONS
:
302 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p Type: %u\n", DeviceObject
, IoStack
->Parameters
.QueryDeviceRelations
.Type
);
303 return USBSTOR_FdoHandleDeviceRelations(DeviceExtension
, Irp
);
305 case IRP_MN_STOP_DEVICE
:
307 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
308 IoStopTimer(DeviceObject
);
309 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
311 // forward irp to next device object
312 IoSkipCurrentIrpStackLocation(Irp
);
313 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
315 case IRP_MN_REMOVE_DEVICE
:
317 DPRINT("IRP_MN_REMOVE_DEVICE\n");
319 return USBSTOR_FdoHandleRemoveDevice(DeviceObject
, DeviceExtension
, Irp
);
321 case IRP_MN_QUERY_CAPABILITIES
:
323 // FIXME: set custom capabilities
324 IoSkipCurrentIrpStackLocation(Irp
);
325 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
327 case IRP_MN_QUERY_STOP_DEVICE
:
328 case IRP_MN_QUERY_REMOVE_DEVICE
:
332 // we can if nothing is pending
334 if (DeviceExtension
->IrpPendingCount
!= 0 ||
335 DeviceExtension
->ActiveSrb
!= NULL
)
340 /* We have pending requests */
341 DPRINT1("Failing removal/stop request due to pending requests present\n");
342 Status
= STATUS_UNSUCCESSFUL
;
346 /* We're all clear */
347 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
349 IoSkipCurrentIrpStackLocation(Irp
);
350 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
354 case IRP_MN_START_DEVICE
:
356 Status
= USBSTOR_FdoHandleStartDevice(DeviceObject
, DeviceExtension
, Irp
);
361 // forward irp to next device object
362 IoSkipCurrentIrpStackLocation(Irp
);
363 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
367 if (Status
!= STATUS_PENDING
)
369 Irp
->IoStatus
.Status
= Status
;
370 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);