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