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
;
132 PIO_WORKITEM WorkItem
;
134 // forward irp to lower device
135 Status
= USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
136 if (!NT_SUCCESS(Status
))
138 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status
);
142 if (!DeviceExtension
->ResetDeviceWorkItem
)
144 WorkItem
= IoAllocateWorkItem(DeviceObject
);
145 DeviceExtension
->ResetDeviceWorkItem
= WorkItem
;
149 return STATUS_INSUFFICIENT_RESOURCES
;
153 // initialize irp queue
154 USBSTOR_QueueInitialize(DeviceExtension
);
156 // first get device & configuration & string descriptor
157 Status
= USBSTOR_GetDescriptors(DeviceObject
);
158 if (!NT_SUCCESS(Status
))
160 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status
);
164 USBSTOR_DumpDeviceDescriptor(DeviceExtension
->DeviceDescriptor
);
167 // Check that this device uses bulk transfers and is SCSI
169 InterfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)DeviceExtension
->ConfigurationDescriptor
+ sizeof(USB_CONFIGURATION_DESCRIPTOR
));
170 ASSERT(InterfaceDesc
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
171 ASSERT(InterfaceDesc
->bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
173 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc
->bInterfaceSubClass
);
174 if (InterfaceDesc
->bInterfaceProtocol
!= 0x50)
176 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
177 return STATUS_NOT_SUPPORTED
;
180 if (InterfaceDesc
->bInterfaceSubClass
== 0x04) // UFI subclass
182 // FIXME: need to pad CDBs to 12 byte
183 // mode select commands must be translated from 1AH / 15h to 5AH / 55h
184 DPRINT1("[USBSTOR] Error: need to pad CDBs\n");
185 return STATUS_NOT_SUPPORTED
;
188 // now select an interface
189 Status
= USBSTOR_SelectConfigurationAndInterface(DeviceObject
, DeviceExtension
);
190 if (!NT_SUCCESS(Status
))
192 // failed to get device descriptor
193 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status
);
197 // check if we got a bulk in + bulk out endpoint
198 Status
= USBSTOR_GetPipeHandles(DeviceExtension
);
199 if (!NT_SUCCESS(Status
))
201 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status
);
205 Status
= USBSTOR_GetMaxLUN(DeviceExtension
->LowerDeviceObject
, DeviceExtension
);
206 if (!NT_SUCCESS(Status
))
208 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status
);
212 // now create for each LUN a device object, 1 minimum
215 Status
= USBSTOR_CreatePDO(DeviceObject
, Index
);
217 if (!NT_SUCCESS(Status
))
219 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index
, Status
);
224 DeviceExtension
->InstanceCount
++;
226 } while(Index
< DeviceExtension
->MaxLUN
);
230 // finally get usb device interface
232 Status
= USBSTOR_GetBusInterface(DeviceExtension
->LowerDeviceObject
, &DeviceExtension
->BusInterface
);
233 if (!NT_SUCCESS(Status
))
236 // failed to device interface
238 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status
);
243 //IoStartTimer(DeviceObject);
245 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
246 return STATUS_SUCCESS
;
250 USBSTOR_FdoHandlePnp(
251 IN PDEVICE_OBJECT DeviceObject
,
254 PIO_STACK_LOCATION IoStack
;
255 PFDO_DEVICE_EXTENSION DeviceExtension
;
258 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
259 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
260 ASSERT(DeviceExtension
->Common
.IsFDO
);
262 switch(IoStack
->MinorFunction
)
264 case IRP_MN_SURPRISE_REMOVAL
:
266 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject
);
267 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
269 // forward irp to next device object
270 IoSkipCurrentIrpStackLocation(Irp
);
271 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
273 case IRP_MN_QUERY_DEVICE_RELATIONS
:
275 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject
);
276 Status
= USBSTOR_FdoHandleDeviceRelations(DeviceExtension
, Irp
);
279 case IRP_MN_STOP_DEVICE
:
281 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
282 IoStopTimer(DeviceObject
);
283 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
285 // forward irp to next device object
286 IoSkipCurrentIrpStackLocation(Irp
);
287 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
289 case IRP_MN_REMOVE_DEVICE
:
291 DPRINT("IRP_MN_REMOVE_DEVICE\n");
293 return USBSTOR_FdoHandleRemoveDevice(DeviceObject
, DeviceExtension
, Irp
);
295 case IRP_MN_QUERY_CAPABILITIES
:
297 // FIXME: set custom capabilities
298 IoSkipCurrentIrpStackLocation(Irp
);
299 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
301 case IRP_MN_QUERY_STOP_DEVICE
:
302 case IRP_MN_QUERY_REMOVE_DEVICE
:
306 // we can if nothing is pending
308 if (DeviceExtension
->IrpPendingCount
!= 0 ||
309 DeviceExtension
->ActiveSrb
!= NULL
)
314 /* We have pending requests */
315 DPRINT1("Failing removal/stop request due to pending requests present\n");
316 Status
= STATUS_UNSUCCESSFUL
;
320 /* We're all clear */
321 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
323 IoSkipCurrentIrpStackLocation(Irp
);
324 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
328 case IRP_MN_START_DEVICE
:
330 Status
= USBSTOR_FdoHandleStartDevice(DeviceObject
, DeviceExtension
, Irp
);
335 // forward irp to next device object
336 IoSkipCurrentIrpStackLocation(Irp
);
337 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
341 if (Status
!= STATUS_PENDING
)
343 Irp
->IoStatus
.Status
= Status
;
344 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);