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
,
129 DPRINT1("Handling FDO removal\n");
131 /* We don't need to request removal of our children here */
133 /* Send the IRP down the stack */
134 IoSkipCurrentIrpStackLocation(Irp
);
135 Status
= IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
137 /* Detach from the device stack */
138 /* IoDetachDevice(DeviceExtension->LowerDeviceObject); */ //This crashes for some reason during unload
140 /* Delete the device object */
141 IoDeleteDevice(DeviceObject
);
147 USBSTOR_FdoHandleStartDevice(
148 IN PDEVICE_OBJECT DeviceObject
,
149 IN PFDO_DEVICE_EXTENSION DeviceExtension
,
152 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc
;
157 // forward irp to lower device
159 Status
= USBSTOR_SyncForwardIrp(DeviceExtension
->LowerDeviceObject
, Irp
);
160 if (!NT_SUCCESS(Status
))
165 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status
);
170 // intialize irp queue
172 USBSTOR_QueueInitialize(DeviceExtension
);
175 // first get device & configuration & string descriptor
177 Status
= USBSTOR_GetDescriptors(DeviceObject
);
178 if (!NT_SUCCESS(Status
))
181 // failed to get device descriptor
183 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status
);
188 // dump device descriptor
190 USBSTOR_DumpDeviceDescriptor(DeviceExtension
->DeviceDescriptor
);
193 // Check that this device uses bulk transfers and is SCSI
195 InterfaceDesc
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)DeviceExtension
->ConfigurationDescriptor
+ sizeof(USB_CONFIGURATION_DESCRIPTOR
));
196 DPRINT1("bInterfaceSubClass %x\n", InterfaceDesc
->bInterfaceSubClass
);
197 if (InterfaceDesc
->bInterfaceProtocol
!= 0x50)
199 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
200 return STATUS_NOT_SUPPORTED
;
205 // now select an interface
207 Status
= USBSTOR_SelectConfigurationAndInterface(DeviceObject
, DeviceExtension
);
208 if (!NT_SUCCESS(Status
))
211 // failed to get device descriptor
213 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status
);
218 // check if we got a bulk in + bulk out endpoint
220 Status
= USBSTOR_GetPipeHandles(DeviceExtension
);
221 if (!NT_SUCCESS(Status
))
224 // failed to get pipe handles descriptor
226 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status
);
231 // get num of lun which are supported
233 Status
= USBSTOR_GetMaxLUN(DeviceExtension
->LowerDeviceObject
, DeviceExtension
);
234 if (!NT_SUCCESS(Status
))
237 // failed to get max LUN
239 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status
);
244 // now create for each LUN a device object, 1 minimum
251 Status
= USBSTOR_CreatePDO(DeviceObject
, &DeviceExtension
->ChildPDO
[Index
]);
256 if (!NT_SUCCESS(Status
))
259 // failed to create child pdo
261 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index
, Status
);
266 // increment pdo index
270 }while(Index
< DeviceExtension
->MaxLUN
);
274 // finally get usb device interface
276 Status
= USBSTOR_GetBusInterface(DeviceExtension
->LowerDeviceObject
, &DeviceExtension
->BusInterface
);
277 if (!NT_SUCCESS(Status
))
280 // failed to device interface
282 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status
);
288 // fdo is now initialized
290 DPRINT1("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
291 return STATUS_SUCCESS
;
295 USBSTOR_FdoHandlePnp(
296 IN PDEVICE_OBJECT DeviceObject
,
299 PIO_STACK_LOCATION IoStack
;
300 PFDO_DEVICE_EXTENSION DeviceExtension
;
304 // get current stack location
306 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
309 // get device extension
311 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
316 ASSERT(DeviceExtension
->Common
.IsFDO
);
318 switch(IoStack
->MinorFunction
)
320 case IRP_MN_QUERY_DEVICE_RELATIONS
:
322 Status
= USBSTOR_FdoHandleDeviceRelations(DeviceExtension
, Irp
);
325 case IRP_MN_STOP_DEVICE
:
326 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
327 Status
= STATUS_NOT_SUPPORTED
;
329 case IRP_MN_REMOVE_DEVICE
:
331 DPRINT1("IRP_MN_REMOVE_DEVICE\n");
333 return USBSTOR_FdoHandleRemoveDevice(DeviceObject
, DeviceExtension
, Irp
);
335 case IRP_MN_QUERY_CAPABILITIES
:
338 // FIXME: set custom capabilities
340 IoSkipCurrentIrpStackLocation(Irp
);
341 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
343 case IRP_MN_START_DEVICE
:
345 Status
= USBSTOR_FdoHandleStartDevice(DeviceObject
, DeviceExtension
, Irp
);
351 // forward irp to next device object
353 IoSkipCurrentIrpStackLocation(Irp
);
354 return IoCallDriver(DeviceExtension
->LowerDeviceObject
, Irp
);
361 if (Status
!= STATUS_PENDING
)
366 Irp
->IoStatus
.Status
= Status
;
371 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);