21bea27bf468d6d767129cae11b0ce2c8e07630e
[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 default:
283 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
284 break;
285 }
286 Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle;
287 //DPRINT1("Stack->CompletionRoutine %x\n", Stack->CompletionRoutine);
288 //
289 // Send the request to RootHub
290 //
291 Status = FowardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL);
292 return Status;
293 break;
294 }
295 //
296 // FIXME: Can these be sent to RootHub?
297 //
298 case IOCTL_INTERNAL_USB_RESET_PORT:
299 DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
300 break;
301 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
302 {
303 PORT_STATUS_CHANGE PortStatus;
304 LONG PortId;
305 PUCHAR PortStatusBits;
306
307 PortStatusBits = (PUCHAR)Stack->Parameters.Others.Argument1;
308 //
309 // USBD_PORT_ENABLED (bit 0) or USBD_PORT_CONNECTED (bit 1)
310 //
311 DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
312 DPRINT("Arg1 %x\n", *PortStatusBits);
313 *PortStatusBits = 0;
314 if (Stack->Parameters.Others.Argument1)
315 {
316 for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++)
317 {
318 Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
319 if (NT_SUCCESS(Status))
320 {
321 DPRINT("Connect %x\n", ((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2));
322 DPRINT("Enable %x\n", ((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
323 *PortStatusBits +=
324 (((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2)) +
325 (((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
326
327 }
328 }
329 }
330
331 DPRINT1("Arg1 %x\n", *PortStatusBits);
332 Status = STATUS_SUCCESS;
333 break;
334 }
335 case IOCTL_INTERNAL_USB_ENABLE_PORT:
336 DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
337 break;
338 case IOCTL_INTERNAL_USB_CYCLE_PORT:
339 DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
340 break;
341 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
342 {
343 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
344 if (Stack->Parameters.Others.Argument1)
345 {
346 // store device handle
347 *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)ChildDeviceExtension->UsbDeviceHandle;
348 Status = STATUS_SUCCESS;
349 }
350 else
351 {
352 // invalid parameter
353 Status = STATUS_INVALID_PARAMETER;
354 }
355 break;
356 }
357 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
358 {
359 if (Stack->Parameters.Others.Argument1)
360 {
361 // inform caller that it is a real usb hub
362 *(PVOID *)Stack->Parameters.Others.Argument1 = NULL;
363 }
364
365 if (Stack->Parameters.Others.Argument2)
366 {
367 // output device object
368 *(PVOID *)Stack->Parameters.Others.Argument2 = DeviceObject;
369 }
370
371 // done
372 Status = STATUS_SUCCESS;
373 break;
374 }
375 default:
376 {
377 DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
378 Information = Irp->IoStatus.Information;
379 Status = Irp->IoStatus.Status;
380 }
381 }
382
383 if (Status != STATUS_PENDING)
384 {
385 Irp->IoStatus.Information = Information;
386 Irp->IoStatus.Status = Status;
387 IoCompleteRequest(Irp, IO_NO_INCREMENT);
388 }
389 return Status;
390 }
391
392 NTSTATUS
393 USBHUB_PdoStartDevice(
394 IN PDEVICE_OBJECT DeviceObject,
395 IN PIRP Irp)
396 {
397 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
398 //NTSTATUS Status;
399 DPRINT("USBHUB_PdoStartDevice %x\n", DeviceObject);
400 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
401
402 //
403 // This should be a PDO
404 //
405 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
406
407 //
408 // FIXME: Fow now assume success
409 //
410
411 UNIMPLEMENTED
412 return STATUS_SUCCESS;
413 }
414
415 NTSTATUS
416 USBHUB_PdoQueryId(
417 IN PDEVICE_OBJECT DeviceObject,
418 IN PIRP Irp,
419 OUT ULONG_PTR* Information)
420 {
421 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
422 ULONG IdType;
423 PUNICODE_STRING SourceString = NULL;
424 PWCHAR ReturnString = NULL;
425 NTSTATUS Status = STATUS_SUCCESS;
426
427 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
428 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
429
430 switch (IdType)
431 {
432 case BusQueryDeviceID:
433 {
434 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
435 SourceString = &ChildDeviceExtension->usDeviceId;
436 break;
437 }
438 case BusQueryHardwareIDs:
439 {
440 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
441 SourceString = &ChildDeviceExtension->usHardwareIds;
442 break;
443 }
444 case BusQueryCompatibleIDs:
445 {
446 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
447 SourceString = &ChildDeviceExtension->usCompatibleIds;
448 break;
449 }
450 case BusQueryInstanceID:
451 {
452 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
453 SourceString = &ChildDeviceExtension->usInstanceId;
454 break;
455 }
456 default:
457 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
458 return STATUS_NOT_SUPPORTED;
459 }
460
461 if (SourceString)
462 {
463 //
464 // allocate buffer
465 //
466 ReturnString = ExAllocatePool(PagedPool, SourceString->MaximumLength);
467 if (!ReturnString)
468 {
469 //
470 // no memory
471 //
472 return STATUS_INSUFFICIENT_RESOURCES;
473 }
474
475 //
476 // copy buffer
477 //
478 RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->MaximumLength);
479 }
480
481 *Information = (ULONG_PTR)ReturnString;
482
483 return Status;
484 }
485
486 NTSTATUS
487 USBHUB_PdoQueryDeviceText(
488 IN PDEVICE_OBJECT DeviceObject,
489 IN PIRP Irp,
490 OUT ULONG_PTR* Information)
491 {
492 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
493 DEVICE_TEXT_TYPE DeviceTextType;
494 PUNICODE_STRING SourceString = NULL;
495 PWCHAR ReturnString = NULL;
496 NTSTATUS Status = STATUS_SUCCESS;
497 LCID LocaleId;
498
499 DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
500 LocaleId = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.LocaleId;
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
559 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
560 Stack = IoGetCurrentIrpStackLocation(Irp);
561 MinorFunction = Stack->MinorFunction;
562
563 switch (MinorFunction)
564 {
565 case IRP_MN_START_DEVICE:
566 {
567 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
568 Status = USBHUB_PdoStartDevice(DeviceObject, Irp);
569 break;
570 }
571 case IRP_MN_QUERY_CAPABILITIES:
572 {
573 PDEVICE_CAPABILITIES DeviceCapabilities;
574 ULONG i;
575 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
576
577 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
578 // FIXME: capabilities can change with connected device
579 DeviceCapabilities->LockSupported = FALSE;
580 DeviceCapabilities->EjectSupported = FALSE;
581 DeviceCapabilities->Removable = TRUE;
582 DeviceCapabilities->DockDevice = FALSE;
583 DeviceCapabilities->UniqueID = FALSE;
584 DeviceCapabilities->SilentInstall = FALSE;
585 DeviceCapabilities->RawDeviceOK = FALSE;
586 DeviceCapabilities->SurpriseRemovalOK = FALSE;
587 DeviceCapabilities->HardwareDisabled = FALSE;
588 //DeviceCapabilities->NoDisplayInUI = FALSE;
589 DeviceCapabilities->Address = UsbChildExtension->PortNumber;
590 DeviceCapabilities->UINumber = 0;
591 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
592 for (i = 1; i < PowerSystemMaximum; i++)
593 DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
594 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined;
595 DeviceCapabilities->D1Latency = 0;
596 DeviceCapabilities->D2Latency = 0;
597 DeviceCapabilities->D3Latency = 0;
598 Status = STATUS_SUCCESS;
599 break;
600 }
601 case IRP_MN_QUERY_RESOURCES:
602 {
603 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
604
605 Information = Irp->IoStatus.Information;
606 Status = Irp->IoStatus.Status;
607 break;
608 }
609 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
610 {
611 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
612
613 Information = Irp->IoStatus.Information;
614 Status = Irp->IoStatus.Status;
615 break;
616 }
617 case IRP_MN_QUERY_DEVICE_TEXT:
618 {
619 Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information);
620 break;
621 }
622 case IRP_MN_QUERY_ID:
623 {
624 Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information);
625 break;
626 }
627 case IRP_MN_QUERY_BUS_INFORMATION:
628 {
629 PPNP_BUS_INFORMATION BusInfo;
630 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
631 RtlCopyMemory(&BusInfo->BusTypeGuid,
632 &GUID_BUS_TYPE_USB,
633 sizeof(BusInfo->BusTypeGuid));
634 BusInfo->LegacyBusType = PNPBus;
635 // FIXME
636 BusInfo->BusNumber = 0;
637 Information = (ULONG_PTR)BusInfo;
638 Status = STATUS_SUCCESS;
639 break;
640 }
641 case IRP_MN_REMOVE_DEVICE:
642 {
643 PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension;
644 PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface;
645
646 DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
647
648 /* remove us from pdo list */
649 bFound = FALSE;
650 for(Index = 0; Index < USB_MAXCHILDREN; Index++)
651 {
652 if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject)
653 {
654 /* Remove the device */
655 Status = HubInterface->RemoveUsbDevice(HubDeviceExtension->UsbDInterface.BusContext, UsbChildExtension->UsbDeviceHandle, 0);
656
657 /* FIXME handle error */
658 ASSERT(Status == STATUS_SUCCESS);
659
660 /* remove us */
661 HubDeviceExtension->ChildDeviceObject[Index] = NULL;
662 bFound = TRUE;
663 break;
664 }
665 }
666
667 /* Complete the IRP */
668 Irp->IoStatus.Status = STATUS_SUCCESS;
669 IoCompleteRequest(Irp, IO_NO_INCREMENT);
670
671 if (bFound)
672 {
673 /* Delete the device object */
674 IoDeleteDevice(DeviceObject);
675 }
676
677 return STATUS_SUCCESS;
678 }
679 case IRP_MN_QUERY_DEVICE_RELATIONS:
680 {
681 /* only target relations are supported */
682 if (Stack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
683 {
684 /* not supported */
685 Status = Irp->IoStatus.Status;
686 break;
687 }
688
689 /* allocate device relations */
690 DeviceRelation = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS));
691 if (!DeviceRelation)
692 {
693 /* no memory */
694 Status = STATUS_INSUFFICIENT_RESOURCES;
695 break;
696 }
697
698 /* init device relation */
699 DeviceRelation->Count = 1;
700 DeviceRelation->Objects[0] = DeviceObject;
701 ObReferenceObject(DeviceRelation->Objects[0]);
702
703 /* store result */
704 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
705 Status = STATUS_SUCCESS;
706 break;
707 }
708 case IRP_MN_QUERY_STOP_DEVICE:
709 case IRP_MN_QUERY_REMOVE_DEVICE:
710 {
711 /* Sure, no problem */
712 Status = STATUS_SUCCESS;
713 Information = 0;
714 break;
715 }
716 case IRP_MN_QUERY_INTERFACE:
717 {
718 DPRINT1("IRP_MN_QUERY_INTERFACE\n");
719 if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID))
720 {
721 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID\n");
722 RtlCopyMemory(Stack->Parameters.QueryInterface.Interface, &UsbChildExtension->DeviceInterface, Stack->Parameters.QueryInterface.Size);
723 Status = STATUS_SUCCESS;
724 break;
725 }
726
727 // pass irp down
728 IoSkipCurrentIrpStackLocation(Irp);
729 return IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp);
730 }
731 default:
732 {
733 DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
734 Information = Irp->IoStatus.Information;
735 Status = Irp->IoStatus.Status;
736 }
737 }
738
739 Irp->IoStatus.Information = Information;
740 Irp->IoStatus.Status = Status;
741 IoCompleteRequest(Irp, IO_NO_INCREMENT);
742 return Status;
743 }
744