[USBPORT] Start implementation USB2_DeallocateEndpointBudget().
[reactos.git] / drivers / usb / usbstor_new / fdo.c
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
17 VOID
18 USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
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
37 NTSTATUS
38 USBSTOR_FdoHandleDeviceRelations(
39 IN PFDO_DEVICE_EXTENSION DeviceExtension,
40 IN OUT PIRP Irp)
41 {
42 ULONG DeviceCount = 0;
43 LONG Index;
44 PDEVICE_RELATIONS DeviceRelations;
45 PIO_STACK_LOCATION IoStack;
46
47 //
48 // get current irp stack location
49 //
50 IoStack = IoGetCurrentIrpStackLocation(Irp);
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 //
73 DeviceCount++;
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 //
86 return STATUS_INSUFFICIENT_RESOURCES;
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
124 NTSTATUS
125 USBSTOR_FdoHandleRemoveDevice(
126 IN PDEVICE_OBJECT DeviceObject,
127 IN PFDO_DEVICE_EXTENSION DeviceExtension,
128 IN OUT PIRP Irp)
129 {
130 NTSTATUS Status;
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 */
146 IoSkipCurrentIrpStackLocation(Irp);
147 Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
148
149 /* Detach from the device stack */
150 IoDetachDevice(DeviceExtension->LowerDeviceObject);
151
152 /* Delete the device object */
153 IoDeleteDevice(DeviceObject);
154
155 return Status;
156 }
157
158 NTSTATUS
159 USBSTOR_FdoHandleStartDevice(
160 IN PDEVICE_OBJECT DeviceObject,
161 IN PFDO_DEVICE_EXTENSION DeviceExtension,
162 IN OUT PIRP Irp)
163 {
164 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
165 NTSTATUS Status;
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 //
189 Status = USBSTOR_GetDescriptors(DeviceObject);
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 //
212 ASSERT(InterfaceDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
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");
219 return STATUS_NOT_SUPPORTED;
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");
229 return STATUS_NOT_IMPLEMENTED;
230 }
231
232 //
233 // now select an interface
234 //
235 Status = USBSTOR_SelectConfigurationAndInterface(DeviceObject, DeviceExtension);
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 //
279 Status = USBSTOR_CreatePDO(DeviceObject, Index);
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
330 NTSTATUS
331 USBSTOR_FdoHandlePnp(
332 IN PDEVICE_OBJECT DeviceObject,
333 IN OUT PIRP Irp)
334 {
335 PIO_STACK_LOCATION IoStack;
336 PFDO_DEVICE_EXTENSION DeviceExtension;
337 NTSTATUS Status;
338
339 //
340 // get current stack location
341 //
342 IoStack = IoGetCurrentIrpStackLocation(Irp);
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 {
356 case IRP_MN_SURPRISE_REMOVAL:
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 //
364 IoSkipCurrentIrpStackLocation(Irp);
365 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
366 }
367 case IRP_MN_QUERY_DEVICE_RELATIONS:
368 {
369 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject);
370 Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
371 break;
372 }
373 case IRP_MN_STOP_DEVICE:
374 {
375 DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
376 IoStopTimer(DeviceObject);
377 Irp->IoStatus.Status = STATUS_SUCCESS;
378
379 //
380 // forward irp to next device object
381 //
382 IoSkipCurrentIrpStackLocation(Irp);
383 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
384 }
385 case IRP_MN_REMOVE_DEVICE:
386 {
387 DPRINT("IRP_MN_REMOVE_DEVICE\n");
388
389 return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp);
390 }
391 case IRP_MN_QUERY_CAPABILITIES:
392 {
393 //
394 // FIXME: set custom capabilities
395 //
396 IoSkipCurrentIrpStackLocation(Irp);
397 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
398 }
399 case IRP_MN_QUERY_STOP_DEVICE:
400 case IRP_MN_QUERY_REMOVE_DEVICE:
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");
414 Status = STATUS_UNSUCCESSFUL;
415 }
416 else
417 {
418 /* We're all clear */
419 Irp->IoStatus.Status = STATUS_SUCCESS;
420
421 IoSkipCurrentIrpStackLocation(Irp);
422 return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
423 }
424 break;
425 }
426 case IRP_MN_START_DEVICE:
427 {
428 Status = USBSTOR_FdoHandleStartDevice(DeviceObject, DeviceExtension, Irp);
429 break;
430 }
431 default:
432 {
433 //
434 // forward irp to next device object
435 //
436 IoSkipCurrentIrpStackLocation(Irp);
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 //
454 IoCompleteRequest(Irp, IO_NO_INCREMENT);
455 }
456
457 //
458 // done processing
459 //
460 return Status;
461 }