c5a77aef5135ba2ebc25de6b1f4e0ea7ada23fd7
[reactos.git] / drivers / usb / usbport / roothub.c
1 /*
2 * PROJECT: ReactOS USB Port Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBPort root hub implementation
5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #include "usbport.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #define NDEBUG_USBPORT_CORE
14 #include "usbdebug.h"
15
16 RHSTATUS
17 NTAPI
18 USBPORT_MPStatusToRHStatus(IN MPSTATUS MPStatus)
19 {
20 RHSTATUS RHStatus = RH_STATUS_SUCCESS;
21
22 //DPRINT("USBPORT_MPStatusToRHStatus: MPStatus - %x\n", MPStatus);
23
24 if (MPStatus)
25 {
26 RHStatus = (MPStatus != MP_STATUS_FAILURE);
27 ++RHStatus;
28 }
29
30 return RHStatus;
31 }
32
33 MPSTATUS
34 NTAPI
35 USBPORT_RH_SetFeatureUSB2PortPower(IN PDEVICE_OBJECT FdoDevice,
36 IN USHORT Port)
37 {
38 PUSBPORT_DEVICE_EXTENSION FdoExtension;
39 PUSBPORT_REGISTRATION_PACKET Packet;
40 PDEVICE_RELATIONS CompanionControllersList;
41 PUSBPORT_REGISTRATION_PACKET CompanionPacket;
42 PDEVICE_OBJECT CompanionFdoDevice;
43 PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension;
44 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
45 USHORT ix;
46 PDEVICE_OBJECT * Entry;
47 ULONG NumController = 0;
48
49 DPRINT("USBPORT_RootHub_PowerUsb2Port: FdoDevice - %p, Port - %p\n",
50 FdoDevice,
51 Port);
52
53 FdoExtension = FdoDevice->DeviceExtension;
54 Packet = &FdoExtension->MiniPortInterface->Packet;
55
56 CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice,
57 FALSE,
58 TRUE);
59
60 if (!CompanionControllersList)
61 {
62 Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port);
63 return MP_STATUS_SUCCESS;
64 }
65
66 Entry = &CompanionControllersList->Objects[0];
67
68 while (NumController < CompanionControllersList->Count)
69 {
70 CompanionFdoDevice = *Entry;
71
72 CompanionFdoExtension = CompanionFdoDevice->DeviceExtension;
73 CompanionPacket = &CompanionFdoExtension->MiniPortInterface->Packet;
74
75 PdoExtension = CompanionFdoExtension->RootHubPdo->DeviceExtension;
76
77 for (ix = 0;
78 (PdoExtension->CommonExtension.PnpStateFlags & USBPORT_PNP_STATE_STARTED) &&
79 ix < PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts;
80 ++ix)
81 {
82 CompanionPacket->RH_SetFeaturePortPower(CompanionFdoExtension->MiniPortExt,
83 ix + 1);
84 }
85
86 ++NumController;
87 ++Entry;
88 }
89
90 Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port);
91
92 if (CompanionControllersList)
93 {
94 ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG);
95 }
96
97 return MP_STATUS_SUCCESS;
98 }
99
100 RHSTATUS
101 NTAPI
102 USBPORT_RootHubClassCommand(IN PDEVICE_OBJECT FdoDevice,
103 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
104 IN PVOID Buffer,
105 IN PULONG BufferLength)
106 {
107 PUSBPORT_DEVICE_EXTENSION FdoExtension;
108 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
109 PUSBPORT_REGISTRATION_PACKET Packet;
110 USHORT Port;
111 USHORT Feature;
112 MPSTATUS MPStatus;
113 RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL;
114 KIRQL OldIrql;
115
116 DPRINT("USBPORT_RootHubClassCommand: USB command - %x, *BufferLength - %x\n",
117 SetupPacket->bRequest,
118 *BufferLength);
119
120 FdoExtension = FdoDevice->DeviceExtension;
121 PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
122 Packet = &FdoExtension->MiniPortInterface->Packet;
123
124 Port = SetupPacket->wIndex.W;
125
126 switch (SetupPacket->bRequest)
127 {
128 case USB_REQUEST_GET_STATUS:
129 {
130 if (!Buffer)
131 {
132 return RHStatus;
133 }
134
135 *(PULONG)Buffer = 0;
136
137 if (SetupPacket->bmRequestType.Recipient == BMREQUEST_TO_OTHER)
138 {
139 ASSERT(*BufferLength >= 4);
140
141 if (Port > PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts ||
142 Port <= 0 ||
143 SetupPacket->wLength < 4)
144 {
145 return RHStatus;
146 }
147
148 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
149
150 MPStatus = Packet->RH_GetPortStatus(FdoExtension->MiniPortExt,
151 SetupPacket->wIndex.W,
152 Buffer);
153
154 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
155 }
156 else
157 {
158 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
159
160 MPStatus = Packet->RH_GetHubStatus(FdoExtension->MiniPortExt,
161 Buffer);
162
163 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
164 }
165
166 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
167 break;
168 }
169
170 case USB_REQUEST_CLEAR_FEATURE:
171 Feature = SetupPacket->wValue.W;
172
173 if ((SetupPacket->bmRequestType.Recipient) != USBPORT_RECIPIENT_ROOT_PORT)
174 {
175 if (Feature == FEATURE_C_HUB_LOCAL_POWER)
176 {
177 RHStatus = RH_STATUS_SUCCESS;
178 return RHStatus;
179 }
180
181 if (Feature == FEATURE_C_HUB_OVER_CURRENT)
182 {
183 MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt,
184 0);
185 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
186 return RHStatus;
187 }
188
189 DbgBreakPoint();
190 return RHStatus;
191 }
192
193 switch (Feature)
194 {
195 case FEATURE_PORT_ENABLE:
196 MPStatus = Packet->RH_ClearFeaturePortEnable(FdoExtension->MiniPortExt,
197 Port);
198 break;
199
200 case FEATURE_PORT_SUSPEND:
201 MPStatus = Packet->RH_ClearFeaturePortSuspend(FdoExtension->MiniPortExt,
202 Port);
203 break;
204
205 case FEATURE_PORT_POWER:
206 MPStatus = Packet->RH_ClearFeaturePortPower(FdoExtension->MiniPortExt,
207 Port);
208 break;
209
210 case FEATURE_C_PORT_CONNECTION:
211 MPStatus = Packet->RH_ClearFeaturePortConnectChange(FdoExtension->MiniPortExt,
212 Port);
213 break;
214
215 case FEATURE_C_PORT_ENABLE:
216 MPStatus = Packet->RH_ClearFeaturePortEnableChange(FdoExtension->MiniPortExt,
217 Port);
218 break;
219
220 case FEATURE_C_PORT_SUSPEND:
221 MPStatus = Packet->RH_ClearFeaturePortSuspendChange(FdoExtension->MiniPortExt,
222 Port);
223 break;
224
225 case FEATURE_C_PORT_OVER_CURRENT:
226 MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt,
227 Port);
228 break;
229
230 case FEATURE_C_PORT_RESET:
231 MPStatus = Packet->RH_ClearFeaturePortResetChange(FdoExtension->MiniPortExt,
232 Port);
233 break;
234
235 default:
236 DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n",
237 Feature);
238 return RHStatus;
239 }
240
241 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
242 break;
243
244 case USB_REQUEST_SET_FEATURE:
245 if (SetupPacket->bmRequestType.Recipient != USBPORT_RECIPIENT_ROOT_PORT)
246 {
247 return RHStatus;
248 }
249
250 Feature = SetupPacket->wValue.W;
251
252 switch (Feature)
253 {
254 case FEATURE_PORT_ENABLE:
255 MPStatus = Packet->RH_SetFeaturePortEnable(FdoExtension->MiniPortExt,
256 Port);
257 break;
258
259 case FEATURE_PORT_SUSPEND:
260 MPStatus = Packet->RH_SetFeaturePortSuspend(FdoExtension->MiniPortExt,
261 Port);
262 break;
263
264 case FEATURE_PORT_RESET:
265 MPStatus = Packet->RH_SetFeaturePortReset(FdoExtension->MiniPortExt,
266 Port);
267 break;
268
269 case FEATURE_PORT_POWER:
270 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
271 {
272 MPStatus = USBPORT_RH_SetFeatureUSB2PortPower(FdoDevice, Port);
273 }
274 else
275 {
276 MPStatus = Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt,
277 Port);
278 }
279
280 break;
281
282 default:
283 DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n",
284 Feature);
285 return RHStatus;
286 }
287
288 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
289 break;
290
291 case USB_REQUEST_GET_DESCRIPTOR:
292 if (Buffer &&
293 SetupPacket->wValue.W == 0 &&
294 SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST)
295 {
296 SIZE_T DescriptorLength;
297
298 DescriptorLength = PdoExtension->RootHubDescriptors->Descriptor.bDescriptorLength;
299
300 if (*BufferLength < DescriptorLength)
301 DescriptorLength = *BufferLength;
302
303 RtlCopyMemory(Buffer,
304 &PdoExtension->RootHubDescriptors->Descriptor,
305 DescriptorLength);
306
307 *BufferLength = DescriptorLength;
308 RHStatus = RH_STATUS_SUCCESS;
309 }
310
311 break;
312
313 default:
314 DPRINT1("USBPORT_RootHubClassCommand: Not supported USB request - %x\n",
315 SetupPacket->bRequest);
316 //USB_REQUEST_SET_ADDRESS 0x05
317 //USB_REQUEST_SET_DESCRIPTOR 0x07
318 //USB_REQUEST_GET_CONFIGURATION 0x08
319 //USB_REQUEST_SET_CONFIGURATION 0x09
320 //USB_REQUEST_GET_INTERFACE 0x0A
321 //USB_REQUEST_SET_INTERFACE 0x0B
322 //USB_REQUEST_SYNC_FRAME 0x0C
323 break;
324 }
325
326 return RHStatus;
327 }
328
329 RHSTATUS
330 NTAPI
331 USBPORT_RootHubStandardCommand(IN PDEVICE_OBJECT FdoDevice,
332 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
333 IN PVOID Buffer,
334 IN OUT PULONG TransferLength)
335 {
336 PUSBPORT_DEVICE_EXTENSION FdoExtension;
337 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
338 PUSBPORT_REGISTRATION_PACKET Packet;
339 SIZE_T Length;
340 PVOID Descriptor;
341 SIZE_T DescriptorLength;
342 MPSTATUS MPStatus;
343 RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL;
344 KIRQL OldIrql;
345
346 DPRINT("USBPORT_RootHubStandardCommand: USB command - %x, TransferLength - %p\n",
347 SetupPacket->bRequest,
348 TransferLength);
349
350 FdoExtension = FdoDevice->DeviceExtension;
351 PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
352 Packet = &FdoExtension->MiniPortInterface->Packet;
353
354 switch (SetupPacket->bRequest)
355 {
356 case USB_REQUEST_GET_DESCRIPTOR:
357 if (SetupPacket->wValue.LowByte ||
358 !(SetupPacket->bmRequestType.Dir))
359 {
360 return RHStatus;
361 }
362
363 switch (SetupPacket->wValue.HiByte)
364 {
365 case USB_DEVICE_DESCRIPTOR_TYPE:
366 Descriptor = &PdoExtension->RootHubDescriptors->DeviceDescriptor;
367 DescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR);
368 break;
369
370 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
371 Descriptor = &PdoExtension->RootHubDescriptors->ConfigDescriptor;
372 DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) +
373 sizeof(USB_INTERFACE_DESCRIPTOR) +
374 sizeof(USB_ENDPOINT_DESCRIPTOR);
375 break;
376
377 default:
378 DPRINT1("USBPORT_RootHubStandardCommand: Not supported Descriptor Type - %x\n",
379 SetupPacket->wValue.HiByte);
380 return RHStatus;
381 }
382
383 if (!Descriptor)
384 {
385 return RHStatus;
386 }
387
388 if (*TransferLength >= DescriptorLength)
389 Length = DescriptorLength;
390 else
391 Length = *TransferLength;
392
393 RtlCopyMemory(Buffer, Descriptor, Length);
394 *TransferLength = Length;
395
396 RHStatus = RH_STATUS_SUCCESS;
397 break;
398
399 case USB_REQUEST_GET_STATUS:
400 if (!SetupPacket->wValue.W &&
401 SetupPacket->wLength == sizeof(USHORT) &&
402 !SetupPacket->wIndex.W &&
403 SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST)
404 {
405 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
406
407 MPStatus = Packet->RH_GetStatus(FdoExtension->MiniPortExt,
408 Buffer);
409
410 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
411
412 *TransferLength = sizeof(USHORT);
413 RHStatus = USBPORT_MPStatusToRHStatus(MPStatus);
414 }
415
416 break;
417
418 case USB_REQUEST_GET_CONFIGURATION:
419 if (SetupPacket->wValue.W ||
420 SetupPacket->wIndex.W ||
421 SetupPacket->wLength != 1 ||
422 SetupPacket->bmRequestType.Dir == BMREQUEST_HOST_TO_DEVICE)
423 {
424 return RHStatus;
425 }
426
427 Length = 0;
428
429 if (*TransferLength >= 1)
430 {
431 Length = 1;
432 RtlCopyMemory(Buffer, &PdoExtension->ConfigurationValue, Length);
433 }
434
435 *TransferLength = Length;
436
437 RHStatus = RH_STATUS_SUCCESS;
438 break;
439
440 case USB_REQUEST_SET_CONFIGURATION:
441 if (!SetupPacket->wIndex.W &&
442 !SetupPacket->wLength &&
443 !(SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST))
444 {
445 if (SetupPacket->wValue.W == 0 ||
446 SetupPacket->wValue.W ==
447 PdoExtension->RootHubDescriptors->ConfigDescriptor.bConfigurationValue)
448 {
449 PdoExtension->ConfigurationValue = SetupPacket->wValue.LowByte;
450 RHStatus = RH_STATUS_SUCCESS;
451 }
452 }
453
454 break;
455
456 case USB_REQUEST_SET_ADDRESS:
457 if (!SetupPacket->wIndex.W &&
458 !SetupPacket->wLength &&
459 !(SetupPacket->bmRequestType.Dir))
460 {
461 PdoExtension->DeviceHandle.DeviceAddress = SetupPacket->wValue.LowByte;
462 RHStatus = RH_STATUS_SUCCESS;
463 break;
464 }
465
466 break;
467
468 default:
469 DPRINT1("USBPORT_RootHubStandardCommand: Not supported USB request - %x\n",
470 SetupPacket->bRequest);
471 //USB_REQUEST_CLEAR_FEATURE 0x01
472 //USB_REQUEST_SET_FEATURE 0x03
473 //USB_REQUEST_SET_DESCRIPTOR 0x07
474 //USB_REQUEST_GET_INTERFACE 0x0A
475 //USB_REQUEST_SET_INTERFACE 0x0B
476 //USB_REQUEST_SYNC_FRAME 0x0C
477 break;
478 }
479
480 return RHStatus;
481 }
482
483 RHSTATUS
484 NTAPI
485 USBPORT_RootHubEndpoint0(IN PUSBPORT_TRANSFER Transfer)
486 {
487 PDEVICE_OBJECT FdoDevice;
488 SIZE_T TransferLength;
489 PVOID Buffer;
490 PURB Urb;
491 PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
492 UCHAR Type;
493 RHSTATUS RHStatus;
494
495 DPRINT("USBPORT_RootHubEndpoint0: Transfer - %p\n", Transfer);
496
497 TransferLength = Transfer->TransferParameters.TransferBufferLength;
498 Urb = Transfer->Urb;
499 FdoDevice = Transfer->Endpoint->FdoDevice;
500
501 if (TransferLength > 0)
502 Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa;
503 else
504 Buffer = NULL;
505
506 SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)Urb->UrbControlTransfer.SetupPacket;
507
508 Type = SetupPacket->bmRequestType.Type;
509
510 if (Type == BMREQUEST_STANDARD)
511 {
512 RHStatus = USBPORT_RootHubStandardCommand(FdoDevice,
513 SetupPacket,
514 Buffer,
515 &TransferLength);
516 }
517 else if (Type == BMREQUEST_CLASS)
518 {
519 RHStatus = USBPORT_RootHubClassCommand(FdoDevice,
520 SetupPacket,
521 Buffer,
522 &TransferLength);
523 }
524 else
525 {
526 return RH_STATUS_UNSUCCESSFUL;
527 }
528
529 if (RHStatus == RH_STATUS_SUCCESS)
530 Transfer->CompletedTransferLen = TransferLength;
531
532 return RHStatus;
533 }
534
535 RHSTATUS
536 NTAPI
537 USBPORT_RootHubSCE(IN PUSBPORT_TRANSFER Transfer)
538 {
539 PUSBPORT_ENDPOINT Endpoint;
540 PUSBPORT_DEVICE_EXTENSION FdoExtension;
541 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
542 PUSBPORT_REGISTRATION_PACKET Packet;
543 ULONG TransferLength;
544 USB_PORT_STATUS_AND_CHANGE PortStatus;
545 USB_HUB_STATUS_AND_CHANGE HubStatus;
546 PVOID Buffer;
547 PULONG AddressBitMap;
548 ULONG Port;
549 PURB Urb;
550 RHSTATUS RHStatus = RH_STATUS_NO_CHANGES;
551 PUSB_HUB_DESCRIPTOR HubDescriptor;
552 UCHAR NumberOfPorts;
553
554 DPRINT("USBPORT_RootHubSCE: Transfer - %p\n", Transfer);
555
556 Endpoint = Transfer->Endpoint;
557
558 FdoExtension = Endpoint->FdoDevice->DeviceExtension;
559 PdoExtension = FdoExtension->RootHubPdo->DeviceExtension;
560 Packet = &FdoExtension->MiniPortInterface->Packet;
561
562 HubDescriptor = &PdoExtension->RootHubDescriptors->Descriptor;
563 NumberOfPorts = HubDescriptor->bNumberOfPorts;
564
565 PortStatus.AsUlong32 = 0;
566 HubStatus.AsUlong32 = 0;
567
568 Urb = Transfer->Urb;
569 TransferLength = Transfer->TransferParameters.TransferBufferLength;
570
571 if (TransferLength)
572 {
573 Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa;
574 }
575 else
576 {
577 Buffer = NULL;
578 }
579
580 /* Check parameters */
581
582 if (!Buffer)
583 {
584 /* Not valid parameter */
585 DPRINT1("USBPORT_RootHubSCE: Error! Buffer is NULL\n");
586 return RH_STATUS_UNSUCCESSFUL;
587 }
588
589 if ((TransferLength < (NumberOfPorts / 8 + 1)))
590 {
591 /* Not valid parameters */
592 DPRINT1("USBPORT_RootHubSCE: Error! TransferLength - %x, NumberOfPorts - %x\n",
593 TransferLength,
594 NumberOfPorts);
595
596 return RH_STATUS_UNSUCCESSFUL;
597 }
598
599 RtlZeroMemory(Buffer, TransferLength);
600
601 AddressBitMap = Buffer;
602
603 /* Scan all the ports for changes */
604 for (Port = 1; Port <= NumberOfPorts; Port++)
605 {
606 DPRINT_CORE("USBPORT_RootHubSCE: Port - %p\n", Port);
607
608 /* Request the port status from miniport */
609 if (Packet->RH_GetPortStatus(FdoExtension->MiniPortExt,
610 Port,
611 &PortStatus))
612 {
613 /* Miniport returned an error */
614 DPRINT1("USBPORT_RootHubSCE: RH_GetPortStatus failed\n");
615 return RH_STATUS_UNSUCCESSFUL;
616 }
617
618 if (PortStatus.PortChange.Usb20PortChange.ConnectStatusChange ||
619 PortStatus.PortChange.Usb20PortChange.PortEnableDisableChange ||
620 PortStatus.PortChange.Usb20PortChange.SuspendChange ||
621 PortStatus.PortChange.Usb20PortChange.OverCurrentIndicatorChange ||
622 PortStatus.PortChange.Usb20PortChange.ResetChange)
623 {
624 /* At the port status there is a change */
625 AddressBitMap[Port >> 5] |= 1 << (Port & 0x1F);
626 RHStatus = RH_STATUS_SUCCESS;
627 }
628 }
629
630 /* Request the hub status from miniport */
631 if (!Packet->RH_GetHubStatus(FdoExtension->MiniPortExt, &HubStatus))
632 {
633 if (HubStatus.HubChange.LocalPowerChange == 1 ||
634 HubStatus.HubChange.OverCurrentChange == 1)
635 {
636 /* At the hub status there is a change */
637 AddressBitMap[0] |= 1;
638 RHStatus = RH_STATUS_SUCCESS;
639 }
640
641 if (RHStatus == RH_STATUS_SUCCESS)
642 {
643 /* Done */
644 Urb->UrbControlTransfer.TransferBufferLength = TransferLength;
645 return RH_STATUS_SUCCESS;
646 }
647
648 if (RHStatus == RH_STATUS_NO_CHANGES)
649 {
650 /* No changes. Enable IRQs for miniport root hub */
651 Packet->RH_EnableIrq(FdoExtension->MiniPortExt);
652 }
653
654 return RHStatus;
655 }
656
657 /* Miniport returned an error */
658 DPRINT1("USBPORT_RootHubSCE: RH_GetHubStatus failed\n");
659 return RH_STATUS_UNSUCCESSFUL;
660 }
661
662 VOID
663 NTAPI
664 USBPORT_RootHubEndpointWorker(IN PUSBPORT_ENDPOINT Endpoint)
665 {
666 PDEVICE_OBJECT FdoDevice;
667 PUSBPORT_DEVICE_EXTENSION FdoExtension;
668 PUSBPORT_REGISTRATION_PACKET Packet;
669 PUSBPORT_TRANSFER Transfer;
670 RHSTATUS RHStatus;
671 USBD_STATUS USBDStatus;
672 KIRQL OldIrql;
673
674 DPRINT_CORE("USBPORT_RootHubEndpointWorker: Endpoint - %p\n", Endpoint);
675
676 FdoDevice = Endpoint->FdoDevice;
677 FdoExtension = FdoDevice->DeviceExtension;
678 Packet = &FdoExtension->MiniPortInterface->Packet;
679
680 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
681 if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
682 {
683 Packet->CheckController(FdoExtension->MiniPortExt);
684 }
685 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
686
687 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
688
689 Transfer = CONTAINING_RECORD(Endpoint->TransferList.Flink,
690 USBPORT_TRANSFER,
691 TransferLink);
692
693 if (IsListEmpty(&Endpoint->TransferList) ||
694 Endpoint->TransferList.Flink == NULL ||
695 !Transfer)
696 {
697 if (Endpoint->StateLast == USBPORT_ENDPOINT_REMOVE)
698 {
699 ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList,
700 &Endpoint->CloseLink,
701 &FdoExtension->EndpointClosedSpinLock);
702 }
703
704 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
705
706 USBPORT_FlushCancelList(Endpoint);
707 return;
708 }
709
710 if (Transfer->Flags & (TRANSFER_FLAG_ABORTED | TRANSFER_FLAG_CANCELED))
711 {
712 RemoveEntryList(&Transfer->TransferLink);
713 InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink);
714
715 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
716 USBPORT_FlushCancelList(Endpoint);
717 return;
718 }
719
720 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
721
722 if (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
723 RHStatus = USBPORT_RootHubEndpoint0(Transfer);
724 else
725 RHStatus = USBPORT_RootHubSCE(Transfer);
726
727 if (RHStatus != RH_STATUS_NO_CHANGES)
728 {
729 if (RHStatus == RH_STATUS_SUCCESS)
730 USBDStatus = USBD_STATUS_SUCCESS;
731 else
732 USBDStatus = USBD_STATUS_STALL_PID;
733
734 KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
735 USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
736 KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
737
738 USBPORT_FlushCancelList(Endpoint);
739 return;
740 }
741
742 USBPORT_FlushCancelList(Endpoint);
743 }
744
745 NTSTATUS
746 NTAPI
747 USBPORT_RootHubCreateDevice(IN PDEVICE_OBJECT FdoDevice,
748 IN PDEVICE_OBJECT PdoDevice)
749 {
750 PUSBPORT_DEVICE_EXTENSION FdoExtension;
751 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
752 PUSBPORT_REGISTRATION_PACKET Packet;
753 PUSBPORT_DEVICE_HANDLE DeviceHandle;
754 USBPORT_ROOT_HUB_DATA RootHubData;
755 ULONG NumMaskByte;
756 ULONG DescriptorsLength;
757 PUSBPORT_RH_DESCRIPTORS Descriptors;
758 PUSB_DEVICE_DESCRIPTOR RH_DeviceDescriptor;
759 PUSB_CONFIGURATION_DESCRIPTOR RH_ConfigurationDescriptor;
760 PUSB_INTERFACE_DESCRIPTOR RH_InterfaceDescriptor;
761 PUSB_ENDPOINT_DESCRIPTOR RH_EndPointDescriptor;
762 PUSB_HUB_DESCRIPTOR RH_HubDescriptor;
763 ULONG ix;
764 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
765 NTSTATUS Status;
766
767 DPRINT("USBPORT_RootHubCreateDevice: FdoDevice - %p, PdoDevice - %p\n",
768 FdoDevice,
769 PdoDevice);
770
771 FdoExtension = FdoDevice->DeviceExtension;
772 PdoExtension = PdoDevice->DeviceExtension;
773 Packet = &FdoExtension->MiniPortInterface->Packet;
774
775 DeviceHandle = &PdoExtension->DeviceHandle;
776 USBPORT_AddDeviceHandle(FdoDevice, DeviceHandle);
777
778 InitializeListHead(&DeviceHandle->PipeHandleList);
779
780 DeviceHandle->IsRootHub = TRUE;
781 DeviceHandle->DeviceSpeed = UsbFullSpeed;
782 DeviceHandle->Flags = DEVICE_HANDLE_FLAG_ROOTHUB;
783
784 RtlZeroMemory(&RootHubData, sizeof(RootHubData));
785
786 Packet->RH_GetRootHubData(FdoExtension->MiniPortExt, &RootHubData);
787
788 ASSERT(RootHubData.NumberOfPorts != 0);
789 NumMaskByte = ((RootHubData.NumberOfPorts - 1) >> 3) + 1;
790
791 DescriptorsLength = sizeof(USB_DEVICE_DESCRIPTOR) +
792 sizeof(USB_CONFIGURATION_DESCRIPTOR) +
793 sizeof(USB_INTERFACE_DESCRIPTOR) +
794 sizeof(USB_ENDPOINT_DESCRIPTOR) +
795 (sizeof(USB_HUB_DESCRIPTOR) + 2 * NumMaskByte);
796
797 Descriptors = ExAllocatePoolWithTag(NonPagedPool,
798 DescriptorsLength,
799 USB_PORT_TAG);
800
801 if (Descriptors)
802 {
803 RtlZeroMemory(Descriptors, DescriptorsLength);
804
805 PdoExtension->RootHubDescriptors = Descriptors;
806
807 RH_DeviceDescriptor = &PdoExtension->RootHubDescriptors->DeviceDescriptor;
808
809 RH_DeviceDescriptor->bLength = sizeof(USB_DEVICE_DESCRIPTOR);
810 RH_DeviceDescriptor->bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE;
811 RH_DeviceDescriptor->bcdUSB = 0x100;
812 RH_DeviceDescriptor->bDeviceClass = USB_DEVICE_CLASS_HUB;
813 RH_DeviceDescriptor->bDeviceSubClass = 0x01;
814 RH_DeviceDescriptor->bDeviceProtocol = 0x00;
815 RH_DeviceDescriptor->bMaxPacketSize0 = 0x08;
816 RH_DeviceDescriptor->idVendor = FdoExtension->VendorID;
817 RH_DeviceDescriptor->idProduct = FdoExtension->DeviceID;
818 RH_DeviceDescriptor->bcdDevice = FdoExtension->RevisionID;
819 RH_DeviceDescriptor->iManufacturer = 0x00;
820 RH_DeviceDescriptor->iProduct = 0x00;
821 RH_DeviceDescriptor->iSerialNumber = 0x00;
822 RH_DeviceDescriptor->bNumConfigurations = 0x01;
823
824 RH_ConfigurationDescriptor = &PdoExtension->RootHubDescriptors->ConfigDescriptor;
825
826 RH_ConfigurationDescriptor->bLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
827 RH_ConfigurationDescriptor->bDescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE;
828
829 RH_ConfigurationDescriptor->wTotalLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) +
830 sizeof(USB_INTERFACE_DESCRIPTOR) +
831 sizeof(USB_ENDPOINT_DESCRIPTOR);
832
833 RH_ConfigurationDescriptor->bNumInterfaces = 0x01;
834 RH_ConfigurationDescriptor->bConfigurationValue = 0x01;
835 RH_ConfigurationDescriptor->iConfiguration = 0x00;
836 RH_ConfigurationDescriptor->bmAttributes = USB_CONFIG_SELF_POWERED;
837 RH_ConfigurationDescriptor->MaxPower = 0x00;
838
839 RH_InterfaceDescriptor = &PdoExtension->RootHubDescriptors->InterfaceDescriptor;
840
841 RH_InterfaceDescriptor->bLength = sizeof(USB_INTERFACE_DESCRIPTOR);
842 RH_InterfaceDescriptor->bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE;
843 RH_InterfaceDescriptor->bInterfaceNumber = 0x00;
844 RH_InterfaceDescriptor->bAlternateSetting = 0x00;
845 RH_InterfaceDescriptor->bNumEndpoints = 0x01;
846 RH_InterfaceDescriptor->bInterfaceClass = USB_DEVICE_CLASS_HUB;
847 RH_InterfaceDescriptor->bInterfaceSubClass = 0x01;
848 RH_InterfaceDescriptor->bInterfaceProtocol = 0x00;
849 RH_InterfaceDescriptor->iInterface = 0x00;
850
851 RH_EndPointDescriptor = &PdoExtension->RootHubDescriptors->EndPointDescriptor;
852
853 RH_EndPointDescriptor->bLength = sizeof(USB_ENDPOINT_DESCRIPTOR);
854 RH_EndPointDescriptor->bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
855 RH_EndPointDescriptor->bEndpointAddress = 0x81;
856 RH_EndPointDescriptor->bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT; // SCE endpoint
857 RH_EndPointDescriptor->wMaxPacketSize = 0x0008;
858 RH_EndPointDescriptor->bInterval = 0x0C; // 12 msec
859
860 RH_HubDescriptor = &PdoExtension->RootHubDescriptors->Descriptor;
861
862 RH_HubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR) + 2 * NumMaskByte;
863
864 if (Packet->MiniPortVersion == USB_MINIPORT_VERSION_OHCI ||
865 Packet->MiniPortVersion == USB_MINIPORT_VERSION_UHCI ||
866 Packet->MiniPortVersion == USB_MINIPORT_VERSION_EHCI)
867 {
868 RH_HubDescriptor->bDescriptorType = USB_20_HUB_DESCRIPTOR_TYPE;
869 }
870 else if (Packet->MiniPortVersion == USB_MINIPORT_VERSION_XHCI)
871 {
872 RH_HubDescriptor->bDescriptorType = USB_30_HUB_DESCRIPTOR_TYPE;
873 }
874 else
875 {
876 DPRINT1("USBPORT_RootHubCreateDevice: Unknown MiniPortVersion - %x\n",
877 Packet->MiniPortVersion);
878
879 DbgBreakPoint();
880 }
881
882 RH_HubDescriptor->bNumberOfPorts = RootHubData.NumberOfPorts;
883 RH_HubDescriptor->wHubCharacteristics = RootHubData.HubCharacteristics.AsUSHORT;
884 RH_HubDescriptor->bPowerOnToPowerGood = RootHubData.PowerOnToPowerGood;
885 RH_HubDescriptor->bHubControlCurrent = RootHubData.HubControlCurrent;
886
887 for (ix = 0; ix < NumMaskByte; ix += 2)
888 {
889 RH_HubDescriptor->bRemoveAndPowerMask[ix] = 0;
890 RH_HubDescriptor->bRemoveAndPowerMask[ix + 1] = -1;
891 }
892
893 EndpointDescriptor = &DeviceHandle->PipeHandle.EndpointDescriptor;
894
895 EndpointDescriptor->bLength = sizeof(USB_ENDPOINT_DESCRIPTOR);
896 EndpointDescriptor->bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
897 EndpointDescriptor->bEndpointAddress = 0x00;
898 EndpointDescriptor->bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
899 EndpointDescriptor->wMaxPacketSize = 0x0040;
900 EndpointDescriptor->bInterval = 0x00;
901
902 Status = USBPORT_OpenPipe(FdoDevice,
903 DeviceHandle,
904 &DeviceHandle->PipeHandle,
905 NULL);
906 }
907 else
908 {
909 Status = STATUS_INSUFFICIENT_RESOURCES;
910 }
911
912 return Status;
913 }
914
915 ULONG
916 NTAPI
917 USBPORT_InvalidateRootHub(PVOID MiniPortExtension)
918 {
919 PUSBPORT_DEVICE_EXTENSION FdoExtension;
920 PDEVICE_OBJECT FdoDevice;
921 PDEVICE_OBJECT PdoDevice;
922 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
923 PUSBPORT_ENDPOINT Endpoint = NULL;
924
925 DPRINT("USBPORT_InvalidateRootHub ... \n");
926
927 FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
928 sizeof(USBPORT_DEVICE_EXTENSION));
929
930 FdoDevice = FdoExtension->CommonExtension.SelfDevice;
931
932 if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND &&
933 FdoExtension->Flags & USBPORT_FLAG_HC_WAKE_SUPPORT &&
934 FdoExtension->MiniPortFlags & USBPORT_MPFLAG_SUSPENDED &&
935 FdoExtension->TimerFlags & USBPORT_TMFLAG_WAKE)
936 {
937 USBPORT_HcQueueWakeDpc(FdoDevice);
938 return 0;
939 }
940
941 FdoExtension->MiniPortInterface->Packet.RH_DisableIrq(FdoExtension->MiniPortExt);
942
943 PdoDevice = FdoExtension->RootHubPdo;
944
945 if (PdoDevice)
946 {
947 PdoExtension = PdoDevice->DeviceExtension;
948 Endpoint = PdoExtension->Endpoint;
949
950 if (Endpoint)
951 {
952 USBPORT_InvalidateEndpointHandler(FdoDevice,
953 PdoExtension->Endpoint,
954 INVALIDATE_ENDPOINT_WORKER_THREAD);
955 }
956 }
957
958 return 0;
959 }
960
961 VOID
962 NTAPI
963 USBPORT_RootHubPowerAndChirpAllCcPorts(IN PDEVICE_OBJECT FdoDevice)
964 {
965 PUSBPORT_DEVICE_EXTENSION FdoExtension;
966 PUSBPORT_REGISTRATION_PACKET Packet;
967 USBPORT_ROOT_HUB_DATA RootHubData;
968 ULONG Port;
969 PDEVICE_RELATIONS CompanionControllersList;
970 PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension;
971 PUSBPORT_REGISTRATION_PACKET CompanionPacket;
972 ULONG CompanionPorts;
973 ULONG NumController;
974 PDEVICE_OBJECT * Entry;
975 ULONG NumPorts;
976
977 DPRINT("USBPORT_RootHub_PowerAndChirpAllCcPorts: FdoDevice - %p\n",
978 FdoDevice);
979
980 FdoExtension = FdoDevice->DeviceExtension;
981
982 Packet = &FdoExtension->MiniPortInterface->Packet;
983
984 RtlZeroMemory(&RootHubData, sizeof(RootHubData));
985
986 Packet->RH_GetRootHubData(FdoExtension->MiniPortExt,
987 &RootHubData);
988
989 NumPorts = RootHubData.NumberOfPorts;
990
991 for (Port = 1; Port <= NumPorts; ++Port)
992 {
993 Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port);
994 }
995
996 USBPORT_Wait(FdoDevice, 10);
997
998 CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice,
999 FALSE,
1000 TRUE);
1001
1002 if (CompanionControllersList)
1003 {
1004 Entry = &CompanionControllersList->Objects[0];
1005
1006 for (NumController = 0;
1007 NumController < CompanionControllersList->Count;
1008 NumController++)
1009 {
1010 CompanionPacket = &FdoExtension->MiniPortInterface->Packet;
1011
1012 CompanionFdoExtension = (*Entry)->DeviceExtension;
1013
1014 CompanionPacket->RH_GetRootHubData(CompanionFdoExtension->MiniPortExt,
1015 &RootHubData);
1016
1017 CompanionPorts = RootHubData.NumberOfPorts;
1018
1019 for (Port = 1; Port <= CompanionPorts; ++Port)
1020 {
1021 CompanionPacket->RH_SetFeaturePortPower(CompanionFdoExtension->MiniPortExt,
1022 Port);
1023 }
1024
1025 ++Entry;
1026 }
1027
1028 ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG);
1029 }
1030
1031 USBPORT_Wait(FdoDevice, 100);
1032
1033 for (Port = 1; Port <= NumPorts; ++Port)
1034 {
1035 if (FdoExtension->MiniPortInterface->Version < 200)
1036 {
1037 break;
1038 }
1039
1040 InterlockedIncrement((PLONG)&FdoExtension->ChirpRootPortLock);
1041 Packet->RH_ChirpRootPort(FdoExtension->MiniPortExt, Port);
1042 InterlockedDecrement((PLONG)&FdoExtension->ChirpRootPortLock);
1043 }
1044 }