939a9f3f81616e8124a1e72bb79931ec7a9870c9
[reactos.git] / reactos / drivers / usb / usbhub / pdo.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
5 * PURPOSE: Handle PDO
6 * PROGRAMMERS:
7 * Hervé Poussineau (hpoussin@reactos.org)
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
10 */
11
12 #include "usbhub.h"
13
14 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
15
16 NTSTATUS
17 NTAPI
18 UrbCompletion(
19 PDEVICE_OBJECT DeviceObject,
20 PIRP Irp,
21 PVOID Context)
22 {
23 PIRP OriginalIrp;
24 DPRINT("Entered Urb Completion\n");
25
26 //
27 // Get the original Irp
28 //
29 OriginalIrp = (PIRP)Context;
30
31 //
32 // Update it to match what was returned for the IRP that was passed to RootHub
33 //
34 OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;
35 OriginalIrp->IoStatus.Information = Irp->IoStatus.Information;
36 DPRINT("Status %x, Information %x\n", Irp->IoStatus.Status, Irp->IoStatus.Information);
37
38 //
39 // Complete the original Irp
40 //
41 IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT);
42
43 //
44 // Return this status so the IO Manager doesnt mess with the Irp
45 //
46 return STATUS_MORE_PROCESSING_REQUIRED;
47 }
48
49 NTSTATUS
50 FowardUrbToRootHub(
51 PDEVICE_OBJECT RootHubDeviceObject,
52 IN ULONG IoControlCode,
53 PIRP Irp,
54 OUT PVOID OutParameter1,
55 OUT PVOID OutParameter2)
56 {
57 NTSTATUS Status;
58 PIRP ForwardIrp;
59 IO_STATUS_BLOCK IoStatus;
60 PIO_STACK_LOCATION ForwardStack, CurrentStack;
61 PURB Urb;
62
63 //
64 // Get the current stack location for the Irp
65 //
66 CurrentStack = IoGetCurrentIrpStackLocation(Irp);
67 ASSERT(CurrentStack);
68
69 //
70 // Pull the Urb from that stack, it will be reused in the Irp sent to RootHub
71 //
72 Urb = (PURB)CurrentStack->Parameters.Others.Argument1;
73 ASSERT(Urb);
74
75 //
76 // Create the Irp to forward to RootHub
77 //
78 ForwardIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_SHUTDOWN,
79 RootHubDeviceObject,
80 NULL,
81 0,
82 0,
83 &IoStatus);
84 if (!ForwardIrp)
85 {
86 DPRINT1("Failed to allocate IRP\n");
87 return STATUS_INSUFFICIENT_RESOURCES;
88 }
89
90 //
91 // Get the new Irps next stack
92 //
93 ForwardStack = IoGetNextIrpStackLocation(ForwardIrp);
94
95 //
96 // Copy the stack for the current irp into the next stack of new irp
97 //
98 RtlCopyMemory(ForwardStack, CurrentStack, sizeof(IO_STACK_LOCATION));
99
100 IoStatus.Status = STATUS_NOT_SUPPORTED;
101 IoStatus.Information = 0;
102
103 //
104 // Mark the Irp from upper driver as pending
105 //
106 IoMarkIrpPending(Irp);
107
108 //
109 // Now set the completion routine for the new Irp.
110 //
111 IoSetCompletionRoutine(ForwardIrp,
112 UrbCompletion,
113 Irp,
114 TRUE,
115 TRUE,
116 TRUE);
117
118 Status = IoCallDriver(RootHubDeviceObject, ForwardIrp);
119
120 //
121 // Always return pending as the completion routine will take care of it
122 //
123 return STATUS_PENDING;
124 }
125
126 BOOLEAN
127 IsValidPDO(
128 IN PDEVICE_OBJECT DeviceObject)
129 {
130 ULONG Index;
131 PHUB_DEVICE_EXTENSION HubDeviceExtension;
132 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
133
134
135 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
136 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
137 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
138
139 for(Index = 0; Index < USB_MAXCHILDREN; Index++)
140 {
141 if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject)
142 {
143 /* PDO exists */
144 return TRUE;
145 }
146 }
147
148 /* invalid pdo */
149 return FALSE;
150 }
151
152
153 NTSTATUS
154 USBHUB_PdoHandleInternalDeviceControl(
155 IN PDEVICE_OBJECT DeviceObject,
156 IN PIRP Irp)
157 {
158 NTSTATUS Status;
159 PIO_STACK_LOCATION Stack;
160 ULONG_PTR Information = 0;
161 PHUB_DEVICE_EXTENSION HubDeviceExtension;
162 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
163 PDEVICE_OBJECT RootHubDeviceObject;
164 PURB Urb;
165
166 //DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject);
167
168 //
169 // get current stack location
170 //
171 Stack = IoGetCurrentIrpStackLocation(Irp);
172 ASSERT(Stack);
173
174 //
175 // Set default status
176 //
177 Status = Irp->IoStatus.Status;
178
179 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
180 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
181 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
182 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
183
184 if(!IsValidPDO(DeviceObject))
185 {
186 DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject);
187 Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
188 Irp->IoStatus.Information = 0;
189 IoCompleteRequest(Irp, IO_NO_INCREMENT);
190 return STATUS_DEVICE_NOT_CONNECTED;
191 }
192
193 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
194 {
195 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
196 {
197 PHUB_DEVICE_EXTENSION DeviceExtension;
198
199 DPRINT("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
200 if (Irp->AssociatedIrp.SystemBuffer == NULL
201 || Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID))
202 {
203 Status = STATUS_INVALID_PARAMETER;
204 }
205 else
206 {
207 PVOID* pHubPointer;
208 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
209
210 pHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer;
211 // FIXME
212 *pHubPointer = NULL;
213 Information = sizeof(PVOID);
214 Status = STATUS_SUCCESS;
215 }
216 break;
217 }
218 case IOCTL_INTERNAL_USB_SUBMIT_URB:
219 {
220 //DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB\n");
221
222 //
223 // Get the Urb
224 //
225 Urb = (PURB)Stack->Parameters.Others.Argument1;
226 ASSERT(Urb);
227
228 //
229 // Set the real device handle
230 //
231 //DPRINT("UsbdDeviceHandle %x, ChildDeviceHandle %x\n", Urb->UrbHeader.UsbdDeviceHandle, ChildDeviceExtension->UsbDeviceHandle);
232
233 Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle;
234
235 //
236 // Submit to RootHub
237 //
238 switch (Urb->UrbHeader.Function)
239 {
240 //
241 // Debugging only
242 //
243 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
244 DPRINT1("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
245 break;
246 case URB_FUNCTION_CLASS_DEVICE:
247 DPRINT1("URB_FUNCTION_CLASS_DEVICE\n");
248 break;
249 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
250 DPRINT1("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
251 break;
252 case URB_FUNCTION_SELECT_CONFIGURATION:
253 DPRINT1("URB_FUNCTION_SELECT_CONFIGURATION\n");
254 break;
255 case URB_FUNCTION_SELECT_INTERFACE:
256 DPRINT1("URB_FUNCTION_SELECT_INTERFACE\n");
257 break;
258 case URB_FUNCTION_CLASS_OTHER:
259 DPRINT1("URB_FUNCTION_CLASS_OTHER\n");
260 break;
261 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
262 {
263 /*
264 DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n");
265 DPRINT1("PipeHandle %x\n", Urb->UrbBulkOrInterruptTransfer.PipeHandle);
266 DPRINT1("TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags);
267 DPRINT1("Buffer %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
268 DPRINT1("BufferMDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
269 DPRINT1("Length %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
270 DPRINT1("UrbLink %x\n", Urb->UrbBulkOrInterruptTransfer.UrbLink);
271 DPRINT1("hca %x\n", Urb->UrbBulkOrInterruptTransfer.hca);
272 if (Urb->UrbBulkOrInterruptTransfer.TransferFlags == USBD_SHORT_TRANSFER_OK)
273 {
274 }
275 */
276 break;
277
278 }
279 case URB_FUNCTION_CLASS_INTERFACE:
280 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
281 break;
282 case URB_FUNCTION_VENDOR_DEVICE:
283 DPRINT1("URB_FUNCTION_VENDOR_DEVICE\n");
284 break;
285 default:
286 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
287 break;
288 }
289 Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle;
290 //DPRINT1("Stack->CompletionRoutine %x\n", Stack->CompletionRoutine);
291 //
292 // Send the request to RootHub
293 //
294 Status = FowardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL);
295 return Status;
296 break;
297 }
298 //
299 // FIXME: Can these be sent to RootHub?
300 //
301 case IOCTL_INTERNAL_USB_RESET_PORT:
302 DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
303 break;
304 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
305 {
306 PORT_STATUS_CHANGE PortStatus;
307 LONG PortId;
308 PUCHAR PortStatusBits;
309
310 PortStatusBits = (PUCHAR)Stack->Parameters.Others.Argument1;
311 //
312 // USBD_PORT_ENABLED (bit 0) or USBD_PORT_CONNECTED (bit 1)
313 //
314 DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
315 DPRINT("Arg1 %x\n", *PortStatusBits);
316 *PortStatusBits = 0;
317 if (Stack->Parameters.Others.Argument1)
318 {
319 for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++)
320 {
321 Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
322 if (NT_SUCCESS(Status))
323 {
324 DPRINT("Connect %x\n", ((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2));
325 DPRINT("Enable %x\n", ((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
326 *PortStatusBits +=
327 (((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2)) +
328 (((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
329
330 }
331 }
332 }
333
334 DPRINT1("Arg1 %x\n", *PortStatusBits);
335 Status = STATUS_SUCCESS;
336 break;
337 }
338 case IOCTL_INTERNAL_USB_ENABLE_PORT:
339 DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
340 break;
341 case IOCTL_INTERNAL_USB_CYCLE_PORT:
342 DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
343 break;
344 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
345 {
346 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
347 if (Stack->Parameters.Others.Argument1)
348 {
349 // store device handle
350 *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)ChildDeviceExtension->UsbDeviceHandle;
351 Status = STATUS_SUCCESS;
352 }
353 else
354 {
355 // invalid parameter
356 Status = STATUS_INVALID_PARAMETER;
357 }
358 break;
359 }
360 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
361 {
362 if (Stack->Parameters.Others.Argument1)
363 {
364 // inform caller that it is a real usb hub
365 *(PVOID *)Stack->Parameters.Others.Argument1 = NULL;
366 }
367
368 if (Stack->Parameters.Others.Argument2)
369 {
370 // output device object
371 *(PVOID *)Stack->Parameters.Others.Argument2 = DeviceObject;
372 }
373
374 // done
375 Status = STATUS_SUCCESS;
376 break;
377 }
378 default:
379 {
380 DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
381 Information = Irp->IoStatus.Information;
382 Status = Irp->IoStatus.Status;
383 }
384 }
385
386 if (Status != STATUS_PENDING)
387 {
388 Irp->IoStatus.Information = Information;
389 Irp->IoStatus.Status = Status;
390 IoCompleteRequest(Irp, IO_NO_INCREMENT);
391 }
392 return Status;
393 }
394
395 NTSTATUS
396 USBHUB_PdoStartDevice(
397 IN PDEVICE_OBJECT DeviceObject,
398 IN PIRP Irp)
399 {
400 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
401 //NTSTATUS Status;
402 DPRINT("USBHUB_PdoStartDevice %x\n", DeviceObject);
403 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
404
405 //
406 // This should be a PDO
407 //
408 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
409
410 //
411 // FIXME: Fow now assume success
412 //
413
414 UNIMPLEMENTED
415 return STATUS_SUCCESS;
416 }
417
418 NTSTATUS
419 USBHUB_PdoQueryId(
420 IN PDEVICE_OBJECT DeviceObject,
421 IN PIRP Irp,
422 OUT ULONG_PTR* Information)
423 {
424 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
425 ULONG IdType;
426 PUNICODE_STRING SourceString = NULL;
427 PWCHAR ReturnString = NULL;
428 NTSTATUS Status = STATUS_SUCCESS;
429
430 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
431 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
432
433 switch (IdType)
434 {
435 case BusQueryDeviceID:
436 {
437 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
438 SourceString = &ChildDeviceExtension->usDeviceId;
439 break;
440 }
441 case BusQueryHardwareIDs:
442 {
443 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
444 SourceString = &ChildDeviceExtension->usHardwareIds;
445 break;
446 }
447 case BusQueryCompatibleIDs:
448 {
449 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
450 SourceString = &ChildDeviceExtension->usCompatibleIds;
451 break;
452 }
453 case BusQueryInstanceID:
454 {
455 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
456 SourceString = &ChildDeviceExtension->usInstanceId;
457 break;
458 }
459 default:
460 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
461 return STATUS_NOT_SUPPORTED;
462 }
463
464 if (SourceString)
465 {
466 //
467 // allocate buffer
468 //
469 ReturnString = ExAllocatePool(PagedPool, SourceString->MaximumLength);
470 if (!ReturnString)
471 {
472 //
473 // no memory
474 //
475 return STATUS_INSUFFICIENT_RESOURCES;
476 }
477
478 //
479 // copy buffer
480 //
481 RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->MaximumLength);
482 }
483
484 *Information = (ULONG_PTR)ReturnString;
485
486 return Status;
487 }
488
489 NTSTATUS
490 USBHUB_PdoQueryDeviceText(
491 IN PDEVICE_OBJECT DeviceObject,
492 IN PIRP Irp,
493 OUT ULONG_PTR* Information)
494 {
495 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
496 DEVICE_TEXT_TYPE DeviceTextType;
497 PUNICODE_STRING SourceString = NULL;
498 PWCHAR ReturnString = NULL;
499 NTSTATUS Status = STATUS_SUCCESS;
500 LCID LocaleId;
501
502 DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
503 LocaleId = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.LocaleId;
504 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
505
506 //
507 // FIXME: LocaleId
508 //
509
510 switch (DeviceTextType)
511 {
512 case DeviceTextDescription:
513 case DeviceTextLocationInformation:
514 {
515 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
516
517 //
518 // does the device provide a text description
519 //
520 if (ChildDeviceExtension->usTextDescription.Buffer && ChildDeviceExtension->usTextDescription.Length)
521 {
522 //
523 // use device text
524 //
525 SourceString = &ChildDeviceExtension->usTextDescription;
526 }
527 break;
528 }
529 default:
530 {
531 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType);
532 Status = STATUS_NOT_SUPPORTED;
533 break;
534 }
535 }
536
537 if (SourceString)
538 {
539 ReturnString = ExAllocatePool(PagedPool, SourceString->MaximumLength);
540 RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->MaximumLength);
541 DPRINT1("%S\n", ReturnString);
542 *Information = (ULONG_PTR)ReturnString;
543 }
544
545 return Status;
546 }
547
548 NTSTATUS
549 USBHUB_PdoHandlePnp(
550 IN PDEVICE_OBJECT DeviceObject,
551 IN PIRP Irp)
552 {
553 NTSTATUS Status;
554 ULONG MinorFunction;
555 PIO_STACK_LOCATION Stack;
556 ULONG_PTR Information = 0;
557 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
558 ULONG Index;
559 ULONG bFound;
560 PDEVICE_RELATIONS DeviceRelation;
561
562 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
563 Stack = IoGetCurrentIrpStackLocation(Irp);
564 MinorFunction = Stack->MinorFunction;
565
566 switch (MinorFunction)
567 {
568 case IRP_MN_START_DEVICE:
569 {
570 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
571 Status = USBHUB_PdoStartDevice(DeviceObject, Irp);
572 break;
573 }
574 case IRP_MN_QUERY_CAPABILITIES:
575 {
576 PDEVICE_CAPABILITIES DeviceCapabilities;
577 ULONG i;
578 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
579
580 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
581 // FIXME: capabilities can change with connected device
582 DeviceCapabilities->LockSupported = FALSE;
583 DeviceCapabilities->EjectSupported = FALSE;
584 DeviceCapabilities->Removable = TRUE;
585 DeviceCapabilities->DockDevice = FALSE;
586 DeviceCapabilities->UniqueID = FALSE;
587 DeviceCapabilities->SilentInstall = FALSE;
588 DeviceCapabilities->RawDeviceOK = FALSE;
589 DeviceCapabilities->SurpriseRemovalOK = FALSE;
590 DeviceCapabilities->HardwareDisabled = FALSE;
591 //DeviceCapabilities->NoDisplayInUI = FALSE;
592 DeviceCapabilities->Address = UsbChildExtension->PortNumber;
593 DeviceCapabilities->UINumber = 0;
594 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
595 for (i = 1; i < PowerSystemMaximum; i++)
596 DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
597 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined;
598 DeviceCapabilities->D1Latency = 0;
599 DeviceCapabilities->D2Latency = 0;
600 DeviceCapabilities->D3Latency = 0;
601 Status = STATUS_SUCCESS;
602 break;
603 }
604 case IRP_MN_QUERY_RESOURCES:
605 {
606 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
607
608 Information = Irp->IoStatus.Information;
609 Status = Irp->IoStatus.Status;
610 break;
611 }
612 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
613 {
614 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
615
616 Information = Irp->IoStatus.Information;
617 Status = Irp->IoStatus.Status;
618 break;
619 }
620 case IRP_MN_QUERY_DEVICE_TEXT:
621 {
622 Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information);
623 break;
624 }
625 case IRP_MN_QUERY_ID:
626 {
627 Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information);
628 break;
629 }
630 case IRP_MN_QUERY_BUS_INFORMATION:
631 {
632 PPNP_BUS_INFORMATION BusInfo;
633 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
634 RtlCopyMemory(&BusInfo->BusTypeGuid,
635 &GUID_BUS_TYPE_USB,
636 sizeof(BusInfo->BusTypeGuid));
637 BusInfo->LegacyBusType = PNPBus;
638 // FIXME
639 BusInfo->BusNumber = 0;
640 Information = (ULONG_PTR)BusInfo;
641 Status = STATUS_SUCCESS;
642 break;
643 }
644 case IRP_MN_REMOVE_DEVICE:
645 {
646 PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension;
647 PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface;
648
649 DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
650
651 /* remove us from pdo list */
652 bFound = FALSE;
653 for(Index = 0; Index < USB_MAXCHILDREN; Index++)
654 {
655 if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject)
656 {
657 /* Remove the device */
658 Status = HubInterface->RemoveUsbDevice(HubDeviceExtension->UsbDInterface.BusContext, UsbChildExtension->UsbDeviceHandle, 0);
659
660 /* FIXME handle error */
661 ASSERT(Status == STATUS_SUCCESS);
662
663 /* remove us */
664 HubDeviceExtension->ChildDeviceObject[Index] = NULL;
665 bFound = TRUE;
666 break;
667 }
668 }
669
670 /* Complete the IRP */
671 Irp->IoStatus.Status = STATUS_SUCCESS;
672 IoCompleteRequest(Irp, IO_NO_INCREMENT);
673
674 if (bFound)
675 {
676 /* Delete the device object */
677 IoDeleteDevice(DeviceObject);
678 }
679
680 return STATUS_SUCCESS;
681 }
682 case IRP_MN_QUERY_DEVICE_RELATIONS:
683 {
684 /* only target relations are supported */
685 if (Stack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
686 {
687 /* not supported */
688 Status = Irp->IoStatus.Status;
689 break;
690 }
691
692 /* allocate device relations */
693 DeviceRelation = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS));
694 if (!DeviceRelation)
695 {
696 /* no memory */
697 Status = STATUS_INSUFFICIENT_RESOURCES;
698 break;
699 }
700
701 /* init device relation */
702 DeviceRelation->Count = 1;
703 DeviceRelation->Objects[0] = DeviceObject;
704 ObReferenceObject(DeviceRelation->Objects[0]);
705
706 /* store result */
707 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
708 Status = STATUS_SUCCESS;
709 break;
710 }
711 case IRP_MN_QUERY_STOP_DEVICE:
712 case IRP_MN_QUERY_REMOVE_DEVICE:
713 {
714 /* Sure, no problem */
715 Status = STATUS_SUCCESS;
716 Information = 0;
717 break;
718 }
719 case IRP_MN_QUERY_INTERFACE:
720 {
721 DPRINT1("IRP_MN_QUERY_INTERFACE\n");
722 if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID))
723 {
724 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID\n");
725 RtlCopyMemory(Stack->Parameters.QueryInterface.Interface, &UsbChildExtension->DeviceInterface, Stack->Parameters.QueryInterface.Size);
726 Status = STATUS_SUCCESS;
727 break;
728 }
729
730 // pass irp down
731 IoSkipCurrentIrpStackLocation(Irp);
732 return IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp);
733 }
734 default:
735 {
736 DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
737 Information = Irp->IoStatus.Information;
738 Status = Irp->IoStatus.Status;
739 }
740 }
741
742 Irp->IoStatus.Information = Information;
743 Irp->IoStatus.Status = Status;
744 IoCompleteRequest(Irp, IO_NO_INCREMENT);
745 return Status;
746 }
747