[USBHUB_NEW] Bring-in the USB Hub driver created by Vadim Galyant. GitHub PR #29...
[reactos.git] / reactos / drivers / usb / usbhub_new / ioctl.c
1 #include "usbhub.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 #define NDEBUG_USBHUB_IOCTL
7 #include "dbg_uhub.h"
8
9 NTSTATUS
10 NTAPI
11 USBH_SelectConfigOrInterfaceComplete(IN PDEVICE_OBJECT DeviceObject,
12 IN PIRP Irp,
13 IN PVOID Context)
14 {
15 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
16 PUSBHUB_FDO_EXTENSION HubExtension;
17 PVOID TimeoutContext; // PUSBHUB_BANDWIDTH_TIMEOUT_CONTEXT
18 PUSBHUB_PORT_DATA PortData = NULL;
19 NTSTATUS Status;
20 KIRQL OldIrql;
21
22 DPRINT("USBH_SelectConfigOrInterfaceComplete ... \n");
23
24 if (Irp->PendingReturned)
25 {
26 IoMarkIrpPending(Irp);
27 }
28
29 PortExtension = Context;
30 HubExtension = PortExtension->HubExtension;
31
32 ASSERT(PortExtension->PortNumber > 0);
33
34 if (HubExtension)
35 {
36 PortData = &HubExtension->PortData[PortExtension->PortNumber - 1];
37 }
38
39 Status = Irp->IoStatus.Status;
40
41 if (NT_SUCCESS(Irp->IoStatus.Status))
42 {
43 KeAcquireSpinLock(&PortExtension->PortTimeoutSpinLock, &OldIrql);
44
45 TimeoutContext = PortExtension->BndwTimeoutContext;
46
47 if (TimeoutContext)
48 {
49 DPRINT1("USBH_SelectConfigOrInterfaceComplete: TimeoutContext != NULL. FIXME\n");
50 DbgBreakPoint();
51 }
52
53 KeReleaseSpinLock(&PortExtension->PortTimeoutSpinLock, OldIrql);
54
55 PortExtension->PortPdoFlags &= ~(USBHUB_PDO_FLAG_PORT_RESTORE_FAIL |
56 USBHUB_PDO_FLAG_ALLOC_BNDW_FAILED);
57
58 if (PortData && PortData->ConnectionStatus != DeviceHubNestedTooDeeply)
59 {
60 PortData->ConnectionStatus = DeviceConnected;
61 }
62 }
63 else
64 {
65 DPRINT1("USBH_SelectConfigOrInterfaceComplete: Status != STATUS_SUCCESS. FIXME\n");
66 DbgBreakPoint();
67 }
68
69 return Status;
70 }
71
72 NTSTATUS
73 NTAPI
74 USBH_PdoUrbFilter(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
75 IN PIRP Irp)
76 {
77 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
78 PUSBHUB_FDO_EXTENSION HubExtension;
79 PDEVICE_OBJECT DeviceObject;
80 PURB Urb;
81 USHORT Function;
82 ULONG MaxPower;
83 USBD_STATUS UrbStatus;
84 BOOLEAN IsValidConfig;
85
86 HubExtension = PortExtension->HubExtension;
87 DeviceObject = PortExtension->Common.SelfDevice;
88
89 Urb = URB_FROM_IRP(Irp);
90
91 DPRINT_IOCTL("USBH_PdoUrbFilter: Device - %p, Irp - %p, Urb - %p\n",
92 DeviceObject,
93 Irp,
94 Urb);
95
96 if (PortExtension->PortPdoFlags & (USBHUB_PDO_FLAG_PORT_RESTORE_FAIL |
97 USBHUB_PDO_FLAG_PORT_RESSETING))
98 {
99 Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
100 USBH_CompleteIrp(Irp, STATUS_INVALID_PARAMETER);
101 return STATUS_INVALID_PARAMETER;
102 }
103
104 Function = Urb->UrbHeader.Function;
105
106 switch (Function)
107 {
108 case URB_FUNCTION_SELECT_CONFIGURATION:
109 {
110 ConfigDescriptor = Urb->UrbSelectConfiguration.ConfigurationDescriptor;
111
112 if (ConfigDescriptor)
113 {
114 IsValidConfig = TRUE;
115
116 if (ConfigDescriptor->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE)
117 {
118 DPRINT1("USBH_PdoUrbFilter: Not valid Cfg. bDescriptorType\n");
119 IsValidConfig = FALSE;
120 UrbStatus = USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR;
121 }
122
123 if (ConfigDescriptor->bLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
124 {
125 DPRINT1("USBH_PdoUrbFilter: Size Cfg. descriptor is too small\n");
126 IsValidConfig = FALSE;
127 UrbStatus = USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR;
128 }
129
130 if (!IsValidConfig)
131 {
132 Urb->UrbHeader.Status = UrbStatus;
133 USBH_CompleteIrp(Irp, STATUS_INVALID_PARAMETER);
134 return STATUS_INVALID_PARAMETER;
135 }
136
137 MaxPower = 2 * ConfigDescriptor->MaxPower;
138 PortExtension->MaxPower = MaxPower;
139
140 if (HubExtension->MaxPowerPerPort < MaxPower)
141 {
142 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_INSUFFICIENT_PWR;
143
144 DPRINT1("USBH_PdoUrbFilter: USBH_InvalidatePortDeviceState() UNIMPLEMENTED. FIXME\n");
145 DbgBreakPoint();
146
147 USBH_CompleteIrp(Irp, STATUS_INVALID_PARAMETER);
148 return STATUS_INVALID_PARAMETER;
149 }
150 }
151 }
152
153 /* fall through */
154
155 case URB_FUNCTION_SELECT_INTERFACE:
156 {
157 IoCopyCurrentIrpStackLocationToNext(Irp);
158
159 IoSetCompletionRoutine(Irp,
160 USBH_SelectConfigOrInterfaceComplete,
161 PortExtension,
162 TRUE,
163 TRUE,
164 TRUE);
165
166 return IoCallDriver(HubExtension->RootHubPdo2, Irp);
167 }
168
169 case URB_FUNCTION_CONTROL_TRANSFER:
170 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
171 case URB_FUNCTION_ISOCH_TRANSFER:
172 {
173 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_DELETE_PENDING)
174 {
175 Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
176 USBH_CompleteIrp(Irp, STATUS_DELETE_PENDING);
177 return STATUS_DELETE_PENDING;
178 }
179
180 break;
181 }
182
183 case URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR:
184 DPRINT1("USBH_PdoUrbFilter: URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR UNIMPLEMENTED. FIXME\n");
185 USBH_CompleteIrp(Irp, STATUS_NOT_IMPLEMENTED);
186 return STATUS_NOT_IMPLEMENTED;
187
188 default:
189 break;
190 }
191
192 return USBH_PassIrp(HubExtension->RootHubPdo2, Irp);
193 }
194
195 NTSTATUS
196 NTAPI
197 USBH_PdoIoctlSubmitUrb(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
198 IN PIRP Irp)
199 {
200 PUSBHUB_FDO_EXTENSION HubExtension;
201 PURB Urb;
202 NTSTATUS Status;
203
204 DPRINT_IOCTL("USBH_PdoIoctlSubmitUrb ... \n");
205
206 HubExtension = PortExtension->HubExtension;
207
208 Urb = URB_FROM_IRP(Irp);
209
210 if (PortExtension->DeviceHandle == NULL)
211 {
212 Urb->UrbHeader.UsbdDeviceHandle = NULL;
213 Status = USBH_PassIrp(HubExtension->RootHubPdo2, Irp);
214 }
215 else
216 {
217 Urb->UrbHeader.UsbdDeviceHandle = PortExtension->DeviceHandle;
218 Status = USBH_PdoUrbFilter(PortExtension, Irp);
219 }
220
221 return Status;
222 }
223
224 NTSTATUS
225 NTAPI
226 USBH_PdoIoctlGetPortStatus(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
227 IN PIRP Irp)
228 {
229 PUSBHUB_FDO_EXTENSION HubExtension;
230 PUSBHUB_PORT_DATA PortData;
231 PIO_STACK_LOCATION IoStack;
232 PULONG PortStatus;
233 NTSTATUS Status;
234
235 DPRINT("USBH_PdoIoctlGetPortStatus ... \n");
236
237 HubExtension = PortExtension->HubExtension;
238
239 InterlockedIncrement(&HubExtension->PendingRequestCount);
240
241 KeWaitForSingleObject(&HubExtension->HubSemaphore,
242 Executive,
243 KernelMode,
244 FALSE,
245 NULL);
246
247 ASSERT(PortExtension->PortNumber > 0);
248 PortData = &HubExtension->PortData[PortExtension->PortNumber - 1];
249
250 Status = USBH_SyncGetPortStatus(HubExtension,
251 PortExtension->PortNumber,
252 &PortData->PortStatus,
253 sizeof(USBHUB_PORT_STATUS));
254
255 IoStack = IoGetCurrentIrpStackLocation(Irp);
256 PortStatus = IoStack->Parameters.Others.Argument1;
257
258 *PortStatus = 0;
259
260 if (PortExtension->Common.SelfDevice == PortData->DeviceObject)
261 {
262 if (PortData->PortStatus.UsbPortStatus.Usb20PortStatus.PortEnabledDisabled)
263 {
264 *PortStatus |= USBD_PORT_ENABLED;
265 }
266
267 if (PortData->PortStatus.UsbPortStatus.Usb20PortStatus.CurrentConnectStatus)
268 {
269 *PortStatus |= USBD_PORT_CONNECTED;
270 }
271 }
272
273 KeReleaseSemaphore(&HubExtension->HubSemaphore,
274 LOW_REALTIME_PRIORITY,
275 1,
276 FALSE);
277
278 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
279 {
280 KeSetEvent(&HubExtension->PendingRequestEvent,
281 EVENT_INCREMENT,
282 FALSE);
283 }
284
285 USBH_CompleteIrp(Irp, Status);
286
287 return Status;
288 }
289
290 VOID
291 NTAPI
292 USBH_ResetPortWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,
293 IN PVOID Context)
294 {
295 PUSBHUB_RESET_PORT_CONTEXT WorkItemReset;
296 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
297 PUSB_DEVICE_HANDLE DeviceHandle;
298 NTSTATUS Status;
299 USHORT Port;
300
301 DPRINT("USBH_ResetPortWorker ... \n");
302
303 WorkItemReset = Context;
304
305 PortExtension = WorkItemReset->PortExtension;
306
307 if (!HubExtension)
308 {
309 Status = STATUS_UNSUCCESSFUL;
310 goto Exit;
311 }
312
313 InterlockedIncrement(&HubExtension->PendingRequestCount);
314
315 KeWaitForSingleObject(&HubExtension->HubSemaphore,
316 Executive,
317 KernelMode,
318 FALSE,
319 NULL);
320
321 Port = PortExtension->PortNumber;
322 DeviceHandle = PortExtension->DeviceHandle;
323
324 ASSERT(Port > 0);
325
326 if (PortExtension->Common.SelfDevice == HubExtension->PortData[Port-1].DeviceObject &&
327 DeviceHandle != NULL)
328 {
329 USBD_RemoveDeviceEx(HubExtension,
330 DeviceHandle,
331 USBD_MARK_DEVICE_BUSY);
332
333 Status = USBH_ResetDevice(HubExtension,
334 Port,
335 TRUE,
336 FALSE);
337 }
338 else
339 {
340 Status = STATUS_INVALID_PARAMETER;
341 }
342
343 KeReleaseSemaphore(&HubExtension->HubSemaphore,
344 LOW_REALTIME_PRIORITY,
345 1,
346 FALSE);
347
348 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
349 {
350 KeSetEvent(&HubExtension->PendingRequestEvent,
351 EVENT_INCREMENT,
352 FALSE);
353 }
354
355 Exit:
356
357 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_PORT_RESSETING;
358
359 USBH_CompleteIrp(WorkItemReset->Irp, Status);
360
361 WorkItemReset->PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_PORT_RESTORE_FAIL;
362 }
363
364 NTSTATUS
365 NTAPI
366 USBH_PdoIoctlResetPort(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
367 IN PIRP Irp)
368 {
369 PUSBHUB_FDO_EXTENSION HubExtension;
370 PUSBHUB_RESET_PORT_CONTEXT HubWorkItemBuffer;
371 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
372 NTSTATUS Status;
373
374 HubExtension = PortExtension->HubExtension;
375
376 DPRINT("USBH_PdoIoctlResetPort ... \n");
377
378 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_PORT_RESSETING)
379 {
380 Status = STATUS_UNSUCCESSFUL;
381 USBH_CompleteIrp(Irp, Status);
382 return Status;
383 }
384
385 Status = USBH_AllocateWorkItem(HubExtension,
386 &HubIoWorkItem,
387 USBH_ResetPortWorker,
388 sizeof(USBHUB_RESET_PORT_CONTEXT),
389 (PVOID *)&HubWorkItemBuffer,
390 DelayedWorkQueue);
391
392 if (!NT_SUCCESS(Status))
393 {
394 Status = STATUS_UNSUCCESSFUL;
395 USBH_CompleteIrp(Irp, Status);
396 return Status;
397 }
398
399 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_PORT_RESSETING;
400 IoMarkIrpPending(Irp);
401
402 HubWorkItemBuffer->PortExtension = PortExtension;
403 HubWorkItemBuffer->Irp = Irp;
404
405 Status = STATUS_PENDING;
406
407 USBH_QueueWorkItem(PortExtension->HubExtension, HubIoWorkItem);
408
409 return Status;
410 }
411
412 VOID
413 NTAPI
414 USBH_PortIdleNotificationCancelRoutine(IN PDEVICE_OBJECT Device,
415 IN PIRP Irp)
416 {
417 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
418 PUSBHUB_FDO_EXTENSION HubExtension;
419 PIRP PendingIdleIrp = NULL;
420 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
421 PUSBHUB_IDLE_PORT_CANCEL_CONTEXT HubWorkItemBuffer;
422 NTSTATUS Status;
423
424 DPRINT("USBH_PortIdleNotificationCancelRoutine ... \n");
425
426 PortExtension = Device->DeviceExtension;
427 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_IDLE_NOTIFICATION;
428
429 HubExtension = PortExtension->HubExtension;
430 ASSERT(HubExtension);
431
432 PortExtension->IdleNotificationIrp = NULL;
433
434 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST)
435 {
436 PendingIdleIrp = HubExtension->PendingIdleIrp;
437 HubExtension->PendingIdleIrp = NULL;
438 }
439
440 IoReleaseCancelSpinLock(Irp->CancelIrql);
441
442 if (PendingIdleIrp)
443 {
444 USBH_HubCancelIdleIrp(HubExtension, PendingIdleIrp);
445 }
446
447 if (HubExtension->CurrentPowerState.DeviceState == PowerDeviceD0)
448 {
449 goto ErrorExit;
450 }
451
452 Status = USBH_AllocateWorkItem(HubExtension,
453 &HubIoWorkItem,
454 USBH_IdleCancelPowerHubWorker,
455 sizeof(USBHUB_IDLE_PORT_CANCEL_CONTEXT),
456 (PVOID *)&HubWorkItemBuffer,
457 DelayedWorkQueue);
458
459 if (NT_SUCCESS(Status))
460 {
461 HubWorkItemBuffer->Irp = Irp;
462 USBH_QueueWorkItem(HubExtension, HubIoWorkItem);
463 return;
464 }
465
466 ErrorExit:
467
468 Irp->IoStatus.Status = STATUS_CANCELLED;
469 IoCompleteRequest(Irp, IO_NO_INCREMENT);
470 }
471
472 NTSTATUS
473 NTAPI
474 USBH_PortIdleNotificationRequest(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
475 IN PIRP Irp)
476 {
477 PUSBHUB_FDO_EXTENSION HubExtension;
478 PIO_STACK_LOCATION IoStack;
479 PUSB_IDLE_CALLBACK_INFO IdleCallbackInfo;
480 NTSTATUS Status;
481 KIRQL Irql;
482
483 DPRINT("USBH_PortIdleNotificationRequest ... \n");
484
485 HubExtension = PortExtension->HubExtension;
486
487 IoAcquireCancelSpinLock(&Irql);
488
489 if (PortExtension->IdleNotificationIrp)
490 {
491 IoReleaseCancelSpinLock(Irql);
492 Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
493 IoCompleteRequest(Irp, IO_NO_INCREMENT);
494 return STATUS_DEVICE_BUSY;
495 }
496
497 IoStack = IoGetCurrentIrpStackLocation(Irp);
498 IdleCallbackInfo = IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
499
500 if (!IdleCallbackInfo || !IdleCallbackInfo->IdleCallback)
501 {
502 IoReleaseCancelSpinLock(Irql);
503
504 Status = STATUS_NO_CALLBACK_ACTIVE;
505 Irp->IoStatus.Status = Status;
506 IoCompleteRequest(Irp, IO_NO_INCREMENT);
507
508 return Status;
509 }
510
511 IoSetCancelRoutine(Irp, USBH_PortIdleNotificationCancelRoutine);
512
513 if (Irp->Cancel)
514 {
515 if (IoSetCancelRoutine(Irp, NULL))
516 {
517 IoReleaseCancelSpinLock(Irql);
518 Status = STATUS_CANCELLED;
519 Irp->IoStatus.Status = STATUS_CANCELLED;
520 IoCompleteRequest(Irp, IO_NO_INCREMENT);
521 }
522 else
523 {
524 IoMarkIrpPending(Irp);
525 IoReleaseCancelSpinLock(Irql);
526 Status = STATUS_PENDING;
527 }
528 }
529 else
530 {
531 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_IDLE_NOTIFICATION;
532
533 PortExtension->IdleNotificationIrp = Irp;
534 IoMarkIrpPending(Irp);
535
536 IoReleaseCancelSpinLock(Irql);
537 Status = STATUS_PENDING;
538
539 DPRINT("USBH_PortIdleNotificationRequest: IdleNotificationIrp - %p\n",
540 PortExtension->IdleNotificationIrp);
541
542 USBH_CheckIdleDeferred(HubExtension);
543 }
544
545 return Status;
546 }
547
548 NTSTATUS
549 NTAPI
550 USBH_IoctlGetNodeName(IN PUSBHUB_FDO_EXTENSION HubExtension,
551 IN PIRP Irp)
552 {
553 PUSB_NODE_CONNECTION_NAME ConnectionName;
554 PDEVICE_OBJECT PortDevice;
555 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
556 ULONG LengthSkip;
557 PWCHAR Buffer;
558 ULONG BufferLength;
559 PWCHAR BufferEnd;
560 ULONG LengthReturned;
561 ULONG LengthName;
562 ULONG Length;
563 NTSTATUS Status;
564 PIO_STACK_LOCATION IoStack;
565 ULONG_PTR Information;
566
567 DPRINT("USBH_IoctlGetNodeName ... \n");
568
569 Status = STATUS_SUCCESS;
570
571 ConnectionName = Irp->AssociatedIrp.SystemBuffer;
572
573 IoStack = IoGetCurrentIrpStackLocation(Irp);
574 Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
575
576 if (Length < sizeof(USB_NODE_CONNECTION_NAME))
577 {
578 Status = STATUS_BUFFER_TOO_SMALL;
579 Information = Irp->IoStatus.Information;
580 goto Exit;
581 }
582
583 if (ConnectionName->ConnectionIndex == 0 ||
584 ConnectionName->ConnectionIndex > HubExtension->HubDescriptor->bNumberOfPorts)
585 {
586 Status = STATUS_INVALID_PARAMETER;
587 Information = Irp->IoStatus.Information;
588 goto Exit;
589 }
590
591 PortDevice = HubExtension->PortData[ConnectionName->ConnectionIndex - 1].DeviceObject;
592
593 if (!PortDevice)
594 {
595 ConnectionName->NodeName[0] = 0;
596 ConnectionName->ActualLength = sizeof(USB_NODE_CONNECTION_NAME);
597
598 Information = sizeof(USB_NODE_CONNECTION_NAME);
599 goto Exit;
600 }
601
602 PortExtension = PortDevice->DeviceExtension;
603
604 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE) ||
605 !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_DEVICE_STARTED) ||
606 !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REG_DEV_INTERFACE))
607 {
608 ConnectionName->NodeName[0] = 0;
609 ConnectionName->ActualLength = sizeof(USB_NODE_CONNECTION_NAME);
610
611 Information = sizeof(USB_NODE_CONNECTION_NAME);
612 goto Exit;
613 }
614
615 Buffer = PortExtension->SymbolicLinkName.Buffer;
616 BufferLength = PortExtension->SymbolicLinkName.Length;
617
618 ASSERT(Buffer[BufferLength / sizeof(WCHAR)] == UNICODE_NULL);
619
620 LengthSkip = 0;
621
622 if (*Buffer == L'\\')
623 {
624 BufferEnd = wcschr(Buffer + 1, L'\\');
625
626 if (BufferEnd != NULL)
627 {
628 LengthSkip = (BufferEnd + 1 - Buffer) * sizeof(WCHAR);
629 }
630 else
631 {
632 LengthSkip = PortExtension->SymbolicLinkName.Length;
633 }
634 }
635
636 LengthName = BufferLength - LengthSkip;
637
638 ConnectionName->ActualLength = 0;
639
640 RtlZeroMemory(ConnectionName->NodeName,
641 Length - FIELD_OFFSET(USB_NODE_CONNECTION_NAME, NodeName));
642
643 LengthReturned = sizeof(USB_NODE_CONNECTION_NAME) + LengthName;
644
645 if (Length < LengthReturned)
646 {
647 ConnectionName->NodeName[0] = 0;
648 ConnectionName->ActualLength = LengthReturned;
649
650 Information = sizeof(USB_NODE_CONNECTION_NAME);
651 goto Exit;
652 }
653
654 RtlCopyMemory(&ConnectionName->NodeName[0],
655 &Buffer[LengthSkip / sizeof(WCHAR)],
656 LengthName);
657
658 ConnectionName->ActualLength = LengthReturned;
659
660 Status = STATUS_SUCCESS;
661 Information = LengthReturned;
662
663 Exit:
664 Irp->IoStatus.Information = Information;
665 USBH_CompleteIrp(Irp, Status);
666 return Status;
667 }
668
669 NTSTATUS
670 NTAPI
671 USBH_IoctlGetNodeInformation(IN PUSBHUB_FDO_EXTENSION HubExtension,
672 IN PIRP Irp)
673 {
674 PUSB_NODE_INFORMATION NodeInfo;
675 PIO_STACK_LOCATION IoStack;
676 ULONG BufferLength;
677 NTSTATUS Status;
678 BOOLEAN HubIsBusPowered;
679
680 DPRINT("USBH_IoctlGetNodeInformation ... \n");
681
682 Status = STATUS_SUCCESS;
683
684 NodeInfo = Irp->AssociatedIrp.SystemBuffer;
685
686 IoStack = IoGetCurrentIrpStackLocation(Irp);
687 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
688
689 RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, BufferLength);
690
691 if (BufferLength < sizeof(USB_NODE_INFORMATION))
692 {
693 Status = STATUS_BUFFER_TOO_SMALL;
694 USBH_CompleteIrp(Irp, Status);
695 return Status;
696 }
697
698 NodeInfo->NodeType = UsbHub;
699
700 RtlCopyMemory(&NodeInfo->u.HubInformation.HubDescriptor,
701 HubExtension->HubDescriptor,
702 sizeof(USB_HUB_DESCRIPTOR));
703
704 HubIsBusPowered = USBH_HubIsBusPowered(HubExtension->Common.SelfDevice,
705 HubExtension->HubConfigDescriptor);
706
707 NodeInfo->u.HubInformation.HubIsBusPowered = HubIsBusPowered;
708
709 Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION);
710
711 USBH_CompleteIrp(Irp, Status);
712
713 return Status;
714 }
715
716 NTSTATUS
717 NTAPI
718 USBH_IoctlGetHubCapabilities(IN PUSBHUB_FDO_EXTENSION HubExtension,
719 IN PIRP Irp)
720 {
721 PUSB_HUB_CAPABILITIES Capabilities;
722 PIO_STACK_LOCATION IoStack;
723 ULONG BufferLength;
724 ULONG Length;
725 USB_HUB_CAPABILITIES HubCaps;
726
727 DPRINT("USBH_IoctlGetHubCapabilities ... \n");
728
729 Capabilities = Irp->AssociatedIrp.SystemBuffer;
730
731 HubCaps.HubIs2xCapable = (HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB) ==
732 USBHUB_FDO_FLAG_USB20_HUB;
733
734 IoStack = IoGetCurrentIrpStackLocation(Irp);
735
736 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
737
738 if (BufferLength == 0)
739 {
740 Irp->IoStatus.Information = BufferLength;
741 USBH_CompleteIrp(Irp, STATUS_INVALID_PARAMETER);
742 return STATUS_INVALID_PARAMETER;
743 }
744
745 if (BufferLength <= sizeof(HubCaps))
746 {
747 Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
748 }
749 else
750 {
751 Length = sizeof(HubCaps);
752 }
753
754 RtlZeroMemory(Capabilities, BufferLength);
755 RtlCopyMemory(Capabilities, &HubCaps, Length);
756
757 Irp->IoStatus.Information = Length;
758
759 USBH_CompleteIrp(Irp, STATUS_SUCCESS);
760
761 return STATUS_SUCCESS;
762 }
763
764 NTSTATUS
765 NTAPI
766 USBH_IoctlGetNodeConnectionAttributes(IN PUSBHUB_FDO_EXTENSION HubExtension,
767 IN PIRP Irp)
768 {
769 PUSB_NODE_CONNECTION_ATTRIBUTES Attributes;
770 ULONG ConnectionIndex;
771 ULONG NumPorts;
772 NTSTATUS Status;
773 PUSBHUB_PORT_DATA PortData;
774 PIO_STACK_LOCATION IoStack;
775 ULONG BufferLength;
776
777 DPRINT("USBH_IoctlGetNodeConnectionAttributes ... \n");
778
779 IoStack = IoGetCurrentIrpStackLocation(Irp);
780 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
781
782 if (BufferLength < sizeof(USB_NODE_CONNECTION_ATTRIBUTES))
783 {
784 Status = STATUS_BUFFER_TOO_SMALL;
785 goto Exit;
786 }
787
788 Attributes = Irp->AssociatedIrp.SystemBuffer;
789
790 ConnectionIndex = Attributes->ConnectionIndex;
791 RtlZeroMemory(Attributes, BufferLength);
792 Attributes->ConnectionIndex = ConnectionIndex;
793
794 Status = STATUS_INVALID_PARAMETER;
795
796 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts;
797
798 if (NumPorts == 0 ||
799 ConnectionIndex == 0 ||
800 ConnectionIndex > NumPorts)
801 {
802 goto Exit;
803 }
804
805 PortData = HubExtension->PortData + (ConnectionIndex - 1);
806
807 Attributes->ConnectionStatus = PortData->ConnectionStatus;
808 Attributes->PortAttributes = PortData->PortAttributes;
809
810 Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_ATTRIBUTES);
811 Status = STATUS_SUCCESS;
812
813 Exit:
814
815 USBH_CompleteIrp(Irp, Status);
816 return Status;
817 }
818
819 NTSTATUS
820 NTAPI
821 USBH_IoctlGetNodeConnectionInformation(IN PUSBHUB_FDO_EXTENSION HubExtension,
822 IN PIRP Irp,
823 IN BOOLEAN IsExt)
824 {
825 PUSBHUB_PORT_DATA PortData;
826 ULONG BufferLength;
827 PUSB_NODE_CONNECTION_INFORMATION_EX Info;
828 ULONG ConnectionIndex;
829 ULONG NumPorts;
830 NTSTATUS Status;
831 PDEVICE_OBJECT DeviceObject;
832 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
833 PIO_STACK_LOCATION IoStack;
834
835 DPRINT("USBH_IoctlGetNodeConnectionInformation ... \n");
836
837 IoStack = IoGetCurrentIrpStackLocation(Irp);
838 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
839
840 if (BufferLength < (ULONG)FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION_EX,
841 PipeList))
842 {
843 Status = STATUS_BUFFER_TOO_SMALL;
844 goto Exit;
845 }
846
847 Info = Irp->AssociatedIrp.SystemBuffer;
848
849 ConnectionIndex = Info->ConnectionIndex;
850 RtlZeroMemory(Info, BufferLength);
851 Info->ConnectionIndex = ConnectionIndex;
852
853 Status = STATUS_INVALID_PARAMETER;
854
855 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts;
856
857 if (NumPorts == 0 ||
858 ConnectionIndex == 0 ||
859 ConnectionIndex > NumPorts)
860 {
861 goto Exit;
862 }
863
864 PortData = HubExtension->PortData + (ConnectionIndex - 1);
865 DeviceObject = PortData->DeviceObject;
866
867 if (!DeviceObject)
868 {
869 Info->ConnectionStatus = PortData->ConnectionStatus;
870
871 Irp->IoStatus.Information = FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION_EX,
872 PipeList);
873 Status = STATUS_SUCCESS;
874 goto Exit;
875 }
876
877 PortExtension = DeviceObject->DeviceExtension;
878
879 Info->ConnectionStatus = PortData->ConnectionStatus;
880
881 Info->DeviceIsHub = (PortExtension->PortPdoFlags &
882 USBHUB_PDO_FLAG_HUB_DEVICE) ==
883 USBHUB_PDO_FLAG_HUB_DEVICE;
884
885 RtlCopyMemory(&Info->DeviceDescriptor,
886 &PortExtension->DeviceDescriptor,
887 sizeof(USB_DEVICE_DESCRIPTOR));
888
889 if (PortExtension->DeviceHandle)
890 {
891 Status = USBD_GetDeviceInformationEx(PortExtension,
892 HubExtension,
893 Info,
894 BufferLength,
895 PortExtension->DeviceHandle);
896 }
897 else
898 {
899 Status = STATUS_SUCCESS;
900 }
901
902 if (NT_SUCCESS(Status))
903 {
904 if (!IsExt)
905 {
906 /* IOCTL_USB_GET_NODE_CONNECTION_INFORMATION request reports
907 only low and full speed connections. Info->Speed member
908 is Info->LowSpeed in the non-EX version of the structure */
909
910 Info->Speed = (Info->Speed == UsbLowSpeed);
911 }
912
913 Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) +
914 (Info->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFO);
915 goto Exit;
916 }
917
918 if (Status != STATUS_BUFFER_TOO_SMALL)
919 {
920 goto Exit;
921 }
922
923 Irp->IoStatus.Information = FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION_EX,
924 PipeList);
925 Status = STATUS_SUCCESS;
926
927 Exit:
928 USBH_CompleteIrp(Irp, Status);
929 return Status;
930 }
931
932 NTSTATUS
933 NTAPI
934 USBH_IoctlGetNodeConnectionDriverKeyName(IN PUSBHUB_FDO_EXTENSION HubExtension,
935 IN PIRP Irp)
936 {
937 PUSBHUB_PORT_DATA PortData;
938 PDEVICE_OBJECT PortDevice;
939 ULONG Length;
940 ULONG ResultLength;
941 NTSTATUS Status;
942 PIO_STACK_LOCATION IoStack;
943 ULONG BufferLength;
944 PUSB_NODE_CONNECTION_DRIVERKEY_NAME KeyName;
945 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
946
947 DPRINT("USBH_IoctlGetNodeConnectionDriverKeyName ... \n");
948
949 IoStack = IoGetCurrentIrpStackLocation(Irp);
950 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
951
952 if (BufferLength < sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME) ||
953 HubExtension->HubDescriptor->bNumberOfPorts == 0)
954 {
955 Status = STATUS_BUFFER_TOO_SMALL;
956 goto Exit;
957 }
958
959 KeyName = Irp->AssociatedIrp.SystemBuffer;
960 Status = STATUS_INVALID_PARAMETER;
961
962 PortData = &HubExtension->PortData[KeyName->ConnectionIndex - 1];
963 PortDevice = PortData->DeviceObject;
964
965 if (!PortDevice)
966 {
967 goto Exit;
968 }
969
970 PortExtension = PortDevice->DeviceExtension;
971
972 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_ENUMERATED))
973 {
974 Status = STATUS_INVALID_DEVICE_STATE;
975 goto Exit;
976 }
977
978 ResultLength = BufferLength - sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME);
979
980 Status = IoGetDeviceProperty(PortDevice,
981 DevicePropertyDriverKeyName,
982 BufferLength - sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME),
983 &KeyName->DriverKeyName,
984 &ResultLength);
985
986 if (Status == STATUS_BUFFER_TOO_SMALL)
987 {
988 Status = STATUS_SUCCESS;
989 }
990
991 Length = ResultLength + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME);
992 KeyName->ActualLength = Length;
993
994 if (BufferLength < Length)
995 {
996 KeyName->DriverKeyName[0] = 0;
997 Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME);
998 }
999 else
1000 {
1001 Irp->IoStatus.Information = Length;
1002 }
1003
1004 Exit:
1005 USBH_CompleteIrp(Irp, Status);
1006 return Status;
1007 }
1008
1009 NTSTATUS
1010 NTAPI
1011 USBH_IoctlGetDescriptor(IN PUSBHUB_FDO_EXTENSION HubExtension,
1012 IN PIRP Irp)
1013 {
1014 ULONG BufferLength;
1015 PUSBHUB_PORT_DATA PortData;
1016 PUSB_DESCRIPTOR_REQUEST UsbRequest;
1017 PDEVICE_OBJECT PortDevice;
1018 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
1019 struct _URB_CONTROL_TRANSFER * Urb;
1020 NTSTATUS Status;
1021 ULONG RequestBufferLength;
1022 PIO_STACK_LOCATION IoStack;
1023 ULONG NumPorts;
1024
1025 IoStack = IoGetCurrentIrpStackLocation(Irp);
1026 BufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
1027
1028 DPRINT("USBH_IoctlGetDescriptor: BufferLength - %x\n", BufferLength);
1029
1030 if (BufferLength < sizeof(USB_DESCRIPTOR_REQUEST))
1031 {
1032 Status = STATUS_BUFFER_TOO_SMALL;
1033 goto Exit;
1034 }
1035
1036 UsbRequest = Irp->AssociatedIrp.SystemBuffer;
1037 RequestBufferLength = UsbRequest->SetupPacket.wLength;
1038
1039 if (RequestBufferLength > BufferLength -
1040 FIELD_OFFSET(USB_DESCRIPTOR_REQUEST, Data))
1041 {
1042 DPRINT("USBH_IoctlGetDescriptor: RequestBufferLength - %x\n",
1043 RequestBufferLength);
1044
1045 Status = STATUS_BUFFER_TOO_SMALL;
1046 goto Exit;
1047 }
1048
1049 Status = STATUS_INVALID_PARAMETER;
1050
1051 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts;
1052
1053 if (NumPorts == 0 ||
1054 UsbRequest->ConnectionIndex == 0 ||
1055 UsbRequest->ConnectionIndex > NumPorts)
1056 {
1057 goto Exit;
1058 }
1059
1060 PortData = HubExtension->PortData + (UsbRequest->ConnectionIndex - 1);
1061 PortDevice = PortData->DeviceObject;
1062
1063 if (!PortDevice)
1064 {
1065 goto Exit;
1066 }
1067
1068 PortExtension = PortDevice->DeviceExtension;
1069
1070 if (UsbRequest->SetupPacket.bmRequest == USB_CONFIGURATION_DESCRIPTOR_TYPE &&
1071 RequestBufferLength == sizeof(USB_CONFIGURATION_DESCRIPTOR))
1072 {
1073 Status = STATUS_SUCCESS;
1074
1075 RtlCopyMemory(&UsbRequest->Data[0],
1076 &PortExtension->ConfigDescriptor,
1077 sizeof(USB_CONFIGURATION_DESCRIPTOR));
1078
1079 Irp->IoStatus.Information = sizeof(USB_DESCRIPTOR_REQUEST) - sizeof(UCHAR) +
1080 sizeof(USB_CONFIGURATION_DESCRIPTOR);
1081 goto Exit;
1082 }
1083
1084 Urb = ExAllocatePoolWithTag(NonPagedPool,
1085 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
1086 USB_HUB_TAG);
1087
1088 if (!Urb)
1089 {
1090 Status = STATUS_INSUFFICIENT_RESOURCES;
1091 goto Exit;
1092 }
1093
1094 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
1095
1096 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
1097 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
1098
1099 Urb->TransferBuffer = &UsbRequest->Data[0];
1100 Urb->TransferBufferLength = RequestBufferLength;
1101 Urb->TransferBufferMDL = NULL;
1102 Urb->UrbLink = NULL;
1103
1104 RtlCopyMemory(Urb->SetupPacket,
1105 &UsbRequest->SetupPacket,
1106 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1107
1108 Status = USBH_SyncSubmitUrb(PortExtension->Common.SelfDevice,
1109 (PURB)Urb);
1110
1111 Irp->IoStatus.Information = (sizeof(USB_DESCRIPTOR_REQUEST) - sizeof(UCHAR)) +
1112 Urb->TransferBufferLength;
1113
1114 ExFreePoolWithTag(Urb, USB_HUB_TAG);
1115
1116 Exit:
1117 USBH_CompleteIrp(Irp, Status);
1118 return Status;
1119 }
1120
1121 NTSTATUS
1122 NTAPI
1123 USBH_DeviceControl(IN PUSBHUB_FDO_EXTENSION HubExtension,
1124 IN PIRP Irp)
1125 {
1126 NTSTATUS Status = STATUS_DEVICE_BUSY;
1127 PIO_STACK_LOCATION IoStack;
1128 ULONG ControlCode;
1129 BOOLEAN IsCheckHubIdle = FALSE;
1130
1131 DPRINT("USBH_DeviceControl: HubExtension - %p, Irp - %p\n",
1132 HubExtension,
1133 Irp);
1134
1135 IoStack = IoGetCurrentIrpStackLocation(Irp);
1136 ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
1137 DPRINT("USBH_DeviceControl: ControlCode - %lX\n", ControlCode);
1138
1139 if ((HubExtension->CurrentPowerState.DeviceState != PowerDeviceD0) &&
1140 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED))
1141 {
1142 IsCheckHubIdle = TRUE;
1143 USBH_HubSetD0(HubExtension);
1144 }
1145
1146 switch (ControlCode)
1147 {
1148 case IOCTL_USB_GET_HUB_CAPABILITIES:
1149 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_HUB_CAPABILITIES\n");
1150 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
1151 {
1152 Status = USBH_IoctlGetHubCapabilities(HubExtension, Irp);
1153 break;
1154 }
1155
1156 USBH_CompleteIrp(Irp, Status);
1157 break;
1158
1159 case IOCTL_USB_HUB_CYCLE_PORT:
1160 DPRINT1("USBH_DeviceControl: IOCTL_USB_HUB_CYCLE_PORT UNIMPLEMENTED. FIXME\n");
1161 DbgBreakPoint();
1162 break;
1163
1164 case IOCTL_USB_GET_NODE_INFORMATION:
1165 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_INFORMATION\n");
1166 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
1167 {
1168 Status = USBH_IoctlGetNodeInformation(HubExtension, Irp);
1169 break;
1170 }
1171
1172 USBH_CompleteIrp(Irp, Status);
1173 break;
1174
1175 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
1176 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
1177 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
1178 {
1179 Status = USBH_IoctlGetNodeConnectionInformation(HubExtension,
1180 Irp,
1181 FALSE);
1182 break;
1183 }
1184
1185 USBH_CompleteIrp(Irp, Status);
1186 break;
1187
1188 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX:
1189 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX\n");
1190 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
1191 {
1192 Status = USBH_IoctlGetNodeConnectionInformation(HubExtension,
1193 Irp,
1194 TRUE);
1195 break;
1196 }
1197
1198 USBH_CompleteIrp(Irp, Status);
1199 break;
1200
1201 case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES:
1202 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES\n");
1203 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
1204 {
1205 Status = USBH_IoctlGetNodeConnectionAttributes(HubExtension, Irp);
1206 break;
1207 }
1208
1209 USBH_CompleteIrp(Irp, Status);
1210 break;
1211
1212 case IOCTL_USB_GET_NODE_CONNECTION_NAME:
1213 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
1214 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
1215 {
1216 Status = USBH_IoctlGetNodeName(HubExtension, Irp);
1217 break;
1218 }
1219
1220 USBH_CompleteIrp(Irp, Status);
1221 break;
1222
1223 case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
1224 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n");
1225 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
1226 {
1227 Status = USBH_IoctlGetNodeConnectionDriverKeyName(HubExtension, Irp);
1228 break;
1229 }
1230
1231 USBH_CompleteIrp(Irp, Status);
1232 break;
1233
1234 case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
1235 DPRINT("USBH_DeviceControl: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
1236 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
1237 {
1238 Status = USBH_IoctlGetDescriptor(HubExtension, Irp);
1239 break;
1240 }
1241
1242 USBH_CompleteIrp(Irp, Status);
1243 break;
1244
1245 case IOCTL_KS_PROPERTY:
1246 DPRINT("USBH_DeviceControl: IOCTL_KS_PROPERTY\n");
1247 Status = STATUS_INVALID_DEVICE_REQUEST;
1248 USBH_CompleteIrp(Irp, Status);
1249 break;
1250
1251 default:
1252 DPRINT1("USBH_DeviceControl: Unhandled IOCTL_ - %lX\n", ControlCode);
1253 Status = USBH_PassIrp(HubExtension->RootHubPdo, Irp);
1254 break;
1255 }
1256
1257 if (IsCheckHubIdle)
1258 {
1259 USBH_CheckHubIdle(HubExtension);
1260 }
1261
1262 return Status;
1263 }
1264
1265 NTSTATUS
1266 NTAPI
1267 USBH_PdoInternalControl(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
1268 IN PIRP Irp)
1269 {
1270 PUSBHUB_FDO_EXTENSION HubExtension;
1271 NTSTATUS Status = STATUS_NOT_SUPPORTED;
1272 ULONG ControlCode;
1273 PIO_STACK_LOCATION IoStack;
1274 PULONG HubCount;
1275
1276 DPRINT_IOCTL("USBH_PdoInternalControl: PortExtension - %p, Irp - %p\n",
1277 PortExtension,
1278 Irp);
1279
1280 HubExtension = PortExtension->HubExtension;
1281
1282 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_NOT_CONNECTED)
1283 {
1284 Status = STATUS_DEVICE_NOT_CONNECTED;
1285 goto Exit;
1286 }
1287
1288 if (PortExtension->CurrentPowerState.DeviceState != PowerDeviceD0)
1289 {
1290 Status = STATUS_DEVICE_POWERED_OFF;
1291 goto Exit;
1292 }
1293
1294 IoStack = IoGetCurrentIrpStackLocation(Irp);
1295 ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
1296
1297 if (ControlCode == IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO)
1298 {
1299 HubExtension = PortExtension->RootHubExtension;
1300 DPRINT("USBH_PdoInternalControl: HubExtension - %p\n", HubExtension);
1301 }
1302
1303 if (!HubExtension)
1304 {
1305 Status = STATUS_DEVICE_BUSY;
1306 goto Exit;
1307 }
1308
1309 switch (ControlCode)
1310 {
1311 case IOCTL_INTERNAL_USB_SUBMIT_URB:
1312 return USBH_PdoIoctlSubmitUrb(PortExtension, Irp);
1313
1314 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
1315 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
1316 return USBH_PortIdleNotificationRequest(PortExtension, Irp);
1317
1318 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
1319 DPRINT("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
1320 return USBH_PdoIoctlGetPortStatus(PortExtension, Irp);
1321
1322 case IOCTL_INTERNAL_USB_RESET_PORT:
1323 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_RESET_PORT\n");
1324 return USBH_PdoIoctlResetPort(PortExtension, Irp);
1325
1326 case IOCTL_INTERNAL_USB_ENABLE_PORT:
1327 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_ENABLE_PORT\n");
1328 DbgBreakPoint();
1329 break;
1330
1331 case IOCTL_INTERNAL_USB_CYCLE_PORT:
1332 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_CYCLE_PORT\n");
1333 DbgBreakPoint();
1334 break;
1335
1336 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
1337 DPRINT("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
1338 *(PVOID *)IoStack->Parameters.Others.Argument1 = PortExtension->DeviceHandle;
1339 Status = STATUS_SUCCESS;
1340 break;
1341
1342 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
1343 DPRINT("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_HUB_COUNT. PortPdoFlags - %lX\n",
1344 PortExtension->PortPdoFlags);
1345
1346 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE))
1347 {
1348 Status = STATUS_INVALID_PARAMETER;
1349 break;
1350 }
1351
1352 HubCount = IoStack->Parameters.Others.Argument1;
1353
1354 ++*HubCount;
1355
1356 Status = USBH_SyncGetHubCount(HubExtension->LowerDevice,
1357 HubCount);
1358
1359 DPRINT("USBH_PdoInternalControl: *HubCount - %x\n", *HubCount);
1360 break;
1361
1362 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
1363 DPRINT("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO. PortPdoFlags - %lX\n",
1364 PortExtension->PortPdoFlags);
1365
1366 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE))
1367 {
1368 DbgBreakPoint();
1369 Status = STATUS_SUCCESS;
1370
1371 *(PVOID *)IoStack->Parameters.Others.Argument1 = NULL;
1372
1373 USBH_CompleteIrp(Irp, Status);
1374 break;
1375 }
1376
1377 ASSERT(HubExtension->RootHubPdo);
1378 return USBH_PassIrp(HubExtension->RootHubPdo, Irp);
1379
1380 case IOCTL_INTERNAL_USB_GET_HUB_NAME:
1381 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_HUB_NAME\n");
1382 DbgBreakPoint();
1383 break;
1384
1385 case IOCTL_GET_HCD_DRIVERKEY_NAME:
1386 DPRINT1("USBH_PdoInternalControl: IOCTL_GET_HCD_DRIVERKEY_NAME\n");
1387 DbgBreakPoint();
1388 break;
1389
1390 case IOCTL_INTERNAL_USB_GET_BUS_INFO:
1391 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_BUS_INFO\n");
1392 DbgBreakPoint();
1393 break;
1394
1395 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
1396 DPRINT1("USBH_PdoInternalControl: IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
1397 DbgBreakPoint();
1398 break;
1399
1400 default:
1401 DPRINT1("USBH_PdoInternalControl: unhandled IOCTL_ - %lX\n", ControlCode);
1402 break;
1403 }
1404
1405 Exit:
1406 USBH_CompleteIrp(Irp, Status);
1407 return Status;
1408 }