[FREELDR]
[reactos.git] / reactos / drivers / usb / usbehci / usbiffn.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbehci/usbiffn.c
5 * PURPOSE: Direct Call Interface Functions.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 */
9
10 /* Many of these direct calls are documented on http://www.osronline.com */
11
12 #include "usbehci.h"
13 #include <hubbusif.h>
14 #include <usbbusif.h>
15 #include "hardware.h"
16 #include "transfer.h"
17
18 PVOID InternalCreateUsbDevice(ULONG Port, PUSB_DEVICE Parent, BOOLEAN Hub)
19 {
20 PUSB_DEVICE UsbDevicePointer = NULL;
21
22 UsbDevicePointer = ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_DEVICE), USB_POOL_TAG);
23
24 if (!UsbDevicePointer)
25 {
26 DPRINT1("Out of memory\n");
27 return NULL;
28 }
29
30 RtlZeroMemory(UsbDevicePointer, sizeof(USB_DEVICE));
31
32 if ((Hub) && (!Parent))
33 {
34 DPRINT1("This is the root hub\n");
35 }
36
37 UsbDevicePointer->Port = Port - 1;
38 UsbDevicePointer->ParentDevice = Parent;
39
40 UsbDevicePointer->IsHub = Hub;
41
42 return UsbDevicePointer;
43 }
44
45 VOID
46 USB_BUSIFFN
47 InterfaceReference(PVOID BusContext)
48 {
49 DPRINT1("Ehci: InterfaceReference called\n");
50 }
51
52 VOID
53 USB_BUSIFFN
54 InterfaceDereference(PVOID BusContext)
55 {
56 DPRINT1("Ehci: InterfaceDereference called\n");
57 }
58
59 /* Bus Interface Hub V5 Functions */
60
61
62 /* Hub Driver calls this routine for each new device it is informed about on USB Bus
63 osronline documents that this is where the device address is assigned. It also
64 states the same for InitializeUsbDevice. This function only gets the device descriptor
65 from the device and checks that the members for device are correct. */
66
67 NTSTATUS
68 USB_BUSIFFN
69 CreateUsbDevice(PVOID BusContext,
70 PUSB_DEVICE_HANDLE *NewDevice,
71 PUSB_DEVICE_HANDLE HubDeviceHandle,
72 USHORT PortStatus, USHORT PortNumber)
73 {
74 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
75 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
76 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
77 PEHCI_HOST_CONTROLLER hcd;
78 PUSB_DEVICE UsbDevice;
79 LONG i;
80
81 DPRINT1("Ehci: CreateUsbDevice: HubDeviceHandle %x, PortStatus %x, PortNumber %x\n", HubDeviceHandle, PortStatus, PortNumber);
82
83 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
84 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
85
86 hcd = &FdoDeviceExtension->hcd;
87
88 if (PdoDeviceExtension->UsbDevices[0] != HubDeviceHandle)
89 {
90 DPRINT1("Not a valid HubDeviceHandle\n");
91 return STATUS_DEVICE_NOT_CONNECTED;
92 }
93
94 UsbDevice = NULL;
95 /* Add it to the list */
96 for (i=0; i < MAX_USB_DEVICES; i++)
97 {
98 if (PdoDeviceExtension->UsbDevices[i] == NULL)
99 {
100 PdoDeviceExtension->UsbDevices[i] = InternalCreateUsbDevice(PortNumber, HubDeviceHandle, FALSE);
101
102 if (!PdoDeviceExtension->UsbDevices[i])
103 return STATUS_INSUFFICIENT_RESOURCES;
104 UsbDevice = PdoDeviceExtension->UsbDevices[i];
105 break;
106 }
107 }
108
109 /* Check that a device was created */
110 if (!UsbDevice)
111 {
112 DPRINT1("Too many usb devices attached. Max is %d\n", MAX_USB_DEVICES);
113 return STATUS_UNSUCCESSFUL;
114 }
115
116 hcd->Ports[PortNumber - 1].PortStatus = PortStatus;
117
118 /* Get the device descriptor */
119 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
120 CtrlSetup.wValue.LowByte = 0;
121 CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
122 CtrlSetup.wIndex.W = 0;
123 CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
124 CtrlSetup.bmRequestType.B = 0x80;
125 ExecuteTransfer(FdoDeviceExtension->DeviceObject,
126 UsbDevice,
127 0,
128 &CtrlSetup,
129 0,
130 &UsbDevice->DeviceDescriptor,
131 sizeof(USB_DEVICE_DESCRIPTOR),
132 NULL);
133
134 /* Check status and bLength and bDescriptor members */
135 if ((UsbDevice->DeviceDescriptor.bLength != 0x12) || (UsbDevice->DeviceDescriptor.bDescriptorType != 0x1))
136 {
137 return STATUS_DEVICE_DATA_ERROR;
138 }
139
140 DumpDeviceDescriptor(&UsbDevice->DeviceDescriptor);
141
142 /* Return it */
143 *NewDevice = UsbDevice;
144 return STATUS_SUCCESS;
145 }
146
147 /* Assigns the device an address, gets the configuration, interface, and endpoint descriptors
148 from the device. All this data is saved as part of this driver */
149
150 NTSTATUS
151 USB_BUSIFFN
152 InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
153 {
154 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
155 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
156 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
157 USB_DEVICE_DESCRIPTOR DeviceDesc;
158 PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc;
159 PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
160 PUSB_ENDPOINT_DESCRIPTOR EndpointDesc;
161 PUSB_DEVICE UsbDevice;
162 PVOID Buffer;
163 PUCHAR Ptr;
164 UCHAR NewAddress = 0;
165
166 LONG i, j, k, InitAttept;
167
168 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
169 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
170
171 UsbDevice = DeviceHandleToUsbDevice(BusContext, DeviceHandle);
172
173 if (!UsbDevice)
174 {
175 DPRINT1("Invalid DeviceHandle or device not connected\n");
176 return STATUS_DEVICE_NOT_CONNECTED;
177 }
178
179 for (i=0; i<127; i++)
180 {
181 if (UsbDevice == PdoDeviceExtension->UsbDevices[i])
182 {
183 NewAddress = i;
184 break;
185 }
186 }
187
188 ASSERT(NewAddress);
189
190 /* Linux drivers make 3 attemps to set the device address because of problems with some devices. Do the same */
191 InitAttept = 0;
192 while (InitAttept < 3)
193 {
194 /* Set the device address */
195 CtrlSetup.bmRequestType.B = 0x00;
196 CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
197 CtrlSetup.wValue.W = NewAddress;
198 CtrlSetup.wIndex.W = 0;
199 CtrlSetup.wLength = 0;
200
201 DPRINT1("Setting Address to %x\n", NewAddress);
202 ExecuteTransfer(PdoDeviceExtension->ControllerFdo,
203 UsbDevice,
204 0,
205 &CtrlSetup,
206 0,
207 NULL,
208 0,
209 NULL);
210
211 KeStallExecutionProcessor(300 * InitAttept);
212
213 /* Send 0 length packet to endpoint 0 for ack */
214 /*
215 ExecuteTransfer(PdoDeviceExtension->ControllerFdo,
216 UsbDevice,
217 0,
218 NULL,
219 0,
220 NULL,
221 0,
222 NULL);
223 */
224
225 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
226 CtrlSetup.wValue.LowByte = 0;
227 CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
228 CtrlSetup.wIndex.W = 0;
229 CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
230 CtrlSetup.bmRequestType.B = 0x80;
231
232 UsbDevice->Address = NewAddress;
233 ExecuteTransfer(FdoDeviceExtension->DeviceObject,
234 UsbDevice,
235 0,
236 &CtrlSetup,
237 0,
238 &DeviceDesc,
239 sizeof(USB_DEVICE_DESCRIPTOR),
240 NULL);
241
242 DPRINT1("Length %d, DescriptorType %d\n", DeviceDesc.bLength, DeviceDesc.bDescriptorType);
243 if ((DeviceDesc.bLength == 0x12) && (DeviceDesc.bDescriptorType == 0x01))
244 break;
245
246 /* If the descriptor was not gotten */
247 UsbDevice->Address = 0;
248 InitAttept++;
249 }
250
251 if (InitAttept == 3)
252 {
253 DPRINT1("Unable to initialize usb device connected on port %d!\n", UsbDevice->Port);
254 /* FIXME: Should the memory allocated for this device be deleted? */
255 return STATUS_DEVICE_DATA_ERROR;
256 }
257 DumpDeviceDescriptor(&DeviceDesc);
258
259 if (UsbDevice->DeviceDescriptor.bNumConfigurations == 0)
260 {
261 DPRINT1("Device on port %d has no configurations!\n", UsbDevice->Port);
262 /* FIXME: Should the memory allocated for this device be deleted? */
263 return STATUS_DEVICE_DATA_ERROR;
264 }
265 UsbDevice->Configs = ExAllocatePoolWithTag(NonPagedPool,
266 sizeof(PVOID) * UsbDevice->DeviceDescriptor.bNumConfigurations,
267 USB_POOL_TAG);
268
269 if (!UsbDevice->Configs)
270 {
271 DPRINT1("Out of memory\n");
272 /* FIXME: Should the memory allocated for this device be deleted? */
273 return STATUS_NO_MEMORY;
274 }
275
276 Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, USB_POOL_TAG);
277
278 if (!Buffer)
279 {
280 DPRINT1("Out of memory\n");
281 /* FIXME: Should the memory allocated for this device be deleted? */
282 return STATUS_NO_MEMORY;
283 }
284
285 Ptr = Buffer;
286
287 for (i = 0; i < UsbDevice->DeviceDescriptor.bNumConfigurations; i++)
288 {
289 /* Get the Device Configuration Descriptor */
290 CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
291 CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
292 CtrlSetup.bmRequestType._BM.Reserved = 0;
293 CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
294 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
295 CtrlSetup.wValue.LowByte = 0;
296 CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
297 CtrlSetup.wIndex.W = 0;
298 CtrlSetup.wLength = PAGE_SIZE;
299 ExecuteTransfer(PdoDeviceExtension->ControllerFdo,
300 UsbDevice,
301 0,
302 &CtrlSetup,
303 0,
304 Buffer,
305 PAGE_SIZE,
306 NULL);
307
308 ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)Ptr;
309
310 DumpFullConfigurationDescriptor(ConfigDesc);
311 ASSERT(ConfigDesc->wTotalLength <= PAGE_SIZE);
312
313 UsbDevice->Configs[i] = ExAllocatePoolWithTag(NonPagedPool,
314 sizeof(USB_CONFIGURATION) + sizeof(PVOID) * ConfigDesc->bNumInterfaces,
315 USB_POOL_TAG);
316 UsbDevice->Configs[i]->Device = UsbDevice;
317
318 RtlCopyMemory(&UsbDevice->Configs[0]->ConfigurationDescriptor,
319 ConfigDesc, sizeof(USB_CONFIGURATION_DESCRIPTOR));
320 Ptr += ConfigDesc->bLength;
321
322 for (j = 0; j < ConfigDesc->bNumInterfaces; j++)
323 {
324 InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) Ptr;
325 UsbDevice->Configs[i]->Interfaces[j] = ExAllocatePoolWithTag(NonPagedPool,
326 sizeof(USB_INTERFACE) + sizeof(PVOID) * InterfaceDesc->bNumEndpoints,
327 USB_POOL_TAG);
328 RtlCopyMemory(&UsbDevice->Configs[i]->Interfaces[j]->InterfaceDescriptor,
329 InterfaceDesc,
330 sizeof(USB_INTERFACE_DESCRIPTOR));
331
332 Ptr += InterfaceDesc->bLength;
333
334 for (k = 0; k < InterfaceDesc->bNumEndpoints; k++)
335 {
336 EndpointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Ptr;
337 UsbDevice->Configs[i]->Interfaces[j]->EndPoints[k] = ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_ENDPOINT), USB_POOL_TAG);
338 RtlCopyMemory(&UsbDevice->Configs[i]->Interfaces[j]->EndPoints[k]->EndPointDescriptor,
339 EndpointDesc, sizeof(USB_ENDPOINT_DESCRIPTOR));
340 Ptr += sizeof(USB_ENDPOINT_DESCRIPTOR);
341 }
342 }
343 }
344
345 UsbDevice->ActiveConfig = UsbDevice->Configs[0];
346 UsbDevice->ActiveInterface = UsbDevice->Configs[0]->Interfaces[0];
347
348 UsbDevice->DeviceState = DEVICEINTIALIZED;
349
350 return STATUS_SUCCESS;
351 }
352
353 /* Return the descriptors that will fit. Descriptors were saved when the InitializeUsbDevice function was called */
354 NTSTATUS
355 USB_BUSIFFN
356 GetUsbDescriptors(PVOID BusContext,
357 PUSB_DEVICE_HANDLE DeviceHandle,
358 PUCHAR DeviceDescriptorBuffer,
359 PULONG DeviceDescriptorBufferLength,
360 PUCHAR ConfigDescriptorBuffer,
361 PULONG ConfigDescriptorBufferLength)
362 {
363 PUSB_DEVICE UsbDevice;
364 DPRINT1("Ehci: GetUsbDescriptor %x, %x, %x, %x\n", DeviceDescriptorBuffer, *DeviceDescriptorBufferLength,
365 ConfigDescriptorBuffer, *ConfigDescriptorBufferLength);
366
367 UsbDevice = DeviceHandleToUsbDevice(BusContext, DeviceHandle);
368
369 if (!UsbDevice)
370 {
371 DPRINT1("Invalid DeviceHandle or device not connected\n");
372 return STATUS_DEVICE_NOT_CONNECTED;
373 }
374
375 if ((DeviceDescriptorBuffer) && (DeviceDescriptorBufferLength))
376 {
377 RtlCopyMemory(DeviceDescriptorBuffer, &UsbDevice->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
378 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
379 }
380
381 if ((ConfigDescriptorBuffer) && (ConfigDescriptorBufferLength))
382 {
383 RtlCopyMemory(ConfigDescriptorBuffer, &UsbDevice->ActiveConfig->ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR));
384 *ConfigDescriptorBufferLength = sizeof(USB_CONFIGURATION_DESCRIPTOR);
385 }
386
387 return STATUS_SUCCESS;
388 }
389
390 /* Documented http://www.osronline.com/ddkx/buses/usbinterkr_1m7m.htm */
391 NTSTATUS
392 USB_BUSIFFN
393 RemoveUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle, ULONG Flags)
394 {
395 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
396 PUSB_DEVICE UsbDevice;
397 LONG i, j, k;
398
399 DPRINT1("RemoveUsbDevice called, DeviceHandle %x, Flags %x\n", DeviceHandle, Flags);
400
401 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
402
403 UsbDevice = DeviceHandleToUsbDevice(BusContext, DeviceHandle);
404
405 if (!UsbDevice)
406 {
407 DPRINT1("Invalid DeviceHandle or device not connected\n");
408 return STATUS_DEVICE_NOT_CONNECTED;
409 }
410
411 switch (Flags)
412 {
413 case 0:
414 DPRINT1("Number of Configurations %d\n", UsbDevice->DeviceDescriptor.bNumConfigurations);
415 for (i = 0; i < UsbDevice->DeviceDescriptor.bNumConfigurations; i++)
416 {
417 for (j = 0; j < UsbDevice->Configs[i]->ConfigurationDescriptor.bNumInterfaces; j++)
418 {
419 for (k = 0; k < UsbDevice->Configs[i]->Interfaces[j]->InterfaceDescriptor.bNumEndpoints; k++)
420 {
421 ExFreePool(UsbDevice->Configs[i]->Interfaces[j]->EndPoints[k]);
422 }
423 ExFreePool(UsbDevice->Configs[i]->Interfaces[j]);
424 }
425 ExFreePool(UsbDevice->Configs[i]);
426 }
427
428 for (i = 0; i < 127; i++)
429 {
430 if (PdoDeviceExtension->UsbDevices[i] == UsbDevice)
431 PdoDeviceExtension->UsbDevices[i] = NULL;
432 }
433
434 ExFreePool(UsbDevice);
435 break;
436 case USBD_MARK_DEVICE_BUSY:
437 UsbDevice->DeviceState |= DEVICEBUSY;
438 /* Fall through */
439 case USBD_KEEP_DEVICE_DATA:
440 UsbDevice->DeviceState |= DEVICEREMOVED;
441 break;
442 default:
443 DPRINT1("Unknown Remove Flags %x\n", Flags);
444 }
445 return STATUS_SUCCESS;
446 }
447
448 /* Documented at http://www.osronline.com/ddkx/buses/usbinterkr_01te.htm */
449 NTSTATUS
450 USB_BUSIFFN
451 RestoreUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE OldDeviceHandle, PUSB_DEVICE_HANDLE NewDeviceHandle)
452 {
453 PUSB_DEVICE OldUsbDevice;
454 PUSB_DEVICE NewUsbDevice;
455 PUSB_CONFIGURATION ConfigToDelete;
456 int i;
457
458 DPRINT1("Ehci: RestoreUsbDevice %x, %x, %x\n", BusContext, OldDeviceHandle, NewDeviceHandle);
459 ASSERT(FALSE);
460 OldUsbDevice = DeviceHandleToUsbDevice(BusContext, OldDeviceHandle);
461 NewUsbDevice = DeviceHandleToUsbDevice(BusContext, NewDeviceHandle);
462
463 if (!OldUsbDevice)
464 {
465 DPRINT1("OldDeviceHandle is invalid\n");
466 return STATUS_DEVICE_NOT_CONNECTED;
467 }
468
469 if (!(OldUsbDevice->DeviceState & DEVICEREMOVED))
470 {
471 DPRINT1("UsbDevice is not marked as Removed!\n");
472 return STATUS_UNSUCCESSFUL;
473 }
474
475 if (!NewUsbDevice)
476 {
477 DPRINT1("NewDeviceHandle is invalid\n");
478 return STATUS_DEVICE_NOT_CONNECTED;
479 }
480
481 if ((OldUsbDevice->DeviceDescriptor.idVendor == NewUsbDevice->DeviceDescriptor.idVendor) &&
482 (OldUsbDevice->DeviceDescriptor.idProduct == NewUsbDevice->DeviceDescriptor.idProduct))
483 {
484 NewUsbDevice->DeviceState &= ~DEVICEBUSY;
485 NewUsbDevice->DeviceState &= ~DEVICEREMOVED;
486
487 NewUsbDevice->ActiveConfig = OldUsbDevice->ActiveConfig;
488 NewUsbDevice->ActiveInterface = OldUsbDevice->ActiveInterface;
489
490 for (i = 0; i < NewUsbDevice->DeviceDescriptor.bNumConfigurations; i++)
491 {
492 ConfigToDelete = NewUsbDevice->Configs[i];
493 ASSERT(OldUsbDevice->Configs[i]);
494 NewUsbDevice->Configs[i] = OldUsbDevice->Configs[i];
495 OldUsbDevice->Configs[i] = ConfigToDelete;
496 }
497
498 RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
499 return STATUS_SUCCESS;
500 }
501 else
502 {
503 DPRINT1("VendorId or ProductId did not match!\n");
504 return STATUS_DEVICE_NOT_CONNECTED;
505 }
506 }
507
508 /* FIXME: Research this */
509 NTSTATUS
510 USB_BUSIFFN
511 GetPortHackFlags(PVOID BusContext, PULONG Flags)
512 {
513 DPRINT1("Ehci: GetPortHackFlags not implemented. %x, %x\n", BusContext, Flags);
514 return STATUS_NOT_SUPPORTED;
515 }
516
517 NTSTATUS
518 USB_BUSIFFN
519 QueryDeviceInformation(PVOID BusContext,
520 PUSB_DEVICE_HANDLE DeviceHandle,
521 PVOID DeviceInformationBuffer,
522 ULONG DeviceInformationBufferLength,
523 PULONG LengthReturned)
524 {
525 PUSB_DEVICE_INFORMATION_0 DeviceInfo = DeviceInformationBuffer;
526 PUSB_DEVICE UsbDevice;
527 ULONG SizeNeeded;
528 LONG i;
529
530 DPRINT1("Ehci: QueryDeviceInformation (%x, %x, %x, %d, %x\n", BusContext, DeviceHandle, DeviceInformationBuffer,
531 DeviceInformationBufferLength, LengthReturned);
532
533 UsbDevice = DeviceHandleToUsbDevice(BusContext, DeviceHandle);
534
535 if (!UsbDevice)
536 {
537 DPRINT1("Invalid DeviceHandle or device not connected\n");
538 return STATUS_DEVICE_NOT_CONNECTED;
539 }
540
541 SizeNeeded = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[UsbDevice->ActiveInterface->InterfaceDescriptor.bNumEndpoints]);
542 *LengthReturned = SizeNeeded;
543
544 DeviceInfo->ActualLength = SizeNeeded;
545
546 if (DeviceInformationBufferLength < SizeNeeded)
547 {
548 DPRINT1("Buffer to small\n");
549 return STATUS_BUFFER_TOO_SMALL;
550 }
551
552 if (DeviceInfo->InformationLevel != 0)
553 {
554 DPRINT1("Invalid Param\n");
555 return STATUS_INVALID_PARAMETER;
556 }
557
558 DeviceInfo->HubAddress = 0;
559 DeviceInfo->DeviceAddress = UsbDevice->Address;
560 DeviceInfo->DeviceSpeed = UsbDevice->DeviceSpeed;
561 DeviceInfo->DeviceType = UsbDevice->DeviceType;
562
563 if (!UsbDevice->DeviceState)
564 {
565 DeviceInfo->CurrentConfigurationValue = 0;
566 DeviceInfo->NumberOfOpenPipes = 0;
567 DeviceInfo->PortNumber = 0;
568 }
569 else
570 {
571 DeviceInfo->CurrentConfigurationValue = UsbDevice->ActiveConfig->ConfigurationDescriptor.bConfigurationValue;
572 /* FIXME: Use correct number of open pipes instead of all available */
573 DeviceInfo->NumberOfOpenPipes = UsbDevice->ActiveInterface->InterfaceDescriptor.bNumEndpoints;
574 DeviceInfo->PortNumber = UsbDevice->Port;
575 }
576
577 RtlCopyMemory(&DeviceInfo->DeviceDescriptor, &UsbDevice->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
578
579 for (i = 0; i < UsbDevice->ActiveInterface->InterfaceDescriptor.bNumEndpoints; i++)
580 {
581 RtlCopyMemory(&DeviceInfo->PipeList[i].EndpointDescriptor,
582 &UsbDevice->ActiveInterface->EndPoints[i]->EndPointDescriptor,
583 sizeof(USB_ENDPOINT_DESCRIPTOR));
584 }
585 return STATUS_SUCCESS;
586 }
587
588 NTSTATUS
589 USB_BUSIFFN
590 GetControllerInformation(PVOID BusContext,
591 PVOID ControllerInformationBuffer,
592 ULONG ControllerInformationBufferLength,
593 PULONG LengthReturned)
594 {
595 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
596
597 DPRINT1("Ehci: GetControllerInformation called\n");
598
599 if (!LengthReturned)
600 return STATUS_INVALID_PARAMETER;
601
602 ControllerInfo = ControllerInformationBuffer;
603
604 if (ControllerInformationBufferLength < sizeof(USB_CONTROLLER_INFORMATION_0))
605 {
606 DPRINT1("Buffer to small\n");
607 return STATUS_BUFFER_TOO_SMALL;
608 }
609
610 if (ControllerInfo->InformationLevel != 0)
611 {
612 DPRINT1("InformationLevel other than 0 not supported\n");
613 return STATUS_NOT_SUPPORTED;
614 }
615
616 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
617 ControllerInfo->SelectiveSuspendEnabled = FALSE;
618 ControllerInfo->IsHighSpeedController = TRUE;
619
620 *LengthReturned = ControllerInfo->ActualLength;
621
622 return STATUS_SUCCESS;
623 }
624
625 NTSTATUS
626 USB_BUSIFFN
627 ControllerSelectiveSuspend(PVOID BusContext, BOOLEAN Enable)
628 {
629 DPRINT1("Ehci: ControllerSelectiveSuspend not implemented\n");
630 return STATUS_NOT_SUPPORTED;
631 }
632
633 NTSTATUS
634 USB_BUSIFFN
635 GetExtendedHubInformation(PVOID BusContext,
636 PDEVICE_OBJECT HubPhysicalDeviceObject,
637 PVOID HubInformationBuffer,
638 ULONG HubInformationBufferLength,
639 PULONG LengthReturned)
640 {
641
642 PUSB_EXTHUB_INFORMATION_0 UsbExtHubInfo = HubInformationBuffer;
643 PPDO_DEVICE_EXTENSION PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
644 PFDO_DEVICE_EXTENSION FdoDeviceExntension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
645 LONG i;
646 DPRINT1("Ehci: GetExtendedHubInformation BusContext %x, PDO %x, InformationBuffer %x\n",
647 BusContext, HubPhysicalDeviceObject, HubInformationBuffer);
648
649 /* Set the default return value */
650 *LengthReturned = 0;
651
652 DPRINT("InformationLevel %x\n", UsbExtHubInfo->InformationLevel);
653
654 /* Caller is suppose to have set InformationLevel to 0. However usbehci from MS seems to ignore this */
655 if (UsbExtHubInfo->InformationLevel != 0)
656 {
657 DPRINT1("InformationLevel should really be set to 0. Ignoring\n");
658 }
659
660 UsbExtHubInfo->NumberOfPorts = FdoDeviceExntension->hcd.ECHICaps.HCSParams.PortCount;
661
662 for (i=0; i < UsbExtHubInfo->NumberOfPorts; i++)
663 {
664 UsbExtHubInfo->Port[i].PhysicalPortNumber = i + 1;
665 UsbExtHubInfo->Port[i].PortLabelNumber = i + 1;
666 UsbExtHubInfo->Port[i].VidOverride = 0;
667 UsbExtHubInfo->Port[i].PidOverride = 0;
668 UsbExtHubInfo->Port[i].PortAttributes = USB_PORTATTR_SHARED_USB2;// | USB_PORTATTR_OWNED_BY_CC;
669 }
670
671 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[8]);
672
673 return STATUS_SUCCESS;
674 }
675
676 NTSTATUS
677 USB_BUSIFFN
678 GetRootHubSymbolicName(PVOID BusContext,
679 PVOID HubSymNameBuffer,
680 ULONG HubSymNameBufferLength,
681 PULONG HubSymNameActualLength)
682 {
683 DPRINT1("Ehci: GetRootHubSymbolicName called\n");
684
685 if (HubSymNameBufferLength < 16)
686 return STATUS_UNSUCCESSFUL;
687 RtlCopyMemory(HubSymNameBuffer, L"ROOT_HUB", HubSymNameBufferLength);
688 *HubSymNameActualLength = 16;
689
690 return STATUS_SUCCESS;
691 }
692
693 PVOID
694 USB_BUSIFFN
695 GetDeviceBusContext(PVOID HubBusContext, PVOID DeviceHandle)
696 {
697 PUSB_DEVICE UsbDevice;
698
699 DPRINT1("Ehci: GetDeviceBusContext called\n");
700 UsbDevice = DeviceHandleToUsbDevice(HubBusContext, DeviceHandle);
701
702 if (!UsbDevice)
703 {
704 DPRINT1("Invalid DeviceHandle or device not connected\n");
705 return NULL;
706 }
707
708 return NULL;
709 }
710
711 NTSTATUS
712 USB_BUSIFFN
713 Initialize20Hub(PVOID BusContext, PUSB_DEVICE_HANDLE HubDeviceHandle, ULONG TtCount)
714 {
715 DPRINT1("Ehci: Initialize20Hub called, HubDeviceHandle: %x, TtCount %x\n", HubDeviceHandle, TtCount);
716 /* FIXME: */
717 /* Create the Irp Queue for SCE */
718 /* Should queue be created for each device or each enpoint??? */
719 return STATUS_SUCCESS;
720 }
721
722 NTSTATUS
723 USB_BUSIFFN
724 RootHubInitNotification(PVOID BusContext, PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine)
725 {
726 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
727 DPRINT1("Ehci: RootHubInitNotification %x, %x, %x\n", BusContext, CallbackContext, CallbackRoutine);
728
729 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
730 PdoDeviceExtension->CallbackContext = CallbackContext;
731 PdoDeviceExtension->CallbackRoutine = CallbackRoutine;
732 if (PdoDeviceExtension->CallbackRoutine)
733 {
734 DPRINT1("Called Callbackrountine\n");
735 PdoDeviceExtension->CallbackRoutine(PdoDeviceExtension->CallbackContext);
736 DPRINT1("Done Callbackrountine\n");
737 }
738 else
739 {
740 DPRINT1("PdoDeviceExtension->CallbackRoutine is NULL!\n");
741 }
742
743 return STATUS_SUCCESS;
744 }
745
746 VOID
747 USB_BUSIFFN
748 FlushTransfers(PVOID BusContext, PVOID DeviceHandle)
749 {
750 PUSB_DEVICE UsbDevice;
751 UsbDevice = DeviceHandleToUsbDevice(BusContext, DeviceHandle);
752
753 if (!UsbDevice)
754 {
755 DPRINT1("Invalid DeviceHandle or device not connected\n");
756 }
757
758 DPRINT1("FlushTransfers not implemented.\n");
759 }
760
761 VOID
762 USB_BUSIFFN
763 SetDeviceHandleData(PVOID BusContext, PVOID DeviceHandle, PDEVICE_OBJECT UsbDevicePdo)
764 {
765 PUSB_DEVICE UsbDevice;
766
767 DPRINT1("Ehci: SetDeviceHandleData %x, %x, %x\n", BusContext, DeviceHandle, UsbDevicePdo);
768 UsbDevice = DeviceHandleToUsbDevice(BusContext, DeviceHandle);
769 if (!UsbDevice)
770 {
771 DPRINT1("Invalid DeviceHandle or device not connected\n");
772 return;
773 }
774
775 UsbDevice->UsbDevicePdo = UsbDevicePdo;
776 }
777
778
779 /* USB_BUS_INTERFACE_USBDI_V2 Functions */
780
781 VOID
782 USB_BUSIFFN
783 GetUSBDIVersion(PVOID BusContext, PUSBD_VERSION_INFORMATION VersionInformation, PULONG HcdCapabilites)
784 {
785 DPRINT1("Ehci: GetUSBDIVersion called\n");
786 return;
787 }
788
789 NTSTATUS
790 USB_BUSIFFN
791 QueryBusTime(PVOID BusContext, PULONG CurrentFrame)
792 {
793 DPRINT1("Ehci: QueryBusTime called\n");
794 return STATUS_NOT_SUPPORTED;
795 }
796
797 NTSTATUS
798 USB_BUSIFFN
799 SubmitIsoOutUrb(PVOID BusContext, PURB Urb)
800 {
801 DPRINT1("Ehci: SubmitIsoOutUrb called\n");
802 return STATUS_NOT_SUPPORTED;
803 }
804
805 NTSTATUS
806 USB_BUSIFFN
807 QueryBusInformation(PVOID BusContext,
808 ULONG Level,
809 PVOID BusInformationBuffer,
810 PULONG BusInformationBufferLength,
811 PULONG BusInformationActualLength)
812 {
813 DPRINT1("Ehci: QueryBusInformation called\n");
814 return STATUS_NOT_SUPPORTED;
815 }
816
817 BOOLEAN
818 USB_BUSIFFN
819 IsDeviceHighSpeed(PVOID BusContext)
820 {
821 DPRINT1("Ehci: IsDeviceHighSpeed called\n");
822 return TRUE;
823 }
824
825 NTSTATUS
826 USB_BUSIFFN
827 EnumLogEntry(PVOID BusContext, ULONG DriverTag, ULONG EnumTag, ULONG P1, ULONG P2)
828 {
829 DPRINT1("Ehci: EnumLogEntry called %x, %x, %x, %x\n", DriverTag, EnumTag, P1, P2);
830
831 return STATUS_SUCCESS;
832 }