2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbstor/fdo.c
5 * PURPOSE: USB block storage device driver.
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
15 USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
17 DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor
);
18 DPRINT1("bLength %x\n", DeviceDescriptor
->bLength
);
19 DPRINT1("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
20 DPRINT1("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
21 DPRINT1("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
22 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
23 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
24 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
25 DPRINT1("idVendor %x\n", DeviceDescriptor
->idVendor
);
26 DPRINT1("idProduct %x\n", DeviceDescriptor
->idProduct
);
27 DPRINT1("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
28 DPRINT1("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
29 DPRINT1("iProduct %x\n", DeviceDescriptor
->iProduct
);
30 DPRINT1("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
31 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
35 USBSTOR_FdoHandleDeviceRelations(
36 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
39 ULONG DeviceCount
= 0;
41 PDEVICE_RELATIONS DeviceRelations
;
42 PIO_STACK_LOCATION IoStack
;
45 // get current irp stack location
47 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
50 // check if relation type is BusRelations
52 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= BusRelations
)
55 // FDO always only handles bus relations
57 return USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
61 // go through array and count device objects
63 for(Index
= 0; Index
< max(DeviceExtension
->MaxLUN
, 1); Index
++)
65 if (DeviceExtension
->ChildPDO
[Index
])
75 // allocate device relations
77 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
) + (DeviceCount
> 1 ? (DeviceCount
-1) * sizeof(PDEVICE_OBJECT
) : 0));
83 return STATUS_INSUFFICIENT_RESOURCES
;
89 for(Index
= 0; Index
< max(DeviceExtension
->MaxLUN
, 1); Index
++)
91 if (DeviceExtension
->ChildPDO
[Index
])
96 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceExtension
->ChildPDO
[Index
];
101 ObReferenceObject(DeviceExtension
->ChildPDO
[Index
]);
106 DeviceRelations
->Count
++;
113 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
116 // request completed successfully
118 return STATUS_SUCCESS
;
122 USBSTOR_FdoHandleRemoveDevice(
123 IN PDEVICE_OBJECT DeviceObject
,
124 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
130 DPRINT("Handling FDO removal %p\n", DeviceObject
);
132 /* FIXME: wait for devices finished processing */
133 for(Index
= 0; Index
< 16; Index
++)
135 if (DeviceExtension
->ChildPDO
[Index
] != NULL
)
137 DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension
->ChildPDO
[Index
], DeviceExtension
->ChildPDO
[Index
]->ReferenceCount
, DeviceExtension
->ChildPDO
[Index
]->AttachedDevice
);
138 IoDeleteDevice(DeviceExtension
->ChildPDO
[Index
]);
142 /* Send the IRP down the stack */
143 IoSkipCurrentIrpStackLocation(Irp
);
144 Status
= IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
146 /* Detach from the device stack */
147 IoDetachDevice(DeviceExtension
->LowerDeviceObject
);
149 /* Delete the device object */
150 IoDeleteDevice(DeviceObject
);
156 USBSTOR_FdoHandleStartDevice(
157 IN PDEVICE_OBJECT DeviceObject
,
158 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
161 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc
;
166 // forward irp to lower device
168 Status
= USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
169 if (!NT_SUCCESS(Status
))
174 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status
);
179 // intialize irp queue
181 USBSTOR_QueueInitialize(DeviceExtension
);
184 // first get device & configuration & string descriptor
186 Status
= USBSTOR_GetDescriptors(DeviceObject
);
187 if (!NT_SUCCESS(Status
))
190 // failed to get device descriptor
192 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status
);
197 // dump device descriptor
199 USBSTOR_DumpDeviceDescriptor(DeviceExtension
->DeviceDescriptor
);
202 // Check that this device uses bulk transfers and is SCSI
204 InterfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)DeviceExtension
->ConfigurationDescriptor
+ sizeof(USB_CONFIGURATION_DESCRIPTOR
));
209 ASSERT(InterfaceDesc
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
210 ASSERT(InterfaceDesc
->bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
212 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc
->bInterfaceSubClass
);
213 if (InterfaceDesc
->bInterfaceProtocol
!= 0x50)
215 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
216 return STATUS_NOT_SUPPORTED
;
219 if (InterfaceDesc
->bInterfaceSubClass
!= 0x06)
222 // FIXME: need to pad CDBs to 12 byte
223 // mode select commands must be translated from 1AH / 15h to 5AH / 55h
225 DPRINT1("[USBSTOR] Error: need to pad CDBs\n");
226 return STATUS_NOT_IMPLEMENTED
;
230 // now select an interface
232 Status
= USBSTOR_SelectConfigurationAndInterface(DeviceObject
, DeviceExtension
);
233 if (!NT_SUCCESS(Status
))
236 // failed to get device descriptor
238 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status
);
243 // check if we got a bulk in + bulk out endpoint
245 Status
= USBSTOR_GetPipeHandles(DeviceExtension
);
246 if (!NT_SUCCESS(Status
))
249 // failed to get pipe handles descriptor
251 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status
);
256 // get num of lun which are supported
258 Status
= USBSTOR_GetMaxLUN(DeviceExtension
->LowerDeviceObject
, DeviceExtension
);
259 if (!NT_SUCCESS(Status
))
262 // failed to get max LUN
264 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status
);
269 // now create for each LUN a device object, 1 minimum
276 Status
= USBSTOR_CreatePDO(DeviceObject
, Index
);
281 if (!NT_SUCCESS(Status
))
284 // failed to create child pdo
286 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index
, Status
);
291 // increment pdo index
294 DeviceExtension
->InstanceCount
++;
296 }while(Index
< DeviceExtension
->MaxLUN
);
300 // finally get usb device interface
302 Status
= USBSTOR_GetBusInterface(DeviceExtension
->LowerDeviceObject
, &DeviceExtension
->BusInterface
);
303 if (!NT_SUCCESS(Status
))
306 // failed to device interface
308 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status
);
317 //IoStartTimer(DeviceObject);
321 // fdo is now initialized
323 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
324 return STATUS_SUCCESS
;
328 USBSTOR_FdoHandlePnp(
329 IN PDEVICE_OBJECT DeviceObject
,
332 PIO_STACK_LOCATION IoStack
;
333 PFDO_DEVICE_EXTENSION DeviceExtension
;
337 // get current stack location
339 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
342 // get device extension
344 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
349 ASSERT(DeviceExtension
->Common
.IsFDO
);
351 switch(IoStack
->MinorFunction
)
353 case IRP_MN_SURPRISE_REMOVAL
:
355 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject
);
356 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
359 // forward irp to next device object
361 IoSkipCurrentIrpStackLocation(Irp
);
362 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
364 case IRP_MN_QUERY_DEVICE_RELATIONS
:
366 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject
);
367 Status
= USBSTOR_FdoHandleDeviceRelations(DeviceExtension
, Irp
);
370 case IRP_MN_STOP_DEVICE
:
372 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
373 IoStopTimer(DeviceObject
);
374 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
377 // forward irp to next device object
379 IoSkipCurrentIrpStackLocation(Irp
);
380 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
382 case IRP_MN_REMOVE_DEVICE
:
384 DPRINT("IRP_MN_REMOVE_DEVICE\n");
386 return USBSTOR_FdoHandleRemoveDevice(DeviceObject
, DeviceExtension
, Irp
);
388 case IRP_MN_QUERY_CAPABILITIES
:
391 // FIXME: set custom capabilities
393 IoSkipCurrentIrpStackLocation(Irp
);
394 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
396 case IRP_MN_QUERY_STOP_DEVICE
:
397 case IRP_MN_QUERY_REMOVE_DEVICE
:
401 // we can if nothing is pending
403 if (DeviceExtension
->IrpPendingCount
!= 0 ||
404 DeviceExtension
->ActiveSrb
!= NULL
)
409 /* We have pending requests */
410 DPRINT1("Failing removal/stop request due to pending requests present\n");
411 Status
= STATUS_UNSUCCESSFUL
;
415 /* We're all clear */
416 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
418 IoSkipCurrentIrpStackLocation(Irp
);
419 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
423 case IRP_MN_START_DEVICE
:
425 Status
= USBSTOR_FdoHandleStartDevice(DeviceObject
, DeviceExtension
, Irp
);
431 // forward irp to next device object
433 IoSkipCurrentIrpStackLocation(Irp
);
434 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
441 if (Status
!= STATUS_PENDING
)
446 Irp
->IoStatus
.Status
= Status
;
451 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);