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