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