[NTFS]
[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 #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 ForwardUrbToRootHub(
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
150 // This can happen when parent device was surprise removed.
151 if (ChildDeviceExtension->ParentDeviceObject == NULL)
152 return FALSE;
153
154 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
155
156 KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
157 for(Index = 0; Index < USB_MAXCHILDREN; Index++)
158 {
159 if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject)
160 {
161 KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
162
163 /* PDO exists */
164 return TRUE;
165 }
166 }
167 KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
168
169 /* invalid pdo */
170 return FALSE;
171 }
172
173
174 NTSTATUS
175 USBHUB_PdoHandleInternalDeviceControl(
176 IN PDEVICE_OBJECT DeviceObject,
177 IN PIRP Irp)
178 {
179 NTSTATUS Status;
180 PIO_STACK_LOCATION Stack;
181 ULONG_PTR Information = 0;
182 PHUB_DEVICE_EXTENSION HubDeviceExtension;
183 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
184 PDEVICE_OBJECT RootHubDeviceObject;
185 PURB Urb;
186
187 //DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject);
188
189 //
190 // get current stack location
191 //
192 Stack = IoGetCurrentIrpStackLocation(Irp);
193 ASSERT(Stack);
194
195 //
196 // Set default status
197 //
198 Status = Irp->IoStatus.Status;
199
200 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
201 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
202
203 Status = IoAcquireRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
204 if (!NT_SUCCESS(Status))
205 {
206 Irp->IoStatus.Status = Status;
207 IoCompleteRequest(Irp, IO_NO_INCREMENT);
208 return Status;
209 }
210
211 if (ChildDeviceExtension->Common.PnPState == SurpriseRemovePending ||
212 ChildDeviceExtension->Common.PnPState == RemovePending ||
213 ChildDeviceExtension->ParentDeviceObject == NULL)
214 {
215 // Parent or child device was surprise removed.
216 DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject);
217 Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
218 Irp->IoStatus.Information = 0;
219 IoCompleteRequest(Irp, IO_NO_INCREMENT);
220 IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
221 return STATUS_DEVICE_NOT_CONNECTED;
222 }
223
224 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
225 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
226
227 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
228 {
229 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
230 {
231 DPRINT("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
232 if (Irp->AssociatedIrp.SystemBuffer == NULL
233 || Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID))
234 {
235 Status = STATUS_INVALID_PARAMETER;
236 }
237 else
238 {
239 PVOID* pHubPointer;
240
241 pHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer;
242 // FIXME
243 *pHubPointer = NULL;
244 Information = sizeof(PVOID);
245 Status = STATUS_SUCCESS;
246 }
247 break;
248 }
249 case IOCTL_INTERNAL_USB_SUBMIT_URB:
250 {
251 //DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB\n");
252
253 //
254 // Get the Urb
255 //
256 Urb = (PURB)Stack->Parameters.Others.Argument1;
257 ASSERT(Urb);
258
259 //
260 // Set the real device handle
261 //
262 //DPRINT("UsbdDeviceHandle %x, ChildDeviceHandle %x\n", Urb->UrbHeader.UsbdDeviceHandle, ChildDeviceExtension->UsbDeviceHandle);
263
264 Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle;
265
266 //
267 // Submit to RootHub
268 //
269 switch (Urb->UrbHeader.Function)
270 {
271 //
272 // Debugging only
273 //
274 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
275 DPRINT("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
276 break;
277 case URB_FUNCTION_CLASS_DEVICE:
278 DPRINT("URB_FUNCTION_CLASS_DEVICE\n");
279 break;
280 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
281 DPRINT("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
282 break;
283 case URB_FUNCTION_SELECT_CONFIGURATION:
284 DPRINT("URB_FUNCTION_SELECT_CONFIGURATION\n");
285 break;
286 case URB_FUNCTION_SELECT_INTERFACE:
287 DPRINT("URB_FUNCTION_SELECT_INTERFACE\n");
288 break;
289 case URB_FUNCTION_CLASS_OTHER:
290 DPRINT("URB_FUNCTION_CLASS_OTHER\n");
291 break;
292 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
293 {
294 /*
295 DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n");
296 DPRINT1("PipeHandle %x\n", Urb->UrbBulkOrInterruptTransfer.PipeHandle);
297 DPRINT1("TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags);
298 DPRINT1("Buffer %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
299 DPRINT1("BufferMDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
300 DPRINT1("Length %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
301 DPRINT1("UrbLink %x\n", Urb->UrbBulkOrInterruptTransfer.UrbLink);
302 DPRINT1("hca %x\n", Urb->UrbBulkOrInterruptTransfer.hca);
303 if (Urb->UrbBulkOrInterruptTransfer.TransferFlags == USBD_SHORT_TRANSFER_OK)
304 {
305 }
306 */
307 break;
308
309 }
310 case URB_FUNCTION_CLASS_INTERFACE:
311 DPRINT("URB_FUNCTION_CLASS_INTERFACE\n");
312 break;
313 case URB_FUNCTION_VENDOR_DEVICE:
314 DPRINT("URB_FUNCTION_VENDOR_DEVICE\n");
315 break;
316 default:
317 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
318 break;
319 }
320 Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle;
321 //DPRINT1("Stack->CompletionRoutine %x\n", Stack->CompletionRoutine);
322 //
323 // Send the request to RootHub
324 //
325 Status = ForwardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL);
326 IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
327 return Status;
328 }
329 //
330 // FIXME: Can these be sent to RootHub?
331 //
332 case IOCTL_INTERNAL_USB_RESET_PORT:
333 DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
334 break;
335 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
336 {
337 PORT_STATUS_CHANGE PortStatus;
338 ULONG PortId;
339 PUCHAR PortStatusBits;
340
341 PortStatusBits = (PUCHAR)Stack->Parameters.Others.Argument1;
342 //
343 // USBD_PORT_ENABLED (bit 0) or USBD_PORT_CONNECTED (bit 1)
344 //
345 DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
346 DPRINT("Arg1 %x\n", *PortStatusBits);
347 *PortStatusBits = 0;
348 if (Stack->Parameters.Others.Argument1)
349 {
350 for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++)
351 {
352 Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
353 if (NT_SUCCESS(Status))
354 {
355 DPRINT("Connect %x\n", ((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2));
356 DPRINT("Enable %x\n", ((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
357 *PortStatusBits +=
358 (((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2)) +
359 (((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
360
361 }
362 }
363 }
364
365 DPRINT1("Arg1 %x\n", *PortStatusBits);
366 Status = STATUS_SUCCESS;
367 break;
368 }
369 case IOCTL_INTERNAL_USB_ENABLE_PORT:
370 DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
371 break;
372 case IOCTL_INTERNAL_USB_CYCLE_PORT:
373 DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
374 break;
375 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
376 {
377 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
378 if (Stack->Parameters.Others.Argument1)
379 {
380 // store device handle
381 *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)ChildDeviceExtension->UsbDeviceHandle;
382 Status = STATUS_SUCCESS;
383 }
384 else
385 {
386 // invalid parameter
387 Status = STATUS_INVALID_PARAMETER;
388 }
389 break;
390 }
391 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
392 {
393 if (Stack->Parameters.Others.Argument1)
394 {
395 // inform caller that it is a real usb hub
396 *(PVOID *)Stack->Parameters.Others.Argument1 = NULL;
397 }
398
399 if (Stack->Parameters.Others.Argument2)
400 {
401 // output device object
402 *(PVOID *)Stack->Parameters.Others.Argument2 = DeviceObject;
403 }
404
405 // done
406 Status = STATUS_SUCCESS;
407 break;
408 }
409 default:
410 {
411 DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
412 Information = Irp->IoStatus.Information;
413 Status = Irp->IoStatus.Status;
414 }
415 }
416
417 if (Status != STATUS_PENDING)
418 {
419 Irp->IoStatus.Information = Information;
420 Irp->IoStatus.Status = Status;
421 IoCompleteRequest(Irp, IO_NO_INCREMENT);
422 }
423 IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
424 return Status;
425 }
426
427 NTSTATUS
428 USBHUB_PdoStartDevice(
429 IN PDEVICE_OBJECT DeviceObject,
430 IN PIRP Irp)
431 {
432 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
433 //NTSTATUS Status;
434 DPRINT("USBHUB_PdoStartDevice %x\n", DeviceObject);
435 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
436
437 //
438 // This should be a PDO
439 //
440 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
441
442 //
443 // register device interface
444 //
445 IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_DEVICE, NULL, &ChildDeviceExtension->SymbolicLinkName);
446 IoSetDeviceInterfaceState(&ChildDeviceExtension->SymbolicLinkName, TRUE);
447
448 SET_NEW_PNP_STATE(ChildDeviceExtension->Common, Started);
449
450 UNIMPLEMENTED;
451 return STATUS_SUCCESS;
452 }
453
454 NTSTATUS
455 USBHUB_PdoQueryId(
456 IN PDEVICE_OBJECT DeviceObject,
457 IN PIRP Irp,
458 OUT ULONG_PTR* Information)
459 {
460 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
461 ULONG IdType;
462 PUNICODE_STRING SourceString = NULL;
463 PWCHAR ReturnString = NULL;
464 NTSTATUS Status = STATUS_SUCCESS;
465
466 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
467 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
468
469 switch (IdType)
470 {
471 case BusQueryDeviceID:
472 {
473 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
474 SourceString = &ChildDeviceExtension->usDeviceId;
475 break;
476 }
477 case BusQueryHardwareIDs:
478 {
479 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
480 SourceString = &ChildDeviceExtension->usHardwareIds;
481 break;
482 }
483 case BusQueryCompatibleIDs:
484 {
485 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
486 SourceString = &ChildDeviceExtension->usCompatibleIds;
487 break;
488 }
489 case BusQueryInstanceID:
490 {
491 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
492 SourceString = &ChildDeviceExtension->usInstanceId;
493 break;
494 }
495 default:
496 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
497 return STATUS_NOT_SUPPORTED;
498 }
499
500 if (SourceString)
501 {
502 //
503 // allocate buffer
504 //
505 ReturnString = ExAllocatePool(PagedPool, SourceString->MaximumLength);
506 if (!ReturnString)
507 {
508 //
509 // no memory
510 //
511 return STATUS_INSUFFICIENT_RESOURCES;
512 }
513
514 //
515 // copy buffer
516 //
517 RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->MaximumLength);
518 }
519
520 *Information = (ULONG_PTR)ReturnString;
521
522 return Status;
523 }
524
525 NTSTATUS
526 USBHUB_PdoQueryDeviceText(
527 IN PDEVICE_OBJECT DeviceObject,
528 IN PIRP Irp,
529 OUT ULONG_PTR* Information)
530 {
531 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
532 DEVICE_TEXT_TYPE DeviceTextType;
533 PUNICODE_STRING SourceString = NULL;
534 PWCHAR ReturnString = NULL;
535 NTSTATUS Status = STATUS_SUCCESS;
536
537 DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
538 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
539
540 //
541 // FIXME: LocaleId
542 //
543
544 switch (DeviceTextType)
545 {
546 case DeviceTextDescription:
547 case DeviceTextLocationInformation:
548 {
549 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
550
551 //
552 // does the device provide a text description
553 //
554 if (ChildDeviceExtension->usTextDescription.Buffer && ChildDeviceExtension->usTextDescription.Length)
555 {
556 //
557 // use device text
558 //
559 SourceString = &ChildDeviceExtension->usTextDescription;
560 }
561 break;
562 }
563 default:
564 {
565 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType);
566 Status = STATUS_NOT_SUPPORTED;
567 break;
568 }
569 }
570
571 if (SourceString)
572 {
573 ReturnString = ExAllocatePool(PagedPool, SourceString->MaximumLength);
574 RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->MaximumLength);
575 DPRINT1("%S\n", ReturnString);
576 *Information = (ULONG_PTR)ReturnString;
577 }
578
579 return Status;
580 }
581
582 NTSTATUS
583 USBHUB_PdoHandlePnp(
584 IN PDEVICE_OBJECT DeviceObject,
585 IN PIRP Irp)
586 {
587 NTSTATUS Status;
588 ULONG MinorFunction;
589 PIO_STACK_LOCATION Stack;
590 ULONG_PTR Information = 0;
591 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
592 PDEVICE_RELATIONS DeviceRelation;
593
594 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
595 Stack = IoGetCurrentIrpStackLocation(Irp);
596 MinorFunction = Stack->MinorFunction;
597
598 Status = IoAcquireRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp);
599 if (!NT_SUCCESS(Status))
600 {
601 Irp->IoStatus.Status = Status;
602 IoCompleteRequest(Irp, IO_NO_INCREMENT);
603 return Status;
604 }
605
606 switch (MinorFunction)
607 {
608 case IRP_MN_START_DEVICE:
609 {
610 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
611 Status = USBHUB_PdoStartDevice(DeviceObject, Irp);
612 break;
613 }
614 case IRP_MN_QUERY_CAPABILITIES:
615 {
616 PDEVICE_CAPABILITIES DeviceCapabilities;
617 ULONG i;
618 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
619
620 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
621 // FIXME: capabilities can change with connected device
622 DeviceCapabilities->LockSupported = FALSE;
623 DeviceCapabilities->EjectSupported = FALSE;
624 DeviceCapabilities->Removable = TRUE;
625 DeviceCapabilities->DockDevice = FALSE;
626 DeviceCapabilities->UniqueID = FALSE;
627 DeviceCapabilities->SilentInstall = FALSE;
628 DeviceCapabilities->RawDeviceOK = FALSE;
629 DeviceCapabilities->SurpriseRemovalOK = FALSE;
630 DeviceCapabilities->HardwareDisabled = FALSE;
631 //DeviceCapabilities->NoDisplayInUI = FALSE;
632 DeviceCapabilities->Address = UsbChildExtension->PortNumber;
633 DeviceCapabilities->UINumber = 0;
634 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
635 for (i = 1; i < PowerSystemMaximum; i++)
636 DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
637 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined;
638 DeviceCapabilities->D1Latency = 0;
639 DeviceCapabilities->D2Latency = 0;
640 DeviceCapabilities->D3Latency = 0;
641 Status = STATUS_SUCCESS;
642 break;
643 }
644 case IRP_MN_QUERY_RESOURCES:
645 {
646 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
647
648 Information = Irp->IoStatus.Information;
649 Status = Irp->IoStatus.Status;
650 break;
651 }
652 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
653 {
654 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
655
656 Information = Irp->IoStatus.Information;
657 Status = Irp->IoStatus.Status;
658 break;
659 }
660 case IRP_MN_QUERY_DEVICE_TEXT:
661 {
662 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
663 Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information);
664 break;
665 }
666 case IRP_MN_QUERY_ID:
667 {
668 DPRINT("IRP_MN_QUERY_ID\n");
669 Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information);
670 break;
671 }
672 case IRP_MN_QUERY_BUS_INFORMATION:
673 {
674 PPNP_BUS_INFORMATION BusInfo;
675 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
676 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
677 RtlCopyMemory(&BusInfo->BusTypeGuid,
678 &GUID_BUS_TYPE_USB,
679 sizeof(BusInfo->BusTypeGuid));
680 BusInfo->LegacyBusType = PNPBus;
681 // FIXME
682 BusInfo->BusNumber = 0;
683 Information = (ULONG_PTR)BusInfo;
684 Status = STATUS_SUCCESS;
685 break;
686 }
687 case IRP_MN_REMOVE_DEVICE:
688 {
689 PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension;
690 PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface;
691
692 DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
693
694 ASSERT((UsbChildExtension->Common.PnPState == RemovePending) ||
695 (UsbChildExtension->Common.PnPState == SurpriseRemovePending));
696
697 SET_NEW_PNP_STATE(UsbChildExtension->Common, NotStarted);
698
699 if (!IsValidPDO(DeviceObject))
700 {
701 // Parent or child device was surprise removed, freeing resources allocated for child device.
702 SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted);
703
704 IoReleaseRemoveLockAndWait(&UsbChildExtension->Common.RemoveLock, Irp);
705
706 // Remove the usb device
707 if (UsbChildExtension->UsbDeviceHandle)
708 {
709 Status = HubInterface->RemoveUsbDevice(HubInterface->BusContext, UsbChildExtension->UsbDeviceHandle, 0);
710 ASSERT(Status == STATUS_SUCCESS);
711 }
712 // Free full configuration descriptor
713 if (UsbChildExtension->FullConfigDesc)
714 ExFreePool(UsbChildExtension->FullConfigDesc);
715
716 // Free ID buffers
717 if (UsbChildExtension->usCompatibleIds.Buffer)
718 ExFreePool(UsbChildExtension->usCompatibleIds.Buffer);
719
720 if (UsbChildExtension->usDeviceId.Buffer)
721 ExFreePool(UsbChildExtension->usDeviceId.Buffer);
722
723 if (UsbChildExtension->usHardwareIds.Buffer)
724 ExFreePool(UsbChildExtension->usHardwareIds.Buffer);
725
726 if (UsbChildExtension->usInstanceId.Buffer)
727 ExFreePool(UsbChildExtension->usInstanceId.Buffer);
728
729 DPRINT("Deleting child PDO\n");
730 IoDeleteDevice(DeviceObject);
731 }
732 else
733 {
734 IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp);
735 }
736
737 // If device is physically presented, we leave its PDO undeleted.
738
739 /* Complete the IRP */
740 Irp->IoStatus.Status = STATUS_SUCCESS;
741 IoCompleteRequest(Irp, IO_NO_INCREMENT);
742
743 return STATUS_SUCCESS;
744 }
745 case IRP_MN_QUERY_DEVICE_RELATIONS:
746 {
747 /* only target relations are supported */
748 if (Stack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
749 {
750 /* not supported */
751 Status = Irp->IoStatus.Status;
752 Information = Irp->IoStatus.Information;
753 break;
754 }
755
756 /* allocate device relations */
757 DeviceRelation = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
758 if (!DeviceRelation)
759 {
760 /* no memory */
761 Status = STATUS_INSUFFICIENT_RESOURCES;
762 break;
763 }
764
765 /* init device relation */
766 DeviceRelation->Count = 1;
767 DeviceRelation->Objects[0] = DeviceObject;
768 ObReferenceObject(DeviceRelation->Objects[0]);
769
770 /* store result */
771 Information = (ULONG_PTR)DeviceRelation;
772 Status = STATUS_SUCCESS;
773 break;
774 }
775 case IRP_MN_QUERY_STOP_DEVICE:
776 {
777 //
778 // We should fail this request, because we're not handling IRP_MN_STOP_DEVICE for now.
779 // We'll receive this IRP ONLY when the PnP manager rebalances resources.
780 //
781 Status = STATUS_NOT_SUPPORTED;
782 break;
783 }
784 case IRP_MN_QUERY_REMOVE_DEVICE:
785 {
786 //
787 // Free interface obtained from bottom, according MSDN we should
788 // check interfaces provided to top, but here we are not checking.
789 // All checking will be performed in roothub driver's
790 // IRP_MN_QUERY_REMOVE_DEVICE handler. This will make problems when
791 // buggy driver is loaded on top of us. But we decided to keep source
792 // simpler, because in any case buggy driver will prevent removing of
793 // whole stack.
794 //
795 UsbChildExtension->DeviceInterface.InterfaceDereference(UsbChildExtension->DeviceInterface.BusContext);
796
797 SET_NEW_PNP_STATE(UsbChildExtension->Common, RemovePending);
798
799 /* Sure, no problem */
800 Status = STATUS_SUCCESS;
801 Information = 0;
802 break;
803 }
804 case IRP_MN_CANCEL_REMOVE_DEVICE:
805 {
806 // Check to see have we received query-remove before
807 if (UsbChildExtension->Common.PnPState == RemovePending)
808 {
809 RESTORE_PREVIOUS_PNP_STATE(UsbChildExtension->Common);
810 UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext);
811 }
812
813 Status = STATUS_SUCCESS;
814 break;
815 }
816 case IRP_MN_QUERY_INTERFACE:
817 {
818 DPRINT1("IRP_MN_QUERY_INTERFACE\n");
819 if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID))
820 {
821 DPRINT1("USB_BUS_INTERFACE_USBDI_GUID\n");
822 RtlCopyMemory(Stack->Parameters.QueryInterface.Interface, &UsbChildExtension->DeviceInterface, Stack->Parameters.QueryInterface.Size);
823 UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext);
824 Status = STATUS_SUCCESS;
825 break;
826 }
827
828 // pass irp down
829 IoSkipCurrentIrpStackLocation(Irp);
830 Status = IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp);
831 IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp);
832 return Status;
833 }
834 case IRP_MN_SURPRISE_REMOVAL:
835 {
836 DPRINT("[USBHUB] HandlePnp IRP_MN_SURPRISE_REMOVAL\n");
837
838 //
839 // Here we should free all resources and stop all access, lets just set
840 // the flag and do further clean-up in subsequent IRP_MN_REMOVE_DEVICE
841 // We can receive this IRP when device is physically connected (on stop/start fail).
842 //
843 SET_NEW_PNP_STATE(UsbChildExtension->Common, SurpriseRemovePending);
844
845 Status = STATUS_SUCCESS;
846 break;
847 }
848 default:
849 {
850 DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
851 Information = Irp->IoStatus.Information;
852 Status = Irp->IoStatus.Status;
853 }
854 }
855
856 IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp);
857
858 Irp->IoStatus.Information = Information;
859 Irp->IoStatus.Status = Status;
860 IoCompleteRequest(Irp, IO_NO_INCREMENT);
861 return Status;
862 }
863