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