[USBPORT] Avoid more integer overflows.
[reactos.git] / drivers / usb / usbport / device.c
1 /*
2 * PROJECT: ReactOS USB Port Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBPort device functions
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 NTSTATUS
14 NTAPI
15 USBPORT_SendSetupPacket(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
16 IN PDEVICE_OBJECT FdoDevice,
17 IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
18 IN PVOID Buffer,
19 IN ULONG Length,
20 IN OUT PULONG TransferedLen,
21 IN OUT PUSBD_STATUS pUSBDStatus)
22 {
23 PURB Urb;
24 PMDL Mdl;
25 USBD_STATUS USBDStatus;
26 KEVENT Event;
27 NTSTATUS Status;
28
29 DPRINT("USBPORT_SendSetupPacket: DeviceHandle - %p, FdoDevice - %p, SetupPacket - %p, Buffer - %p, Length - %x, TransferedLen - %x, pUSBDStatus - %x\n",
30 DeviceHandle,
31 FdoDevice,
32 SetupPacket,
33 Buffer,
34 Length,
35 TransferedLen,
36 pUSBDStatus);
37
38 KeInitializeEvent(&Event, NotificationEvent, FALSE);
39
40 Urb = ExAllocatePoolWithTag(NonPagedPool,
41 sizeof(struct _URB_CONTROL_TRANSFER),
42 USB_PORT_TAG);
43
44 if (Urb)
45 {
46 InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
47
48 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_TRANSFER));
49
50 RtlCopyMemory(Urb->UrbControlTransfer.SetupPacket,
51 SetupPacket,
52 sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
53
54 Urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_TRANSFER);
55 Urb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
56 Urb->UrbHeader.UsbdDeviceHandle = DeviceHandle;
57 Urb->UrbHeader.UsbdFlags = 0;
58
59 Urb->UrbControlTransfer.PipeHandle = &DeviceHandle->PipeHandle;
60 Urb->UrbControlTransfer.TransferBufferLength = Length;
61 Urb->UrbControlTransfer.TransferBuffer = Buffer;
62 Urb->UrbControlTransfer.TransferBufferMDL = NULL;
63
64 Urb->UrbControlTransfer.TransferFlags = USBD_SHORT_TRANSFER_OK |
65 USBD_TRANSFER_DIRECTION;
66
67 if (SetupPacket->bmRequestType.Dir != BMREQUEST_DEVICE_TO_HOST)
68 {
69 Urb->UrbControlTransfer.TransferFlags &= ~USBD_TRANSFER_DIRECTION_IN;
70 }
71
72 Status = STATUS_SUCCESS;
73
74 if (Length)
75 {
76 Mdl = IoAllocateMdl(Buffer, Length, FALSE, FALSE, NULL);
77
78 Urb->UrbControlTransfer.TransferBufferMDL = Mdl;
79
80 if (Mdl)
81 {
82 Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_MDL;
83 MmBuildMdlForNonPagedPool(Mdl);
84 }
85 else
86 {
87 Status = USBPORT_USBDStatusToNtStatus(NULL,
88 USBD_STATUS_INSUFFICIENT_RESOURCES);
89 }
90 }
91
92 if (NT_SUCCESS(Status))
93 {
94 USBDStatus = USBPORT_AllocateTransfer(FdoDevice,
95 Urb,
96 NULL,
97 NULL,
98 &Event);
99
100 if (USBD_SUCCESS(USBDStatus))
101 {
102 InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
103
104 USBPORT_QueueTransferUrb(Urb);
105
106 KeWaitForSingleObject(&Event,
107 Suspended,
108 KernelMode,
109 FALSE,
110 NULL);
111
112 USBDStatus = Urb->UrbHeader.Status;
113 }
114
115 Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
116
117 if (TransferedLen)
118 *TransferedLen = Urb->UrbControlTransfer.TransferBufferLength;
119
120 if (pUSBDStatus)
121 *pUSBDStatus = USBDStatus;
122 }
123
124 InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
125 ExFreePoolWithTag(Urb, USB_PORT_TAG);
126 }
127 else
128 {
129 if (pUSBDStatus)
130 *pUSBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
131
132 Status = USBPORT_USBDStatusToNtStatus(NULL,
133 USBD_STATUS_INSUFFICIENT_RESOURCES);
134 }
135
136 DPRINT("USBPORT_SendSetupPacket: Status - %x\n", Status);
137 return Status;
138 }
139
140 ULONG
141 NTAPI
142 USBPORT_GetInterfaceLength(IN PUSB_INTERFACE_DESCRIPTOR iDescriptor,
143 IN ULONG_PTR EndDescriptors)
144 {
145 SIZE_T Length;
146 PUSB_ENDPOINT_DESCRIPTOR Descriptor;
147 ULONG ix;
148
149 DPRINT("USBPORT_GetInterfaceLength ... \n");
150
151 Length = iDescriptor->bLength;
152 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)iDescriptor + Length);
153
154 if (iDescriptor->bNumEndpoints)
155 {
156 for (ix = 0; ix < iDescriptor->bNumEndpoints; ix++)
157 {
158 while ((Descriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE) &&
159 (Descriptor->bLength > 0))
160 {
161 Length += Descriptor->bLength;
162 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
163 Descriptor->bLength);
164 }
165
166 Length += Descriptor->bLength;
167 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
168 Descriptor->bLength);
169 }
170 }
171
172 while (((ULONG_PTR)Descriptor < EndDescriptors) &&
173 (Descriptor->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE) &&
174 (Descriptor->bLength > 0))
175 {
176 Length += Descriptor->bLength;
177 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
178 Descriptor->bLength);
179 }
180
181 return Length;
182 }
183
184 PUSB_INTERFACE_DESCRIPTOR
185 NTAPI
186 USBPORT_ParseConfigurationDescriptor(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
187 IN UCHAR InterfaceNumber,
188 IN UCHAR Alternate,
189 OUT PUCHAR OutAlternate)
190 {
191 PUSB_CONFIGURATION_DESCRIPTOR TmpDescriptor;
192 PUSB_INTERFACE_DESCRIPTOR iDescriptor;
193 PUSB_INTERFACE_DESCRIPTOR OutDescriptor = NULL;
194 ULONG_PTR Descriptor = (ULONG_PTR)ConfigDescriptor;
195 ULONG_PTR EndDescriptors;
196 ULONG ix;
197
198 DPRINT("USBPORT_ParseConfigurationDescriptor ... \n");
199
200 if (OutAlternate)
201 *OutAlternate = 0;
202
203 for (TmpDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)ConfigDescriptor + ConfigDescriptor->bLength);
204 TmpDescriptor->bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE && TmpDescriptor->bDescriptorType > 0;
205 TmpDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)TmpDescriptor + TmpDescriptor->bLength))
206 ;
207
208 iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)TmpDescriptor;
209
210 EndDescriptors = (ULONG_PTR)ConfigDescriptor +
211 ConfigDescriptor->wTotalLength;
212
213 while ((Descriptor < EndDescriptors) &&
214 (iDescriptor->bInterfaceNumber != InterfaceNumber))
215 {
216 Descriptor = (ULONG_PTR)iDescriptor +
217 USBPORT_GetInterfaceLength(iDescriptor, EndDescriptors);
218
219 iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Descriptor;
220 }
221
222 ix = 0;
223
224 while (Descriptor < EndDescriptors &&
225 iDescriptor->bInterfaceNumber == InterfaceNumber)
226 {
227 if (iDescriptor->bAlternateSetting == Alternate)
228 OutDescriptor = iDescriptor;
229
230 Descriptor = (ULONG_PTR)iDescriptor +
231 USBPORT_GetInterfaceLength(iDescriptor, EndDescriptors);
232
233 iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Descriptor;
234
235 ++ix;
236 }
237
238 if ((ix > 1) && OutAlternate)
239 *OutAlternate = 1;
240
241 return OutDescriptor;
242 }
243
244 USBD_STATUS
245 NTAPI
246 USBPORT_OpenInterface(IN PURB Urb,
247 IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
248 IN PDEVICE_OBJECT FdoDevice,
249 IN PUSBPORT_CONFIGURATION_HANDLE ConfigHandle,
250 IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
251 IN OUT PUSBPORT_INTERFACE_HANDLE *iHandle,
252 IN BOOLEAN IsSetInterface)
253 {
254 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
255 PUSBPORT_INTERFACE_HANDLE InterfaceHandle = NULL;
256 PUSBPORT_PIPE_HANDLE PipeHandle;
257 PUSB_ENDPOINT_DESCRIPTOR Descriptor;
258 PUSBD_PIPE_INFORMATION PipeInfo;
259 ULONG NumEndpoints;
260 SIZE_T Length;
261 SIZE_T HandleLength;
262 BOOLEAN IsAllocated = FALSE;
263 USHORT MaxPacketSize;
264 USHORT wMaxPacketSize;
265 ULONG ix;
266 USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
267 NTSTATUS Status;
268
269 DPRINT("USBPORT_OpenInterface: ...\n");
270
271 InterfaceDescriptor = USBPORT_ParseConfigurationDescriptor(ConfigHandle->ConfigurationDescriptor,
272 InterfaceInfo->InterfaceNumber,
273 InterfaceInfo->AlternateSetting,
274 &InterfaceInfo->AlternateSetting);
275
276 NumEndpoints = InterfaceDescriptor->bNumEndpoints;
277
278 Length = FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) +
279 NumEndpoints * sizeof(USBD_PIPE_INFORMATION);
280
281 if (InterfaceInfo->AlternateSetting && IsSetInterface)
282 {
283 DPRINT1("USBPORT_OpenInterface: InterfaceInfo->AlternateSetting && IsSetInterface !\n");
284 }
285
286 if (*iHandle)
287 {
288 InterfaceHandle = *iHandle;
289 }
290 else
291 {
292 HandleLength = FIELD_OFFSET(USBPORT_INTERFACE_HANDLE, PipeHandle) +
293 NumEndpoints * sizeof(USBPORT_PIPE_HANDLE);
294
295 InterfaceHandle = ExAllocatePoolWithTag(NonPagedPool,
296 HandleLength,
297 USB_PORT_TAG);
298
299 if (!InterfaceHandle)
300 {
301 USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
302 goto Exit;
303 }
304
305 RtlZeroMemory(InterfaceHandle, HandleLength);
306
307 for (ix = 0; ix < NumEndpoints; ++ix)
308 {
309 PipeHandle = &InterfaceHandle->PipeHandle[ix];
310
311 PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
312 PipeHandle->Endpoint = NULL;
313 }
314
315 IsAllocated = TRUE;
316 }
317
318 InterfaceHandle->AlternateSetting = InterfaceInfo->AlternateSetting;
319
320 RtlCopyMemory(&InterfaceHandle->InterfaceDescriptor,
321 InterfaceDescriptor,
322 sizeof(USB_INTERFACE_DESCRIPTOR));
323
324 InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
325 InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
326 InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol;
327 InterfaceInfo->Reserved = 0;
328 InterfaceInfo->NumberOfPipes = InterfaceDescriptor->bNumEndpoints;
329
330 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor +
331 InterfaceDescriptor->bLength);
332
333 for (ix = 0; ix < NumEndpoints; ++ix)
334 {
335 PipeHandle = &InterfaceHandle->PipeHandle[ix];
336
337 while (Descriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE)
338 {
339 if (Descriptor->bLength == 0)
340 {
341 break;
342 }
343 else
344 {
345 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
346 Descriptor->bLength);
347 }
348 }
349
350 if (InterfaceInfo->Pipes[ix].PipeFlags & USBD_PF_CHANGE_MAX_PACKET)
351 {
352 Descriptor->wMaxPacketSize = InterfaceInfo->Pipes[ix].MaximumPacketSize;
353 }
354
355 RtlCopyMemory(&PipeHandle->EndpointDescriptor,
356 Descriptor,
357 sizeof(USB_ENDPOINT_DESCRIPTOR));
358
359 PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
360 PipeHandle->PipeFlags = InterfaceInfo->Pipes[ix].PipeFlags;
361 PipeHandle->Endpoint = NULL;
362
363 wMaxPacketSize = Descriptor->wMaxPacketSize;
364
365 /* USB 2.0 Specification, 5.9 High-Speed, High Bandwidth Endpoints */
366 MaxPacketSize = (wMaxPacketSize & 0x7FF) * (((wMaxPacketSize >> 11) & 3) + 1);
367
368 InterfaceInfo->Pipes[ix].EndpointAddress = Descriptor->bEndpointAddress;
369 InterfaceInfo->Pipes[ix].PipeType = Descriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK;
370 InterfaceInfo->Pipes[ix].MaximumPacketSize = MaxPacketSize;
371 InterfaceInfo->Pipes[ix].PipeHandle = (USBD_PIPE_HANDLE)-1;
372 InterfaceInfo->Pipes[ix].Interval = Descriptor->bInterval;
373
374 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
375 Descriptor->bLength);
376 }
377
378 if (USBD_SUCCESS(USBDStatus))
379 {
380 for (ix = 0; ix < NumEndpoints; ++ix)
381 {
382 PipeInfo = &InterfaceInfo->Pipes[ix];
383 PipeHandle = &InterfaceHandle->PipeHandle[ix];
384
385 Status = USBPORT_OpenPipe(FdoDevice,
386 DeviceHandle,
387 PipeHandle,
388 &USBDStatus);
389
390 if (!NT_SUCCESS(Status))
391 break;
392
393 PipeInfo->PipeHandle = PipeHandle;
394 }
395
396 if (NumEndpoints)
397 {
398 USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
399 }
400 }
401
402 Exit:
403
404 if (USBD_SUCCESS(USBDStatus))
405 {
406 InterfaceInfo->InterfaceHandle = InterfaceHandle;
407 *iHandle = InterfaceHandle;
408 InterfaceInfo->Length = Length;
409 }
410 else
411 {
412 if (InterfaceHandle)
413 {
414 if (NumEndpoints)
415 {
416 DPRINT1("USBPORT_OpenInterface: USBDStatus - %lx\n", USBDStatus);
417 }
418
419 if (IsAllocated)
420 ExFreePoolWithTag(InterfaceHandle, USB_PORT_TAG);
421 }
422 }
423
424 return USBDStatus;
425 }
426
427 VOID
428 NTAPI
429 USBPORT_CloseConfiguration(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
430 IN PDEVICE_OBJECT FdoDevice)
431 {
432 PUSBPORT_CONFIGURATION_HANDLE ConfigHandle;
433 PLIST_ENTRY iHandleList;
434 PUSBPORT_INTERFACE_HANDLE iHandle;
435 ULONG NumEndpoints;
436 PUSBPORT_PIPE_HANDLE PipeHandle;
437
438 DPRINT("USBPORT_CloseConfiguration: ... \n");
439
440 ConfigHandle = DeviceHandle->ConfigHandle;
441
442 if (ConfigHandle)
443 {
444 iHandleList = &ConfigHandle->InterfaceHandleList;
445
446 while (!IsListEmpty(iHandleList))
447 {
448 iHandle = CONTAINING_RECORD(iHandleList->Flink,
449 USBPORT_INTERFACE_HANDLE,
450 InterfaceLink);
451
452 DPRINT("USBPORT_CloseConfiguration: iHandle - %p\n", iHandle);
453
454 RemoveHeadList(iHandleList);
455
456 NumEndpoints = iHandle->InterfaceDescriptor.bNumEndpoints;
457
458 PipeHandle = &iHandle->PipeHandle[0];
459
460 while (NumEndpoints > 0)
461 {
462 USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
463 PipeHandle += 1;
464 --NumEndpoints;
465 }
466
467 ExFreePoolWithTag(iHandle, USB_PORT_TAG);
468 }
469
470 ExFreePoolWithTag(ConfigHandle, USB_PORT_TAG);
471 DeviceHandle->ConfigHandle = NULL;
472 }
473 }
474
475 NTSTATUS
476 NTAPI
477 USBPORT_InitInterfaceInfo(IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
478 IN PUSBPORT_CONFIGURATION_HANDLE ConfigHandle)
479 {
480 PUSB_INTERFACE_DESCRIPTOR Descriptor;
481 PUSBD_PIPE_INFORMATION Pipe;
482 USHORT Length;
483 ULONG PipeFlags;
484 ULONG NumberOfPipes;
485 USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
486
487 DPRINT("USBPORT_InitInterfaceInfo: InterfaceInfo - %p, ConfigHandle - %p\n",
488 InterfaceInfo,
489 ConfigHandle);
490
491 Descriptor = USBPORT_ParseConfigurationDescriptor(ConfigHandle->ConfigurationDescriptor,
492 InterfaceInfo->InterfaceNumber,
493 InterfaceInfo->AlternateSetting,
494 &InterfaceInfo->AlternateSetting);
495
496 Length = sizeof(USBD_INTERFACE_INFORMATION) +
497 sizeof(USBD_PIPE_INFORMATION);
498
499 if (Descriptor)
500 {
501 NumberOfPipes = Descriptor->bNumEndpoints;
502
503 Length = FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) +
504 NumberOfPipes * sizeof(USBD_PIPE_INFORMATION);
505
506 if (InterfaceInfo->Length >= Length)
507 {
508 InterfaceInfo->Class = 0;
509 InterfaceInfo->SubClass = 0;
510 InterfaceInfo->Protocol = 0;
511 InterfaceInfo->Reserved = 0;
512 InterfaceInfo->InterfaceHandle = 0;
513 InterfaceInfo->NumberOfPipes = NumberOfPipes;
514
515 Pipe = InterfaceInfo->Pipes;
516
517 while (NumberOfPipes > 0)
518 {
519 Pipe->EndpointAddress = 0;
520 Pipe->Interval = 0;
521 Pipe->PipeType = 0;
522 Pipe->PipeHandle = 0;
523
524 PipeFlags = Pipe->PipeFlags;
525
526 if (PipeFlags & ~USBD_PF_VALID_MASK)
527 USBDStatus = USBD_STATUS_INVALID_PIPE_FLAGS;
528
529 if (!(PipeFlags & USBD_PF_CHANGE_MAX_PACKET))
530 Pipe->MaximumPacketSize = 0;
531
532 Pipe += 1;
533 --NumberOfPipes;
534 }
535 }
536 else
537 {
538 USBDStatus = USBD_STATUS_BUFFER_TOO_SMALL;
539 }
540 }
541 else
542 {
543 USBDStatus = USBD_STATUS_INTERFACE_NOT_FOUND;
544 }
545
546 InterfaceInfo->Length = Length;
547 return USBDStatus;
548 }
549
550 NTSTATUS
551 NTAPI
552 USBPORT_HandleSelectConfiguration(IN PDEVICE_OBJECT FdoDevice,
553 IN PIRP Irp,
554 IN PURB Urb)
555 {
556 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
557 PUSBPORT_DEVICE_HANDLE DeviceHandle;
558 PUSBPORT_CONFIGURATION_HANDLE ConfigHandle = NULL;
559 PUSBD_INTERFACE_INFORMATION InterfaceInfo;
560 PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
561 ULONG iNumber;
562 ULONG ix;
563 USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
564 NTSTATUS Status;
565 USBD_STATUS USBDStatus;
566 PUSBPORT_DEVICE_EXTENSION FdoExtension;
567
568 DPRINT("USBPORT_HandleSelectConfiguration: ConfigDescriptor %p\n",
569 Urb->UrbSelectConfiguration.ConfigurationDescriptor);
570
571 FdoExtension = FdoDevice->DeviceExtension;
572
573 KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
574 Executive,
575 KernelMode,
576 FALSE,
577 NULL);
578
579 DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
580 ConfigDescriptor = Urb->UrbSelectConfiguration.ConfigurationDescriptor;
581
582 if (!ConfigDescriptor)
583 {
584 DPRINT("USBPORT_HandleSelectConfiguration: ConfigDescriptor == NULL\n");
585
586 RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
587
588 SetupPacket.bmRequestType.B = 0;
589 SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
590 SetupPacket.wValue.W = 0;
591 SetupPacket.wIndex.W = 0;
592 SetupPacket.wLength = 0;
593
594 USBPORT_SendSetupPacket(DeviceHandle,
595 FdoDevice,
596 &SetupPacket,
597 NULL,
598 0,
599 NULL,
600 NULL);
601
602 Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
603 goto Exit;
604 }
605
606 USBPORT_DumpingConfiguration(ConfigDescriptor);
607
608 InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
609
610 iNumber = 0;
611
612 do
613 {
614 ++iNumber;
615 InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)
616 ((ULONG_PTR)InterfaceInfo +
617 InterfaceInfo->Length);
618 }
619 while ((ULONG_PTR)InterfaceInfo < (ULONG_PTR)Urb + Urb->UrbHeader.Length);
620
621 if ((iNumber <= 0) || (iNumber != ConfigDescriptor->bNumInterfaces))
622 {
623 Status = USBPORT_USBDStatusToNtStatus(Urb,
624 USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR);
625 goto Exit;
626 }
627
628 ConfigHandle = ExAllocatePoolWithTag(NonPagedPool,
629 ConfigDescriptor->wTotalLength + sizeof(USBPORT_CONFIGURATION_HANDLE),
630 USB_PORT_TAG);
631
632 if (!ConfigHandle)
633 {
634 Status = USBPORT_USBDStatusToNtStatus(Urb,
635 USBD_STATUS_INSUFFICIENT_RESOURCES);
636 goto Exit;
637 }
638
639 RtlZeroMemory(ConfigHandle,
640 ConfigDescriptor->wTotalLength + sizeof(USBPORT_CONFIGURATION_HANDLE));
641
642 InitializeListHead(&ConfigHandle->InterfaceHandleList);
643
644 ConfigHandle->ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)(ConfigHandle + 1);
645
646 RtlCopyMemory(ConfigHandle->ConfigurationDescriptor,
647 ConfigDescriptor,
648 ConfigDescriptor->wTotalLength);
649
650 RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
651
652 SetupPacket.bmRequestType.B = 0;
653 SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
654 SetupPacket.wValue.W = ConfigDescriptor->bConfigurationValue;
655 SetupPacket.wIndex.W = 0;
656 SetupPacket.wLength = 0;
657
658 USBPORT_SendSetupPacket(DeviceHandle,
659 FdoDevice,
660 &SetupPacket,
661 NULL,
662 0,
663 NULL,
664 &USBDStatus);
665
666 if (USBD_ERROR(USBDStatus))
667 {
668 Status = USBPORT_USBDStatusToNtStatus(Urb,
669 USBD_STATUS_SET_CONFIG_FAILED);
670 goto Exit;
671 }
672
673 if (iNumber <= 0)
674 {
675 Status = USBPORT_USBDStatusToNtStatus(Urb,
676 USBD_STATUS_SUCCESS);
677
678 goto Exit;
679 }
680
681 InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
682
683 for (ix = 0; ix < iNumber; ++ix)
684 {
685 USBDStatus = USBPORT_InitInterfaceInfo(InterfaceInfo,
686 ConfigHandle);
687
688 InterfaceHandle = NULL;
689
690 if (USBD_SUCCESS(USBDStatus))
691 {
692 USBDStatus = USBPORT_OpenInterface(Urb,
693 DeviceHandle,
694 FdoDevice,
695 ConfigHandle,
696 InterfaceInfo,
697 &InterfaceHandle,
698 TRUE);
699 }
700
701 if (InterfaceHandle)
702 {
703 InsertTailList(&ConfigHandle->InterfaceHandleList,
704 &InterfaceHandle->InterfaceLink);
705 }
706
707 if (USBD_ERROR(USBDStatus))
708 break;
709
710 InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)
711 ((ULONG_PTR)InterfaceInfo +
712 InterfaceInfo->Length);
713 }
714
715 if (ix >= iNumber)
716 {
717 Status = USBPORT_USBDStatusToNtStatus(Urb,
718 USBD_STATUS_SUCCESS);
719 }
720 else
721 {
722 Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
723 }
724
725 Exit:
726
727 if (NT_SUCCESS(Status))
728 {
729 Urb->UrbSelectConfiguration.ConfigurationHandle = ConfigHandle;
730 DeviceHandle->ConfigHandle = ConfigHandle;
731 }
732 else
733 {
734 DPRINT1("USBPORT_HandleSelectConfiguration: Status %x\n", Status);
735 }
736
737 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
738 LOW_REALTIME_PRIORITY,
739 1,
740 FALSE);
741
742 return Status;
743 }
744
745 VOID
746 NTAPI
747 USBPORT_AddDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
748 IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
749 {
750 PUSBPORT_DEVICE_EXTENSION FdoExtension;
751
752 DPRINT("USBPORT_AddDeviceHandle: ... \n");
753
754 FdoExtension = FdoDevice->DeviceExtension;
755
756 InsertTailList(&FdoExtension->DeviceHandleList,
757 &DeviceHandle->DeviceHandleLink);
758 }
759
760 VOID
761 NTAPI
762 USBPORT_RemoveDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
763 IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
764 {
765 PUSBPORT_DEVICE_EXTENSION FdoExtension;
766 KIRQL OldIrql;
767
768 DPRINT("USBPORT_RemoveDeviceHandle \n");
769
770 FdoExtension = FdoDevice->DeviceExtension;
771
772 KeAcquireSpinLock(&FdoExtension->DeviceHandleSpinLock, &OldIrql);
773 RemoveEntryList(&DeviceHandle->DeviceHandleLink);
774 KeReleaseSpinLock(&FdoExtension->DeviceHandleSpinLock, OldIrql);
775 }
776
777 BOOLEAN
778 NTAPI
779 USBPORT_ValidateDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
780 IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
781 {
782 PUSBPORT_DEVICE_EXTENSION FdoExtension;
783 KIRQL OldIrql;
784 PLIST_ENTRY HandleList;
785 PUSBPORT_DEVICE_HANDLE CurrentHandle;
786 BOOLEAN Result = FALSE;
787
788 //DPRINT("USBPORT_ValidateDeviceHandle: DeviceHandle - %p\n", DeviceHandle \n");
789
790 FdoExtension = FdoDevice->DeviceExtension;
791
792 KeAcquireSpinLock(&FdoExtension->DeviceHandleSpinLock, &OldIrql);
793 if (DeviceHandle)
794 {
795 HandleList = FdoExtension->DeviceHandleList.Flink;
796
797 while (HandleList != &FdoExtension->DeviceHandleList)
798 {
799 CurrentHandle = CONTAINING_RECORD(HandleList,
800 USBPORT_DEVICE_HANDLE,
801 DeviceHandleLink);
802
803 if (CurrentHandle == DeviceHandle)
804 {
805 Result = TRUE;
806 break;
807 }
808
809 HandleList = HandleList->Flink;
810 }
811 }
812 KeReleaseSpinLock(&FdoExtension->DeviceHandleSpinLock, OldIrql);
813
814 return Result;
815 }
816
817 BOOLEAN
818 NTAPI
819 USBPORT_DeviceHasTransfers(IN PDEVICE_OBJECT FdoDevice,
820 IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
821 {
822 PLIST_ENTRY PipeHandleList;
823 PUSBPORT_PIPE_HANDLE PipeHandle;
824
825 DPRINT("USBPORT_DeviceHasTransfers: ... \n");
826
827 PipeHandleList = DeviceHandle->PipeHandleList.Flink;
828
829 while (PipeHandleList != &DeviceHandle->PipeHandleList)
830 {
831 PipeHandle = CONTAINING_RECORD(PipeHandleList,
832 USBPORT_PIPE_HANDLE,
833 PipeLink);
834
835 PipeHandleList = PipeHandleList->Flink;
836
837 if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE) &&
838 USBPORT_EndpointHasQueuedTransfers(FdoDevice, PipeHandle->Endpoint, NULL))
839 {
840 return TRUE;
841 }
842 }
843
844 return FALSE;
845 }
846
847 VOID
848 NTAPI
849 USBPORT_AbortTransfers(IN PDEVICE_OBJECT FdoDevice,
850 IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
851 {
852 PLIST_ENTRY HandleList;
853 PUSBPORT_PIPE_HANDLE PipeHandle;
854 BOOLEAN Result;
855
856 DPRINT("USBPORT_AbortAllTransfers: ... \n");
857
858 HandleList = DeviceHandle->PipeHandleList.Flink;
859
860 while (HandleList != &DeviceHandle->PipeHandleList)
861 {
862 PipeHandle = CONTAINING_RECORD(HandleList,
863 USBPORT_PIPE_HANDLE,
864 PipeLink);
865
866 HandleList = HandleList->Flink;
867
868 if (!(PipeHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB))
869 {
870 PipeHandle->Endpoint->Flags |= ENDPOINT_FLAG_ABORTING;
871
872 USBPORT_AbortEndpoint(FdoDevice, PipeHandle->Endpoint, NULL);
873 USBPORT_FlushMapTransfers(FdoDevice);
874 }
875 }
876
877 while (TRUE)
878 {
879 Result = USBPORT_DeviceHasTransfers(FdoDevice, DeviceHandle);
880
881 if (!Result)
882 break;
883
884 USBPORT_Wait(FdoDevice, 100);
885 }
886 }
887
888 NTSTATUS
889 NTAPI
890 USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
891 IN PDEVICE_OBJECT FdoDevice,
892 IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
893 IN USHORT PortStatus,
894 IN USHORT Port)
895 {
896 PUSBPORT_DEVICE_HANDLE DeviceHandle;
897 PUSBPORT_PIPE_HANDLE PipeHandle;
898 BOOL IsOpenedPipe;
899 PVOID DeviceDescriptor;
900 USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
901 SIZE_T TransferedLen;
902 SIZE_T DescriptorMinSize;
903 UCHAR MaxPacketSize;
904 PUSBPORT_DEVICE_EXTENSION FdoExtension;
905
906 NTSTATUS Status;
907
908 DPRINT("USBPORT_CreateDevice: PortStatus - %p, Port - %x\n",
909 PortStatus,
910 Port);
911
912 FdoExtension = FdoDevice->DeviceExtension;
913
914 KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
915 Executive,
916 KernelMode,
917 FALSE,
918 NULL);
919
920 if (!USBPORT_ValidateDeviceHandle(FdoDevice, HubDeviceHandle))
921 {
922 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
923 LOW_REALTIME_PRIORITY,
924 1,
925 FALSE);
926
927 DPRINT1("USBPORT_CreateDevice: Not valid hub DeviceHandle\n");
928 return STATUS_DEVICE_NOT_CONNECTED;
929 }
930
931 if (FdoExtension->MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2 &&
932 !(PortStatus & USB_PORT_STATUS_HIGH_SPEED))
933 {
934 DPRINT1("USBPORT_CreateDevice: USB1 device connected to USB2 port. FIXME: Transaction Translator.\n");
935 DbgBreakPoint();
936 }
937
938 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
939 LOW_REALTIME_PRIORITY,
940 1,
941 FALSE);
942
943 DeviceHandle = ExAllocatePoolWithTag(NonPagedPool,
944 sizeof(USBPORT_DEVICE_HANDLE),
945 USB_PORT_TAG);
946
947 if (!DeviceHandle)
948 {
949 DPRINT1("USBPORT_CreateDevice: Not allocated DeviceHandle\n");
950 return STATUS_INSUFFICIENT_RESOURCES;
951 }
952
953 RtlZeroMemory(DeviceHandle, sizeof(USBPORT_DEVICE_HANDLE));
954
955 *pUsbdDeviceHandle = NULL;
956
957 DeviceHandle->PortNumber = Port;
958 DeviceHandle->HubDeviceHandle = HubDeviceHandle;
959
960 if (PortStatus & USB_PORT_STATUS_LOW_SPEED)
961 {
962 DeviceHandle->DeviceSpeed = UsbLowSpeed;
963 }
964 else if (PortStatus & USB_PORT_STATUS_HIGH_SPEED)
965 {
966 DeviceHandle->DeviceSpeed = UsbHighSpeed;
967 }
968 else
969 {
970 DeviceHandle->DeviceSpeed = UsbFullSpeed;
971 }
972
973 KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
974 Executive,
975 KernelMode,
976 FALSE,
977 NULL);
978
979 PipeHandle = &DeviceHandle->PipeHandle;
980
981 PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
982
983 PipeHandle->EndpointDescriptor.bLength = sizeof(PipeHandle->EndpointDescriptor);
984 PipeHandle->EndpointDescriptor.bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
985
986 if (DeviceHandle->DeviceSpeed == UsbLowSpeed)
987 {
988 PipeHandle->EndpointDescriptor.wMaxPacketSize = 8;
989 }
990 else
991 {
992 PipeHandle->EndpointDescriptor.wMaxPacketSize = USB_DEFAULT_MAX_PACKET;
993 }
994
995 InitializeListHead(&DeviceHandle->PipeHandleList);
996
997 Status = USBPORT_OpenPipe(FdoDevice,
998 DeviceHandle,
999 PipeHandle,
1000 NULL);
1001
1002 IsOpenedPipe = NT_SUCCESS(Status);
1003
1004 if (NT_ERROR(Status))
1005 {
1006 DPRINT1("USBPORT_CreateDevice: USBPORT_OpenPipe return - %lx\n", Status);
1007
1008 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1009 LOW_REALTIME_PRIORITY,
1010 1,
1011 FALSE);
1012
1013 ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1014
1015 return Status;
1016 }
1017
1018 DeviceDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1019 USB_DEFAULT_MAX_PACKET,
1020 USB_PORT_TAG);
1021
1022 if (!DeviceDescriptor)
1023 {
1024 DPRINT1("USBPORT_CreateDevice: Not allocated DeviceDescriptor\n");
1025 goto ErrorExit;
1026 }
1027
1028 RtlZeroMemory(DeviceDescriptor, USB_DEFAULT_MAX_PACKET);
1029 RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1030
1031 SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1032 SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1033 SetupPacket.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
1034 SetupPacket.wLength = USB_DEFAULT_MAX_PACKET;
1035
1036 TransferedLen = 0;
1037
1038 Status = USBPORT_SendSetupPacket(DeviceHandle,
1039 FdoDevice,
1040 &SetupPacket,
1041 DeviceDescriptor,
1042 USB_DEFAULT_MAX_PACKET,
1043 &TransferedLen,
1044 NULL);
1045
1046 RtlCopyMemory(&DeviceHandle->DeviceDescriptor,
1047 DeviceDescriptor,
1048 sizeof(USB_DEVICE_DESCRIPTOR));
1049
1050 ExFreePoolWithTag(DeviceDescriptor, USB_PORT_TAG);
1051
1052 DescriptorMinSize = RTL_SIZEOF_THROUGH_FIELD(USB_DEVICE_DESCRIPTOR,
1053 bMaxPacketSize0);
1054
1055 if ((TransferedLen == DescriptorMinSize) && !NT_SUCCESS(Status))
1056 {
1057 Status = STATUS_SUCCESS;
1058 }
1059
1060 if (NT_SUCCESS(Status) && (TransferedLen >= DescriptorMinSize))
1061 {
1062 if ((DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR)) &&
1063 (DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE))
1064 {
1065 MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1066
1067 if (MaxPacketSize == 8 ||
1068 MaxPacketSize == 16 ||
1069 MaxPacketSize == 32 ||
1070 MaxPacketSize == 64)
1071 {
1072 USBPORT_AddDeviceHandle(FdoDevice, DeviceHandle);
1073
1074 *pUsbdDeviceHandle = DeviceHandle;
1075
1076 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1077 LOW_REALTIME_PRIORITY,
1078 1,
1079 FALSE);
1080
1081 return Status;
1082 }
1083 }
1084 }
1085
1086 DPRINT1("USBPORT_CreateDevice: ERROR!!! TransferedLen - %x, Status - %lx\n",
1087 TransferedLen,
1088 Status);
1089
1090 ErrorExit:
1091
1092 // FIXME: if Transaction Translator
1093
1094 Status = STATUS_DEVICE_DATA_ERROR;
1095
1096 if (IsOpenedPipe)
1097 {
1098 USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
1099 }
1100
1101 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1102 LOW_REALTIME_PRIORITY,
1103 1,
1104 FALSE);
1105
1106 ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1107
1108 return Status;
1109 }
1110
1111 ULONG
1112 NTAPI
1113 USBPORT_AllocateUsbAddress(IN PDEVICE_OBJECT FdoDevice)
1114 {
1115 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1116 ULONG BitMapIdx;
1117 ULONG BitNumber;
1118 ULONG ix;
1119
1120 DPRINT("USBPORT_AllocateUsbAddress \n");
1121
1122 FdoExtension = FdoDevice->DeviceExtension;
1123
1124 for (ix = 0; ix < 4; ++ix)
1125 {
1126 BitMapIdx = 1;
1127
1128 for (BitNumber = 0; BitNumber < 32; ++BitNumber)
1129 {
1130 if (!(FdoExtension->UsbAddressBitMap[ix] & BitMapIdx))
1131 {
1132 FdoExtension->UsbAddressBitMap[ix] |= BitMapIdx;
1133 return 32 * ix + BitNumber;
1134 }
1135
1136 BitMapIdx <<= 2;
1137 }
1138 }
1139
1140 return 0;
1141 }
1142
1143 VOID
1144 NTAPI
1145 USBPORT_FreeUsbAddress(IN PDEVICE_OBJECT FdoDevice,
1146 IN USHORT DeviceAddress)
1147 {
1148 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1149 ULONG ix;
1150 ULONG BitMapIdx;
1151 ULONG BitNumber;
1152 USHORT CurrentAddress;
1153
1154 DPRINT("USBPORT_FreeUsbAddress: DeviceAddress - %x\n", DeviceAddress);
1155
1156 FdoExtension = FdoDevice->DeviceExtension;
1157
1158 for (ix = 0; ix < 4; ++ix)
1159 {
1160 BitMapIdx = 1;
1161 CurrentAddress = 32 * ix;
1162
1163 for (BitNumber = 0; BitNumber < 32; ++BitNumber)
1164 {
1165 if (CurrentAddress == DeviceAddress)
1166 {
1167 FdoExtension->UsbAddressBitMap[ix] &= ~BitMapIdx;
1168 return;
1169 }
1170
1171 BitMapIdx <<= 2;
1172 CurrentAddress++;
1173 }
1174 }
1175 }
1176
1177 NTSTATUS
1178 NTAPI
1179 USBPORT_InitializeDevice(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
1180 IN PDEVICE_OBJECT FdoDevice)
1181 {
1182 PUSBPORT_ENDPOINT Endpoint;
1183 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1184 ULONG TransferedLen;
1185 USHORT DeviceAddress = 0;
1186 UCHAR MaxPacketSize;
1187 NTSTATUS Status;
1188 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1189
1190 DPRINT("USBPORT_InitializeDevice: ... \n");
1191
1192 ASSERT(DeviceHandle != NULL);
1193
1194 FdoExtension = FdoDevice->DeviceExtension;
1195
1196 KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1197 Executive,
1198 KernelMode,
1199 FALSE,
1200 NULL);
1201
1202 DeviceAddress = USBPORT_AllocateUsbAddress(FdoDevice);
1203 ASSERT(DeviceHandle->DeviceAddress == USB_DEFAULT_DEVICE_ADDRESS);
1204
1205 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1206
1207 CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
1208 CtrlSetup.wValue.W = DeviceAddress;
1209
1210 Status = USBPORT_SendSetupPacket(DeviceHandle,
1211 FdoDevice,
1212 &CtrlSetup,
1213 NULL,
1214 0,
1215 NULL,
1216 NULL);
1217
1218 DPRINT("USBPORT_InitializeDevice: DeviceAddress - %x. SendSetupPacket Status - %x\n",
1219 DeviceAddress,
1220 Status);
1221
1222 if (!NT_SUCCESS(Status))
1223 goto ExitError;
1224
1225 DeviceHandle->DeviceAddress = DeviceAddress;
1226 Endpoint = DeviceHandle->PipeHandle.Endpoint;
1227
1228 Endpoint->EndpointProperties.TotalMaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1229 Endpoint->EndpointProperties.DeviceAddress = DeviceAddress;
1230
1231 Status = USBPORT_ReopenPipe(FdoDevice, Endpoint);
1232
1233 if (!NT_SUCCESS(Status))
1234 goto ExitError;
1235
1236 USBPORT_Wait(FdoDevice, 10);
1237
1238 RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1239
1240 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1241 CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
1242 CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
1243 CtrlSetup.bmRequestType.B = 0x80;
1244
1245 Status = USBPORT_SendSetupPacket(DeviceHandle,
1246 FdoDevice,
1247 &CtrlSetup,
1248 &DeviceHandle->DeviceDescriptor,
1249 sizeof(USB_DEVICE_DESCRIPTOR),
1250 &TransferedLen,
1251 NULL);
1252
1253 if (NT_SUCCESS(Status))
1254 {
1255 ASSERT(TransferedLen == sizeof(USB_DEVICE_DESCRIPTOR));
1256 ASSERT(DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1257 ASSERT(DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE);
1258
1259 MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1260
1261 ASSERT((MaxPacketSize == 8) ||
1262 (MaxPacketSize == 16) ||
1263 (MaxPacketSize == 32) ||
1264 (MaxPacketSize == 64));
1265 }
1266 else
1267 {
1268 ExitError:
1269 DPRINT1("USBPORT_InitializeDevice: ExitError. Status - %x\n", Status);
1270 }
1271
1272 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1273 LOW_REALTIME_PRIORITY,
1274 1,
1275 FALSE);
1276
1277 return Status;
1278 }
1279
1280 NTSTATUS
1281 NTAPI
1282 USBPORT_GetUsbDescriptor(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
1283 IN PDEVICE_OBJECT FdoDevice,
1284 IN UCHAR Type,
1285 IN PUCHAR ConfigDesc,
1286 IN PULONG ConfigDescSize)
1287 {
1288 USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
1289
1290 DPRINT("USBPORT_GetUsbDescriptor: Type - %x\n");
1291
1292 RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1293
1294 SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1295 SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1296 SetupPacket.wValue.HiByte = Type;
1297 SetupPacket.wLength = (USHORT)*ConfigDescSize;
1298
1299 return USBPORT_SendSetupPacket(DeviceHandle,
1300 FdoDevice,
1301 &SetupPacket,
1302 ConfigDesc,
1303 *ConfigDescSize,
1304 ConfigDescSize,
1305 NULL);
1306 }
1307
1308 PUSBPORT_INTERFACE_HANDLE
1309 NTAPI
1310 USBPORT_GetInterfaceHandle(IN PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle,
1311 IN UCHAR InterfaceNumber)
1312 {
1313 PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1314 PLIST_ENTRY iHandleList;
1315 UCHAR InterfaceNum;
1316
1317 DPRINT("USBPORT_GetInterfaceHandle: ConfigurationHandle - %p, InterfaceNumber - %p\n",
1318 ConfigurationHandle,
1319 InterfaceNumber);
1320
1321 iHandleList = ConfigurationHandle->InterfaceHandleList.Flink;
1322
1323 while (iHandleList &&
1324 (iHandleList != &ConfigurationHandle->InterfaceHandleList))
1325 {
1326 InterfaceHandle = CONTAINING_RECORD(iHandleList,
1327 USBPORT_INTERFACE_HANDLE,
1328 InterfaceLink);
1329
1330 InterfaceNum = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
1331
1332 if (InterfaceNum == InterfaceNumber)
1333 return InterfaceHandle;
1334
1335 iHandleList = InterfaceHandle->InterfaceLink.Flink;
1336 }
1337
1338 return NULL;
1339 }
1340
1341 NTSTATUS
1342 NTAPI
1343 USBPORT_HandleSelectInterface(IN PDEVICE_OBJECT FdoDevice,
1344 IN PIRP Irp,
1345 IN PURB Urb)
1346 {
1347 PUSBPORT_DEVICE_HANDLE DeviceHandle;
1348 PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle;
1349 PUSBD_INTERFACE_INFORMATION Interface;
1350 PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1351 PUSBPORT_INTERFACE_HANDLE iHandle;
1352 PUSBPORT_PIPE_HANDLE PipeHandle;
1353 USBD_STATUS USBDStatus;
1354 USHORT Length;
1355 ULONG ix;
1356 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1357
1358 DPRINT("USBPORT_HandleSelectInterface: ... \n");
1359
1360 FdoExtension = FdoDevice->DeviceExtension;
1361
1362 KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1363 Executive,
1364 KernelMode,
1365 FALSE,
1366 NULL);
1367
1368 ConfigurationHandle = Urb->UrbSelectInterface.ConfigurationHandle;
1369
1370 Interface = &Urb->UrbSelectInterface.Interface;
1371
1372 Length = Interface->Length + sizeof(USBD_PIPE_INFORMATION);
1373 Urb->UrbHeader.Length = Length;
1374
1375 USBDStatus = USBPORT_InitInterfaceInfo(Interface, ConfigurationHandle);
1376
1377 if (USBDStatus)
1378 {
1379 Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
1380 return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
1381 }
1382
1383 DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
1384
1385 InterfaceHandle = USBPORT_GetInterfaceHandle(ConfigurationHandle,
1386 Interface->InterfaceNumber);
1387
1388 if (InterfaceHandle)
1389 {
1390 RemoveEntryList(&InterfaceHandle->InterfaceLink);
1391
1392 if (InterfaceHandle->InterfaceDescriptor.bNumEndpoints)
1393 {
1394 PipeHandle = &InterfaceHandle->PipeHandle[0];
1395
1396 for (ix = 0;
1397 ix < InterfaceHandle->InterfaceDescriptor.bNumEndpoints;
1398 ix++)
1399 {
1400 USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
1401 PipeHandle += 1;
1402 }
1403 }
1404 }
1405
1406 iHandle = 0;
1407
1408 USBDStatus = USBPORT_OpenInterface(Urb,
1409 DeviceHandle,
1410 FdoDevice,
1411 ConfigurationHandle,
1412 Interface,
1413 &iHandle,
1414 1);
1415
1416 if (USBDStatus)
1417 {
1418 Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
1419 }
1420 else
1421 {
1422 if (InterfaceHandle)
1423 ExFreePoolWithTag(InterfaceHandle, USB_PORT_TAG);
1424
1425 Interface->InterfaceHandle = iHandle;
1426
1427 InsertTailList(&ConfigurationHandle->InterfaceHandleList,
1428 &iHandle->InterfaceLink);
1429 }
1430
1431 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1432 LOW_REALTIME_PRIORITY,
1433 1,
1434 FALSE);
1435
1436 return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
1437 }
1438
1439 NTSTATUS
1440 NTAPI
1441 USBPORT_RemoveDevice(IN PDEVICE_OBJECT FdoDevice,
1442 IN OUT PUSBPORT_DEVICE_HANDLE DeviceHandle,
1443 IN ULONG Flags)
1444 {
1445 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1446
1447 DPRINT("USBPORT_RemoveDevice: DeviceHandle - %p, Flags - %x\n",
1448 DeviceHandle,
1449 Flags);
1450
1451 FdoExtension = FdoDevice->DeviceExtension;
1452
1453 if ((Flags & USBD_KEEP_DEVICE_DATA) ||
1454 (Flags & USBD_MARK_DEVICE_BUSY))
1455 {
1456 return STATUS_SUCCESS;
1457 }
1458
1459 KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1460 Executive,
1461 KernelMode,
1462 FALSE,
1463 NULL);
1464
1465 if (!USBPORT_ValidateDeviceHandle(FdoDevice, DeviceHandle))
1466 {
1467 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1468 LOW_REALTIME_PRIORITY,
1469 1,
1470 FALSE);
1471
1472 DPRINT1("USBPORT_RemoveDevice: Not valid device handle\n");
1473 return STATUS_DEVICE_NOT_CONNECTED;
1474 }
1475
1476 USBPORT_RemoveDeviceHandle(FdoDevice, DeviceHandle);
1477
1478 DeviceHandle->Flags |= DEVICE_HANDLE_FLAG_REMOVED;
1479
1480 USBPORT_AbortTransfers(FdoDevice, DeviceHandle);
1481
1482 DPRINT("USBPORT_RemoveDevice: DeviceHandleLock - %x\n",
1483 DeviceHandle->DeviceHandleLock);
1484
1485 while (InterlockedDecrement(&DeviceHandle->DeviceHandleLock) >= 0)
1486 {
1487 InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
1488 USBPORT_Wait(FdoDevice, 100);
1489 }
1490
1491 DPRINT("USBPORT_RemoveDevice: DeviceHandleLock ok\n");
1492
1493 if (DeviceHandle->ConfigHandle)
1494 {
1495 USBPORT_CloseConfiguration(DeviceHandle, FdoDevice);
1496 }
1497
1498 USBPORT_ClosePipe(DeviceHandle, FdoDevice, &DeviceHandle->PipeHandle);
1499
1500 if (DeviceHandle->DeviceAddress)
1501 {
1502 USBPORT_FreeUsbAddress(FdoDevice, DeviceHandle->DeviceAddress);
1503 }
1504
1505 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1506 LOW_REALTIME_PRIORITY,
1507 1,
1508 FALSE);
1509
1510 if (!(DeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB))
1511 {
1512 ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1513 }
1514
1515 return STATUS_SUCCESS;
1516 }
1517
1518 NTSTATUS
1519 NTAPI
1520 USBPORT_RestoreDevice(IN PDEVICE_OBJECT FdoDevice,
1521 IN OUT PUSBPORT_DEVICE_HANDLE OldDeviceHandle,
1522 IN OUT PUSBPORT_DEVICE_HANDLE NewDeviceHandle)
1523 {
1524 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1525 PLIST_ENTRY iHandleList;
1526 PUSBPORT_ENDPOINT Endpoint;
1527 ULONG EndpointRequirements[2] = {0};
1528 USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
1529 NTSTATUS Status = STATUS_SUCCESS;
1530 USBD_STATUS USBDStatus;
1531 KIRQL OldIrql;
1532 PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1533 PUSBPORT_PIPE_HANDLE PipeHandle;
1534 PUSBPORT_REGISTRATION_PACKET Packet;
1535
1536 DPRINT("USBPORT_RestoreDevice: OldDeviceHandle - %p, NewDeviceHandle - %p\n",
1537 OldDeviceHandle,
1538 NewDeviceHandle);
1539
1540 FdoExtension = FdoDevice->DeviceExtension;
1541
1542 KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1543 Executive,
1544 KernelMode,
1545 FALSE,
1546 NULL);
1547
1548 if (!USBPORT_ValidateDeviceHandle(FdoDevice, OldDeviceHandle))
1549 {
1550 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1551 LOW_REALTIME_PRIORITY,
1552 1,
1553 FALSE);
1554
1555 #ifndef NDEBUG
1556 DPRINT("USBPORT_RestoreDevice: OldDeviceHandle not valid\n");
1557 DbgBreakPoint();
1558 #endif
1559 return STATUS_DEVICE_NOT_CONNECTED;
1560 }
1561
1562 if (!USBPORT_ValidateDeviceHandle(FdoDevice, NewDeviceHandle))
1563 {
1564 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1565 LOW_REALTIME_PRIORITY,
1566 1,
1567 FALSE);
1568 #ifndef NDEBUG
1569 DPRINT("USBPORT_RestoreDevice: NewDeviceHandle not valid\n");
1570 DbgBreakPoint();
1571 #endif
1572 return STATUS_DEVICE_NOT_CONNECTED;
1573 }
1574
1575 USBPORT_RemoveDeviceHandle(FdoDevice, OldDeviceHandle);
1576 USBPORT_AbortTransfers(FdoDevice, OldDeviceHandle);
1577
1578 while (InterlockedDecrement(&OldDeviceHandle->DeviceHandleLock) >= 0)
1579 {
1580 InterlockedIncrement(&OldDeviceHandle->DeviceHandleLock);
1581 USBPORT_Wait(FdoDevice, 100);
1582 }
1583
1584 if (sizeof(USB_DEVICE_DESCRIPTOR) == RtlCompareMemory(&NewDeviceHandle->DeviceDescriptor,
1585 &OldDeviceHandle->DeviceDescriptor,
1586 sizeof(USB_DEVICE_DESCRIPTOR)))
1587 {
1588 NewDeviceHandle->ConfigHandle = OldDeviceHandle->ConfigHandle;
1589
1590 if (OldDeviceHandle->ConfigHandle)
1591 {
1592 RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1593
1594 SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1595 SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
1596 SetupPacket.wValue.W = OldDeviceHandle->ConfigHandle->ConfigurationDescriptor->bConfigurationValue;
1597 SetupPacket.wIndex.W = 0;
1598 SetupPacket.wLength = 0;
1599
1600 USBPORT_SendSetupPacket(NewDeviceHandle,
1601 FdoDevice,
1602 &SetupPacket,
1603 NULL,
1604 0,
1605 NULL,
1606 &USBDStatus);
1607
1608 if (USBD_ERROR(USBDStatus))
1609 Status = USBPORT_USBDStatusToNtStatus(NULL, USBDStatus);
1610
1611 if (NT_SUCCESS(Status))
1612 {
1613 iHandleList = NewDeviceHandle->ConfigHandle->InterfaceHandleList.Flink;
1614
1615 while (iHandleList &&
1616 iHandleList != &NewDeviceHandle->ConfigHandle->InterfaceHandleList)
1617 {
1618 InterfaceHandle = CONTAINING_RECORD(iHandleList,
1619 USBPORT_INTERFACE_HANDLE,
1620 InterfaceLink);
1621
1622 if (InterfaceHandle->AlternateSetting)
1623 {
1624 RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1625
1626 SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1627 SetupPacket.bmRequestType.Type = BMREQUEST_STANDARD;
1628 SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
1629
1630 SetupPacket.bRequest = USB_REQUEST_SET_INTERFACE;
1631 SetupPacket.wValue.W = InterfaceHandle->InterfaceDescriptor.bAlternateSetting;
1632 SetupPacket.wIndex.W = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
1633 SetupPacket.wLength = 0;
1634
1635 USBPORT_SendSetupPacket(NewDeviceHandle,
1636 FdoDevice,
1637 &SetupPacket,
1638 NULL,
1639 0,
1640 NULL,
1641 &USBDStatus);
1642 }
1643
1644 iHandleList = iHandleList->Flink;
1645 }
1646 }
1647 }
1648
1649 if (NewDeviceHandle->Flags & DEVICE_HANDLE_FLAG_INITIALIZED)
1650 {
1651 DPRINT1("USBPORT_RestoreDevice: FIXME Transaction Translator\n");
1652 NewDeviceHandle->TtCount = OldDeviceHandle->TtCount;
1653 }
1654
1655 while (!IsListEmpty(&OldDeviceHandle->PipeHandleList))
1656 {
1657 PipeHandle = CONTAINING_RECORD(OldDeviceHandle->PipeHandleList.Flink,
1658 USBPORT_PIPE_HANDLE,
1659 PipeLink);
1660
1661 DPRINT("USBPORT_RestoreDevice: PipeHandle - %p\n", PipeHandle);
1662
1663 USBPORT_RemovePipeHandle(OldDeviceHandle, PipeHandle);
1664
1665 if (PipeHandle != &OldDeviceHandle->PipeHandle)
1666 {
1667 USBPORT_AddPipeHandle(NewDeviceHandle, PipeHandle);
1668
1669 if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE))
1670 {
1671 Endpoint = PipeHandle->Endpoint;
1672 Endpoint->DeviceHandle = NewDeviceHandle;
1673 Endpoint->EndpointProperties.DeviceAddress = NewDeviceHandle->DeviceAddress;
1674
1675 Packet = &FdoExtension->MiniPortInterface->Packet;
1676
1677 if (!(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
1678 {
1679 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock,
1680 &OldIrql);
1681
1682 Packet->ReopenEndpoint(FdoExtension->MiniPortExt,
1683 &Endpoint->EndpointProperties,
1684 Endpoint + 1);
1685
1686 Packet->SetEndpointDataToggle(FdoExtension->MiniPortExt,
1687 Endpoint + 1,
1688 0);
1689
1690 Packet->SetEndpointStatus(FdoExtension->MiniPortExt,
1691 Endpoint + 1,
1692 USBPORT_ENDPOINT_RUN);
1693
1694 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
1695 OldIrql);
1696 }
1697 else
1698 {
1699 MiniportCloseEndpoint(FdoDevice, Endpoint);
1700
1701 RtlZeroMemory(Endpoint + 1, Packet->MiniPortEndpointSize);
1702
1703 RtlZeroMemory((PVOID)Endpoint->EndpointProperties.BufferVA,
1704 Endpoint->EndpointProperties.BufferLength);
1705
1706 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1707
1708 Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt,
1709 &Endpoint->EndpointProperties,
1710 EndpointRequirements);
1711
1712 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
1713 OldIrql);
1714
1715 MiniportOpenEndpoint(FdoDevice, Endpoint);
1716
1717 Endpoint->Flags &= ~(ENDPOINT_FLAG_NUKE |
1718 ENDPOINT_FLAG_ABORTING);
1719
1720 KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
1721 &Endpoint->EndpointOldIrql);
1722
1723 if (Endpoint->StateLast == USBPORT_ENDPOINT_ACTIVE)
1724 {
1725 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
1726
1727 Packet->SetEndpointState(FdoExtension->MiniPortExt,
1728 Endpoint + 1,
1729 USBPORT_ENDPOINT_ACTIVE);
1730
1731 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
1732 }
1733
1734 KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
1735 Endpoint->EndpointOldIrql);
1736 }
1737 }
1738 }
1739 }
1740
1741 USBPORT_AddPipeHandle(OldDeviceHandle, &OldDeviceHandle->PipeHandle);
1742 }
1743 else
1744 {
1745 #ifndef NDEBUG
1746 DPRINT("USBPORT_RestoreDevice: New DeviceDescriptor != Old DeviceDescriptor\n");
1747 DbgBreakPoint();
1748 #endif
1749 Status = STATUS_UNSUCCESSFUL;
1750 }
1751
1752 USBPORT_ClosePipe(OldDeviceHandle, FdoDevice, &OldDeviceHandle->PipeHandle);
1753
1754 if (OldDeviceHandle->DeviceAddress != 0)
1755 USBPORT_FreeUsbAddress(FdoDevice, OldDeviceHandle->DeviceAddress);
1756
1757 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1758 LOW_REALTIME_PRIORITY,
1759 1,
1760 FALSE);
1761
1762 ExFreePoolWithTag(OldDeviceHandle, USB_PORT_TAG);
1763
1764 return Status;
1765 }
1766
1767 NTSTATUS
1768 NTAPI
1769 USBPORT_InitializeTT(IN PDEVICE_OBJECT FdoDevice,
1770 IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
1771 IN ULONG TtNumber)
1772 {
1773 DPRINT1("USBPORT_InitializeTT: UNIMPLEMENTED. FIXME. \n");
1774 return STATUS_SUCCESS;
1775 }
1776
1777 NTSTATUS
1778 NTAPI
1779 USBPORT_Initialize20Hub(IN PDEVICE_OBJECT FdoDevice,
1780 IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
1781 IN ULONG TtCount)
1782 {
1783 NTSTATUS Status;
1784 ULONG ix;
1785
1786 DPRINT("USBPORT_Initialize20Hub \n");
1787
1788 if (!HubDeviceHandle)
1789 {
1790 return STATUS_INVALID_PARAMETER;
1791 }
1792
1793 if (HubDeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB)
1794 {
1795 return STATUS_SUCCESS;
1796 }
1797
1798 if (TtCount == 0)
1799 {
1800 HubDeviceHandle->TtCount = 0;
1801 return STATUS_SUCCESS;
1802 }
1803
1804 for (ix = 0; ix < TtCount; ++ix)
1805 {
1806 Status = USBPORT_InitializeTT(FdoDevice, HubDeviceHandle, ix + 1);
1807
1808 if (!NT_SUCCESS(Status))
1809 break;
1810 }
1811
1812 HubDeviceHandle->TtCount = TtCount;
1813
1814 return Status;
1815 }