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