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)
18 USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor
)
20 DPRINT1("Dumping Device Descriptor %p\n", DeviceDescriptor
);
21 DPRINT1("bLength %x\n", DeviceDescriptor
->bLength
);
22 DPRINT1("bDescriptorType %x\n", DeviceDescriptor
->bDescriptorType
);
23 DPRINT1("bcdUSB %x\n", DeviceDescriptor
->bcdUSB
);
24 DPRINT1("bDeviceClass %x\n", DeviceDescriptor
->bDeviceClass
);
25 DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor
->bDeviceSubClass
);
26 DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor
->bDeviceProtocol
);
27 DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor
->bMaxPacketSize0
);
28 DPRINT1("idVendor %x\n", DeviceDescriptor
->idVendor
);
29 DPRINT1("idProduct %x\n", DeviceDescriptor
->idProduct
);
30 DPRINT1("bcdDevice %x\n", DeviceDescriptor
->bcdDevice
);
31 DPRINT1("iManufacturer %x\n", DeviceDescriptor
->iManufacturer
);
32 DPRINT1("iProduct %x\n", DeviceDescriptor
->iProduct
);
33 DPRINT1("iSerialNumber %x\n", DeviceDescriptor
->iSerialNumber
);
34 DPRINT1("bNumConfigurations %x\n", DeviceDescriptor
->bNumConfigurations
);
38 USBSTOR_FdoHandleDeviceRelations(
39 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
42 ULONG DeviceCount
= 0;
44 PDEVICE_RELATIONS DeviceRelations
;
45 PIO_STACK_LOCATION IoStack
;
48 // get current irp stack location
50 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
53 // check if relation type is BusRelations
55 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= BusRelations
)
58 // FDO always only handles bus relations
60 return USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
64 // go through array and count device objects
66 for(Index
= 0; Index
< max(DeviceExtension
->MaxLUN
, 1); Index
++)
68 if (DeviceExtension
->ChildPDO
[Index
])
78 // allocate device relations
80 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
) + (DeviceCount
> 1 ? (DeviceCount
-1) * sizeof(PDEVICE_OBJECT
) : 0));
86 return STATUS_INSUFFICIENT_RESOURCES
;
92 for(Index
= 0; Index
< max(DeviceExtension
->MaxLUN
, 1); Index
++)
94 if (DeviceExtension
->ChildPDO
[Index
])
99 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceExtension
->ChildPDO
[Index
];
104 ObReferenceObject(DeviceExtension
->ChildPDO
[Index
]);
109 DeviceRelations
->Count
++;
116 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
119 // request completed successfully
121 return STATUS_SUCCESS
;
125 USBSTOR_FdoHandleRemoveDevice(
126 IN PDEVICE_OBJECT DeviceObject
,
127 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
133 DPRINT("Handling FDO removal %p\n", DeviceObject
);
135 /* FIXME: wait for devices finished processing */
136 for(Index
= 0; Index
< 16; Index
++)
138 if (DeviceExtension
->ChildPDO
[Index
] != NULL
)
140 DPRINT("Deleting PDO %p RefCount %x AttachedDevice %p \n", DeviceExtension
->ChildPDO
[Index
], DeviceExtension
->ChildPDO
[Index
]->ReferenceCount
, DeviceExtension
->ChildPDO
[Index
]->AttachedDevice
);
141 IoDeleteDevice(DeviceExtension
->ChildPDO
[Index
]);
145 /* Send the IRP down the stack */
146 IoSkipCurrentIrpStackLocation(Irp
);
147 Status
= IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
149 /* Detach from the device stack */
150 IoDetachDevice(DeviceExtension
->LowerDeviceObject
);
152 /* Delete the device object */
153 IoDeleteDevice(DeviceObject
);
159 USBSTOR_FdoHandleStartDevice(
160 IN PDEVICE_OBJECT DeviceObject
,
161 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
164 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc
;
169 // forward irp to lower device
171 Status
= USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
172 if (!NT_SUCCESS(Status
))
177 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status
);
182 // intialize irp queue
184 USBSTOR_QueueInitialize(DeviceExtension
);
187 // first get device & configuration & string descriptor
189 Status
= USBSTOR_GetDescriptors(DeviceObject
);
190 if (!NT_SUCCESS(Status
))
193 // failed to get device descriptor
195 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status
);
200 // dump device descriptor
202 USBSTOR_DumpDeviceDescriptor(DeviceExtension
->DeviceDescriptor
);
205 // Check that this device uses bulk transfers and is SCSI
207 InterfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)DeviceExtension
->ConfigurationDescriptor
+ sizeof(USB_CONFIGURATION_DESCRIPTOR
));
212 ASSERT(InterfaceDesc
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
);
213 ASSERT(InterfaceDesc
->bLength
== sizeof(USB_INTERFACE_DESCRIPTOR
));
215 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc
->bInterfaceSubClass
);
216 if (InterfaceDesc
->bInterfaceProtocol
!= 0x50)
218 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
219 return STATUS_NOT_SUPPORTED
;
222 if (InterfaceDesc
->bInterfaceSubClass
!= 0x06)
225 // FIXME: need to pad CDBs to 12 byte
226 // mode select commands must be translated from 1AH / 15h to 5AH / 55h
228 DPRINT1("[USBSTOR] Error: need to pad CDBs\n");
229 return STATUS_NOT_IMPLEMENTED
;
233 // now select an interface
235 Status
= USBSTOR_SelectConfigurationAndInterface(DeviceObject
, DeviceExtension
);
236 if (!NT_SUCCESS(Status
))
239 // failed to get device descriptor
241 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status
);
246 // check if we got a bulk in + bulk out endpoint
248 Status
= USBSTOR_GetPipeHandles(DeviceExtension
);
249 if (!NT_SUCCESS(Status
))
252 // failed to get pipe handles descriptor
254 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status
);
259 // get num of lun which are supported
261 Status
= USBSTOR_GetMaxLUN(DeviceExtension
->LowerDeviceObject
, DeviceExtension
);
262 if (!NT_SUCCESS(Status
))
265 // failed to get max LUN
267 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status
);
272 // now create for each LUN a device object, 1 minimum
279 Status
= USBSTOR_CreatePDO(DeviceObject
, Index
);
284 if (!NT_SUCCESS(Status
))
287 // failed to create child pdo
289 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index
, Status
);
294 // increment pdo index
297 DeviceExtension
->InstanceCount
++;
299 }while(Index
< DeviceExtension
->MaxLUN
);
303 // finally get usb device interface
305 Status
= USBSTOR_GetBusInterface(DeviceExtension
->LowerDeviceObject
, &DeviceExtension
->BusInterface
);
306 if (!NT_SUCCESS(Status
))
309 // failed to device interface
311 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status
);
320 //IoStartTimer(DeviceObject);
324 // fdo is now initialized
326 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
327 return STATUS_SUCCESS
;
331 USBSTOR_FdoHandlePnp(
332 IN PDEVICE_OBJECT DeviceObject
,
335 PIO_STACK_LOCATION IoStack
;
336 PFDO_DEVICE_EXTENSION DeviceExtension
;
340 // get current stack location
342 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
345 // get device extension
347 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
352 ASSERT(DeviceExtension
->Common
.IsFDO
);
354 switch(IoStack
->MinorFunction
)
356 case IRP_MN_SURPRISE_REMOVAL
:
358 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject
);
359 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
362 // forward irp to next device object
364 IoSkipCurrentIrpStackLocation(Irp
);
365 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
367 case IRP_MN_QUERY_DEVICE_RELATIONS
:
369 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject
);
370 Status
= USBSTOR_FdoHandleDeviceRelations(DeviceExtension
, Irp
);
373 case IRP_MN_STOP_DEVICE
:
375 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
376 IoStopTimer(DeviceObject
);
377 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
380 // forward irp to next device object
382 IoSkipCurrentIrpStackLocation(Irp
);
383 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
385 case IRP_MN_REMOVE_DEVICE
:
387 DPRINT("IRP_MN_REMOVE_DEVICE\n");
389 return USBSTOR_FdoHandleRemoveDevice(DeviceObject
, DeviceExtension
, Irp
);
391 case IRP_MN_QUERY_CAPABILITIES
:
394 // FIXME: set custom capabilities
396 IoSkipCurrentIrpStackLocation(Irp
);
397 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
399 case IRP_MN_QUERY_STOP_DEVICE
:
400 case IRP_MN_QUERY_REMOVE_DEVICE
:
404 // we can if nothing is pending
406 if (DeviceExtension
->IrpPendingCount
!= 0 ||
407 DeviceExtension
->ActiveSrb
!= NULL
)
412 /* We have pending requests */
413 DPRINT1("Failing removal/stop request due to pending requests present\n");
414 Status
= STATUS_UNSUCCESSFUL
;
418 /* We're all clear */
419 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
421 IoSkipCurrentIrpStackLocation(Irp
);
422 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
426 case IRP_MN_START_DEVICE
:
428 Status
= USBSTOR_FdoHandleStartDevice(DeviceObject
, DeviceExtension
, Irp
);
434 // forward irp to next device object
436 IoSkipCurrentIrpStackLocation(Irp
);
437 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
444 if (Status
!= STATUS_PENDING
)
449 Irp
->IoStatus
.Status
= Status
;
454 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);