ReactOS 0.4.16-dev-297-gc569aee
fdo.c
Go to the documentation of this file.
1/*
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.
6 * PROGRAMMERS:
7 * James Tabor
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
10 */
11
12#include "usbstor.h"
13
14#define NDEBUG
15#include <debug.h>
16
17VOID
19{
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);
35}
36
39 IN PFDO_DEVICE_EXTENSION DeviceExtension,
40 IN OUT PIRP Irp)
41{
43 LONG Index;
44 PDEVICE_RELATIONS DeviceRelations;
45 PIO_STACK_LOCATION IoStack;
46
47 //
48 // get current irp stack location
49 //
51
52 //
53 // check if relation type is BusRelations
54 //
55 if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
56 {
57 //
58 // FDO always only handles bus relations
59 //
60 return USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
61 }
62
63 //
64 // go through array and count device objects
65 //
66 for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
67 {
68 if (DeviceExtension->ChildPDO[Index])
69 {
70 //
71 // child pdo
72 //
74 }
75 }
76
77 //
78 // allocate device relations
79 //
80 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
81 if (!DeviceRelations)
82 {
83 //
84 // no memory
85 //
87 }
88
89 //
90 // add device objects
91 //
92 for(Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
93 {
94 if (DeviceExtension->ChildPDO[Index])
95 {
96 //
97 // store child pdo
98 //
99 DeviceRelations->Objects[DeviceRelations->Count] = DeviceExtension->ChildPDO[Index];
100
101 //
102 // add reference
103 //
104 ObReferenceObject(DeviceExtension->ChildPDO[Index]);
105
106 //
107 // increment count
108 //
109 DeviceRelations->Count++;
110 }
111 }
112
113 //
114 // store result
115 //
116 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
117
118 //
119 // request completed successfully
120 //
121 return STATUS_SUCCESS;
122}
123
127 IN PFDO_DEVICE_EXTENSION DeviceExtension,
128 IN OUT PIRP Irp)
129{
131 ULONG Index;
132
133 DPRINT("Handling FDO removal %p\n", DeviceObject);
134
135 /* FIXME: wait for devices finished processing */
136 for(Index = 0; Index < 16; Index++)
137 {
138 if (DeviceExtension->ChildPDO[Index] != NULL)
139 {
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]);
142 }
143 }
144
145 /* Send the IRP down the stack */
147 Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
148
149 /* Detach from the device stack */
150 IoDetachDevice(DeviceExtension->LowerDeviceObject);
151
152 /* Delete the device object */
154
155 return Status;
156}
157
161 IN PFDO_DEVICE_EXTENSION DeviceExtension,
162 IN OUT PIRP Irp)
163{
166 UCHAR Index = 0;
167
168 //
169 // forward irp to lower device
170 //
171 Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
172 if (!NT_SUCCESS(Status))
173 {
174 //
175 // failed to start
176 //
177 DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status);
178 return Status;
179 }
180
181 //
182 // initialize irp queue
183 //
184 USBSTOR_QueueInitialize(DeviceExtension);
185
186 //
187 // first get device & configuration & string descriptor
188 //
190 if (!NT_SUCCESS(Status))
191 {
192 //
193 // failed to get device descriptor
194 //
195 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status);
196 return Status;
197 }
198
199 //
200 // dump device descriptor
201 //
202 USBSTOR_DumpDeviceDescriptor(DeviceExtension->DeviceDescriptor);
203
204 //
205 // Check that this device uses bulk transfers and is SCSI
206 //
207 InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)DeviceExtension->ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR));
208
209 //
210 // sanity check
211 //
213 ASSERT(InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
214
215 DPRINT("bInterfaceSubClass %x\n", InterfaceDesc->bInterfaceSubClass);
216 if (InterfaceDesc->bInterfaceProtocol != 0x50)
217 {
218 DPRINT1("USB Device is not a bulk only device and is not currently supported\n");
220 }
221
222 if (InterfaceDesc->bInterfaceSubClass != 0x06)
223 {
224 //
225 // FIXME: need to pad CDBs to 12 byte
226 // mode select commands must be translated from 1AH / 15h to 5AH / 55h
227 //
228 DPRINT1("[USBSTOR] Error: need to pad CDBs\n");
230 }
231
232 //
233 // now select an interface
234 //
236 if (!NT_SUCCESS(Status))
237 {
238 //
239 // failed to get device descriptor
240 //
241 DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status);
242 return Status;
243 }
244
245 //
246 // check if we got a bulk in + bulk out endpoint
247 //
248 Status = USBSTOR_GetPipeHandles(DeviceExtension);
249 if (!NT_SUCCESS(Status))
250 {
251 //
252 // failed to get pipe handles descriptor
253 //
254 DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status);
255 return Status;
256 }
257
258 //
259 // get num of lun which are supported
260 //
261 Status = USBSTOR_GetMaxLUN(DeviceExtension->LowerDeviceObject, DeviceExtension);
262 if (!NT_SUCCESS(Status))
263 {
264 //
265 // failed to get max LUN
266 //
267 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status);
268 return Status;
269 }
270
271 //
272 // now create for each LUN a device object, 1 minimum
273 //
274 do
275 {
276 //
277 // create pdo
278 //
280
281 //
282 // check for failure
283 //
284 if (!NT_SUCCESS(Status))
285 {
286 //
287 // failed to create child pdo
288 //
289 DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index, Status);
290 return Status;
291 }
292
293 //
294 // increment pdo index
295 //
296 Index++;
297 DeviceExtension->InstanceCount++;
298
299 }while(Index < DeviceExtension->MaxLUN);
300
301#if 0
302 //
303 // finally get usb device interface
304 //
305 Status = USBSTOR_GetBusInterface(DeviceExtension->LowerDeviceObject, &DeviceExtension->BusInterface);
306 if (!NT_SUCCESS(Status))
307 {
308 //
309 // failed to device interface
310 //
311 DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device interface %x\n", Status);
312 return Status;
313 }
314#endif
315
316
317 //
318 // start the timer
319 //
320 //IoStartTimer(DeviceObject);
321
322
323 //
324 // fdo is now initialized
325 //
326 DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
327 return STATUS_SUCCESS;
328}
329
333 IN OUT PIRP Irp)
334{
335 PIO_STACK_LOCATION IoStack;
336 PFDO_DEVICE_EXTENSION DeviceExtension;
338
339 //
340 // get current stack location
341 //
343
344 //
345 // get device extension
346 //
347 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
348
349 //
350 // sanity check
351 //
352 ASSERT(DeviceExtension->Common.IsFDO);
353
354 switch(IoStack->MinorFunction)
355 {
357 {
358 DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject);
359 Irp->IoStatus.Status = STATUS_SUCCESS;
360
361 //
362 // forward irp to next device object
363 //
365 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
366 }
368 {
369 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject);
370 Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
371 break;
372 }
374 {
375 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
377 Irp->IoStatus.Status = STATUS_SUCCESS;
378
379 //
380 // forward irp to next device object
381 //
383 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
384 }
386 {
387 DPRINT("IRP_MN_REMOVE_DEVICE\n");
388
389 return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp);
390 }
392 {
393 //
394 // FIXME: set custom capabilities
395 //
397 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
398 }
401 {
402#if 0
403 //
404 // we can if nothing is pending
405 //
406 if (DeviceExtension->IrpPendingCount != 0 ||
407 DeviceExtension->ActiveSrb != NULL)
408#else
409 if (TRUE)
410#endif
411 {
412 /* We have pending requests */
413 DPRINT1("Failing removal/stop request due to pending requests present\n");
415 }
416 else
417 {
418 /* We're all clear */
419 Irp->IoStatus.Status = STATUS_SUCCESS;
420
422 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
423 }
424 break;
425 }
427 {
429 break;
430 }
431 default:
432 {
433 //
434 // forward irp to next device object
435 //
437 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
438 }
439 }
440
441 //
442 // complete request
443 //
444 if (Status != STATUS_PENDING)
445 {
446 //
447 // store result
448 //
449 Irp->IoStatus.Status = Status;
450
451 //
452 // complete request
453 //
455 }
456
457 //
458 // done processing
459 //
460 return Status;
461}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
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 STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#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
NTSTATUS NTAPI USBSTOR_SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: misc.c:38
#define PagedPool
Definition: env_spec_w32.h:308
Status
Definition: gdiplustypes.h:25
VOID NTAPI IoStopTimer(PDEVICE_OBJECT DeviceObject)
Definition: iotimer.c:166
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
Definition: misc.c:29
#define ASSERT(a)
Definition: mode.c:44
ULONG DeviceCount
Definition: mpu401.c:26
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
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
#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
union _IO_STACK_LOCATION::@1579 Parameters
struct _IO_STACK_LOCATION::@3978::@4003 QueryDeviceRelations
#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
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
@ BusRelations
Definition: iotypes.h:2152
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MN_START_DEVICE
#define IRP_MN_REMOVE_DEVICE
struct _DEVICE_RELATIONS * PDEVICE_RELATIONS
#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