ReactOS 0.4.16-dev-197-g92996da
fdo.c
Go to the documentation of this file.
1/*
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)
9 */
10
11#include "usbstor.h"
12
13#define NDEBUG
14#include <debug.h>
15
16
17#if DBG
18static
19VOID
21{
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);
37}
38#endif
39
42 IN PFDO_DEVICE_EXTENSION DeviceExtension,
43 IN OUT PIRP Irp)
44{
46 LONG Index;
47 PDEVICE_RELATIONS DeviceRelations;
48 PIO_STACK_LOCATION IoStack;
49
51
52 // FDO always only handles bus relations
53 if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
54 {
55 // go through array and count device objects
56 for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
57 {
58 if (DeviceExtension->ChildPDO[Index])
59 {
61 }
62 }
63
64 DeviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount - 1) * sizeof(PDEVICE_OBJECT), USB_STOR_TAG);
65 if (!DeviceRelations)
66 {
67 Irp->IoStatus.Information = 0;
68 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
71 }
72
73 DeviceRelations->Count = 0;
74
75 // add device objects
76 for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
77 {
78 if (DeviceExtension->ChildPDO[Index])
79 {
80 // store child pdo
81 DeviceRelations->Objects[DeviceRelations->Count] = DeviceExtension->ChildPDO[Index];
82
83 // add reference
84 ObReferenceObject(DeviceExtension->ChildPDO[Index]);
85
86 DeviceRelations->Count++;
87 }
88 }
89
90 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
91 Irp->IoStatus.Status = STATUS_SUCCESS;
92 }
93
95
96 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
97}
98
102 IN PFDO_DEVICE_EXTENSION DeviceExtension,
103 IN OUT PIRP Irp)
104{
106 ULONG Index;
107
108 DPRINT("Handling FDO removal %p\n", DeviceObject);
109
110 // FIXME: wait for devices finished processing
111 for (Index = 0; Index < USB_MAXCHILDREN; Index++)
112 {
113 if (DeviceExtension->ChildPDO[Index] != NULL)
114 {
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]);
117 }
118 }
119
120 // Freeing everything in DeviceExtension
121 if (DeviceExtension->DeviceDescriptor)
122 ExFreePoolWithTag(DeviceExtension->DeviceDescriptor, USB_STOR_TAG);
123 if (DeviceExtension->ConfigurationDescriptor)
124 ExFreePoolWithTag(DeviceExtension->ConfigurationDescriptor, USB_STOR_TAG);
125 if (DeviceExtension->InterfaceInformation)
126 ExFreePoolWithTag(DeviceExtension->InterfaceInformation, USB_STOR_TAG);
127 if (DeviceExtension->ResetDeviceWorkItem)
128 IoFreeWorkItem(DeviceExtension->ResetDeviceWorkItem);
129 if (DeviceExtension->SerialNumber)
130 ExFreePoolWithTag(DeviceExtension->SerialNumber, USB_STOR_TAG);
131
132 // Send the IRP down the stack
134 Irp->IoStatus.Status = STATUS_SUCCESS;
135 Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
136
137 // Detach from the device stack
138 IoDetachDevice(DeviceExtension->LowerDeviceObject);
139
141
142 return Status;
143}
144
148 IN PFDO_DEVICE_EXTENSION DeviceExtension,
149 IN OUT PIRP Irp)
150{
153 UCHAR Index = 0;
155
156 // forward irp to lower device
157 if (!IoForwardIrpSynchronously(DeviceExtension->LowerDeviceObject, Irp))
158 {
159 return STATUS_UNSUCCESSFUL;
160 }
161
162 Status = Irp->IoStatus.Status;
163 if (!NT_SUCCESS(Status))
164 {
165 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status);
166 return Status;
167 }
168
169 if (!DeviceExtension->ResetDeviceWorkItem)
170 {
172 DeviceExtension->ResetDeviceWorkItem = WorkItem;
173
174 if (!WorkItem)
175 {
177 }
178 }
179
180 // initialize irp queue
181 USBSTOR_QueueInitialize(DeviceExtension);
182
183 // first get device & configuration & string descriptor
185 if (!NT_SUCCESS(Status))
186 {
187 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status);
188 return Status;
189 }
190
191#if DBG
192 USBSTOR_DumpDeviceDescriptor(DeviceExtension->DeviceDescriptor);
193#endif
194
195 // Check that this device uses bulk transfers and is SCSI
196
197 InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)DeviceExtension->ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR));
199 ASSERT(InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
200
201 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc->bInterfaceSubClass);
202 if (InterfaceDesc->bInterfaceProtocol != USB_PROTOCOL_BULK)
203 {
204 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
206 }
207
208 if (InterfaceDesc->bInterfaceSubClass == USB_SUBCLASS_UFI)
209 {
210 DPRINT1("USB Floppy devices are not supported\n");
212 }
213
214 // now select an interface
216 if (!NT_SUCCESS(Status))
217 {
218 // failed to get device descriptor
219 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status);
220 return Status;
221 }
222
223 // check if we got a bulk in + bulk out endpoint
224 Status = USBSTOR_GetPipeHandles(DeviceExtension);
225 if (!NT_SUCCESS(Status))
226 {
227 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status);
228 return Status;
229 }
230
231 Status = USBSTOR_GetMaxLUN(DeviceExtension->LowerDeviceObject, DeviceExtension);
232 if (!NT_SUCCESS(Status))
233 {
234 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status);
235 return Status;
236 }
237
238 // now create for each LUN a device object, 1 minimum
239 do
240 {
242
243 if (!NT_SUCCESS(Status))
244 {
245 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index, Status);
246 return Status;
247 }
248
249 Index++;
250 DeviceExtension->InstanceCount++;
251
252 } while(Index < DeviceExtension->MaxLUN);
253
254#if 0
255 //
256 // finally get usb device interface
257 //
258 Status = USBSTOR_GetBusInterface(DeviceExtension->LowerDeviceObject, &DeviceExtension->BusInterface);
259 if (!NT_SUCCESS(Status))
260 {
261 //
262 // failed to device interface
263 //
264 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status);
265 return Status;
266 }
267#endif
268
269 //IoStartTimer(DeviceObject);
270
271 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
272 return STATUS_SUCCESS;
273}
274
278 IN OUT PIRP Irp)
279{
280 PIO_STACK_LOCATION IoStack;
281 PFDO_DEVICE_EXTENSION DeviceExtension;
283
285 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
286 ASSERT(DeviceExtension->Common.IsFDO);
287
288 switch(IoStack->MinorFunction)
289 {
291 {
292 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject);
293 Irp->IoStatus.Status = STATUS_SUCCESS;
294
295 // forward irp to next device object
297 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
298 }
300 {
301 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p Type: %u\n", DeviceObject, IoStack->Parameters.QueryDeviceRelations.Type);
302 return USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
303 }
305 {
306 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
308 Irp->IoStatus.Status = STATUS_SUCCESS;
309
310 // forward irp to next device object
312 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
313 }
315 {
316 DPRINT("IRP_MN_REMOVE_DEVICE\n");
317
318 return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp);
319 }
321 {
322 // FIXME: set custom capabilities
324 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
325 }
328 {
329 if (DeviceExtension->IrpPendingCount != 0 || DeviceExtension->ActiveSrb != NULL)
330 {
331 /* We have pending requests */
332 DPRINT1("Failing removal/stop request due to pending requests present\n");
334 }
335 else
336 {
337 /* We're all clear */
338 Irp->IoStatus.Status = STATUS_SUCCESS;
339
341 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
342 }
343 break;
344 }
346 {
348 break;
349 }
350 default:
351 {
352 // forward irp to next device object
354 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
355 }
356 }
357
358 if (Status != STATUS_PENDING)
359 {
360 Irp->IoStatus.Status = Status;
362 }
363
364 return Status;
365}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
signed int INT32
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
static const struct @259 InterfaceDesc[]
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
#define ULONG_PTR
Definition: config.h:101
NTSTATUS USBSTOR_GetDescriptors(IN PDEVICE_OBJECT DeviceObject)
Definition: descriptor.c:75
NTSTATUS USBSTOR_GetPipeHandles(IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: descriptor.c:319
NTSTATUS USBSTOR_SelectConfigurationAndInterface(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: descriptor.c:234
NTSTATUS USBSTOR_GetMaxLUN(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: misc.c:173
NTSTATUS NTAPI USBSTOR_GetBusInterface(IN PDEVICE_OBJECT DeviceObject, OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterface)
Definition: misc.c:33
VOID USBSTOR_QueueInitialize(PFDO_DEVICE_EXTENSION FDODeviceExtension)
Definition: queue.c:17
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
Status
Definition: gdiplustypes.h:25
VOID NTAPI IoStopTimer(PDEVICE_OBJECT DeviceObject)
Definition: iotimer.c:166
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
ULONG DeviceCount
Definition: mpu401.c:26
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
VOID NTAPI IoDetachDevice(IN PDEVICE_OBJECT TargetDevice)
Definition: device.c:1296
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
#define IoCompleteRequest
Definition: irp.c:1240
BOOLEAN NTAPI IoForwardIrpSynchronously(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1625
#define IoCallDriver
Definition: irp.c:1225
long LONG
Definition: pedump.c:60
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
const KSDEVICE_DESCRIPTOR DeviceDescriptor
Definition: splitter.c:257
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
COMMON_DEVICE_EXTENSION Common
Definition: pci.h:84
struct _IO_STACK_LOCATION::@3974::@3999 QueryDeviceRelations
union _IO_STACK_LOCATION::@1575 Parameters
#define max(a, b)
Definition: svc.c:63
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
struct _USB_CONFIGURATION_DESCRIPTOR USB_CONFIGURATION_DESCRIPTOR
struct _USB_INTERFACE_DESCRIPTOR * PUSB_INTERFACE_DESCRIPTOR
#define USB_INTERFACE_DESCRIPTOR_TYPE
Definition: usb100.h:52
NTSTATUS USBSTOR_FdoHandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
Definition: fdo.c:276
NTSTATUS USBSTOR_FdoHandleRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension, IN OUT PIRP Irp)
Definition: fdo.c:100
NTSTATUS USBSTOR_FdoHandleDeviceRelations(IN PFDO_DEVICE_EXTENSION DeviceExtension, IN OUT PIRP Irp)
Definition: fdo.c:41
NTSTATUS USBSTOR_FdoHandleStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension, IN OUT PIRP Irp)
Definition: fdo.c:146
NTSTATUS USBSTOR_CreatePDO(IN PDEVICE_OBJECT DeviceObject, IN UCHAR LUN)
Definition: pdo.c:864
VOID USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
Definition: fdo.c:18
#define USB_STOR_TAG
Definition: usbstor.h:11
#define USB_MAXCHILDREN
Definition: usbstor.h:61
#define USB_SUBCLASS_UFI
Definition: usbstor.h:26
#define USB_PROTOCOL_BULK
Definition: usbstor.h:39
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
@ BusRelations
Definition: iotypes.h:2152
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MN_START_DEVICE
#define IRP_MN_REMOVE_DEVICE
#define IRP_MN_QUERY_DEVICE_RELATIONS
#define IRP_MN_QUERY_STOP_DEVICE
#define IRP_MN_QUERY_CAPABILITIES
#define IRP_MN_STOP_DEVICE
#define IRP_MN_QUERY_REMOVE_DEVICE
#define ObReferenceObject
Definition: obfuncs.h:204
unsigned char UCHAR
Definition: xmlstorage.h:181