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