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