[USB]
[reactos.git] / reactos / drivers / usb / usbohci / hub_controller.cpp
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/usbohci/hub_controller.cpp
5 * PURPOSE: USB OHCI device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 */
10
11 #define INITGUID
12 #include "usbohci.h"
13
14 VOID StatusChangeEndpointCallBack(
15 PVOID Context);
16
17 class CHubController : public IHubController,
18 public IDispatchIrp
19 {
20 public:
21 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
22
23 STDMETHODIMP_(ULONG) AddRef()
24 {
25 InterlockedIncrement(&m_Ref);
26 return m_Ref;
27 }
28 STDMETHODIMP_(ULONG) Release()
29 {
30 InterlockedDecrement(&m_Ref);
31
32 if (!m_Ref)
33 {
34 delete this;
35 return 0;
36 }
37 return m_Ref;
38 }
39
40 // IHubController interface functions
41 virtual NTSTATUS Initialize(IN PDRIVER_OBJECT DriverObject, IN PHCDCONTROLLER Controller, IN PUSBHARDWAREDEVICE Device, IN BOOLEAN IsRootHubDevice, IN ULONG DeviceAddress);
42 virtual NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject);
43 virtual NTSTATUS GetHubControllerSymbolicLink(ULONG BufferLength, PVOID Buffer, PULONG RequiredLength);
44
45 // IDispatchIrp interface functions
46 virtual NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
47 virtual NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
48 virtual NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
49
50 // local functions
51 NTSTATUS HandleQueryInterface(PIO_STACK_LOCATION IoStack);
52 NTSTATUS SetDeviceInterface(BOOLEAN bEnable);
53 NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject);
54 PUSBHARDWAREDEVICE GetUsbHardware();
55 ULONG AcquireDeviceAddress();
56 VOID ReleaseDeviceAddress(ULONG DeviceAddress);
57 BOOLEAN ValidateUsbDevice(PUSBDEVICE UsbDevice);
58 NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice);
59 NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice);
60 VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
61 // internal ioctl routines
62 NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb);
63 NTSTATUS HandleGetDescriptorFromInterface(IN OUT PIRP Irp, PURB Urb);
64 NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
65 NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
66 NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
67 NTSTATUS HandleSelectInterface(IN OUT PIRP Irp, PURB Urb);
68 NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
69 NTSTATUS HandleClassInterface(IN OUT PIRP Irp, PURB Urb);
70 NTSTATUS HandleClassEndpoint(IN OUT PIRP Irp, PURB Urb);
71 NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
72 NTSTATUS HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb);
73 NTSTATUS HandleClearStall(IN OUT PIRP Irp, PURB Urb);
74 NTSTATUS HandleSyncResetAndClearStall(IN OUT PIRP Irp, PURB Urb);
75 NTSTATUS HandleAbortPipe(IN OUT PIRP Irp, PURB Urb);
76
77 friend VOID StatusChangeEndpointCallBack(PVOID Context);
78
79 // constructor / destructor
80 CHubController(IUnknown *OuterUnknown){}
81 virtual ~CHubController(){}
82
83 protected:
84 LONG m_Ref;
85 PHCDCONTROLLER m_Controller;
86 PUSBHARDWAREDEVICE m_Hardware;
87 BOOLEAN m_IsRootHubDevice;
88 ULONG m_DeviceAddress;
89
90 BOOLEAN m_InterfaceEnabled;
91 UNICODE_STRING m_HubDeviceInterfaceString;
92
93 PDEVICE_OBJECT m_HubControllerDeviceObject;
94 PDRIVER_OBJECT m_DriverObject;
95
96 PVOID m_HubCallbackContext;
97 PRH_INIT_CALLBACK m_HubCallbackRoutine;
98
99 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
100
101 KSPIN_LOCK m_Lock;
102 RTL_BITMAP m_DeviceAddressBitmap;
103 PULONG m_DeviceAddressBitmapBuffer;
104 LIST_ENTRY m_UsbDeviceList;
105 PIRP m_PendingSCEIrp;
106
107 //Internal Functions
108 BOOLEAN QueryStatusChageEndpoint(PIRP Irp);
109 };
110
111 typedef struct
112 {
113 LIST_ENTRY Entry;
114 PUSBDEVICE Device;
115 }USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY;
116
117 /* Lifted from Linux with slight changes */
118 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
119 {
120 0x12, /* bLength; */
121 USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType; Device */
122 0x00, 0x20, /* bcdUSB; v1.1 */
123 USB_DEVICE_CLASS_HUB, /* bDeviceClass; HUB_CLASSCODE */
124 0x01, /* bDeviceSubClass; */
125 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
126 0x08, /* bMaxPacketSize0; 8 Bytes */
127 /* Fill Vendor and Product in when init root hub */
128 0x00, 0x00, /* idVendor; */
129 0x00, 0x00, /* idProduct; */
130 0x00, 0x00, /* bcdDevice */
131 0x00, /* iManufacturer; */
132 0x00, /* iProduct; */
133 0x00, /* iSerialNumber; */
134 0x01 /* bNumConfigurations; */
135
136 };
137
138 const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR =
139 {
140 sizeof(USB_CONFIGURATION_DESCRIPTOR),
141 USB_CONFIGURATION_DESCRIPTOR_TYPE,
142 sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
143 1,
144 1,
145 0,
146 0x40, /* self powered */
147 0x0
148 };
149
150 const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR =
151 {
152 sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */
153 USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType; Interface */
154 0, /* bInterfaceNumber; */
155 0, /* bAlternateSetting; */
156 0x1, /* bNumEndpoints; */
157 0x09, /* bInterfaceClass; HUB_CLASSCODE */
158 0x01, /* bInterfaceSubClass; */
159 0x00, /* bInterfaceProtocol: */
160 0x00, /* iInterface; */
161 };
162
163 const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR =
164 {
165 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */
166 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
167 0x81, /* bEndPointAddress */
168 USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
169 0x01, /* wMaxPacketSize */
170 0xC /* bInterval */
171 };
172
173 //----------------------------------------------------------------------------------------
174 NTSTATUS
175 STDMETHODCALLTYPE
176 CHubController::QueryInterface(
177 IN REFIID refiid,
178 OUT PVOID* Output)
179 {
180 return STATUS_UNSUCCESSFUL;
181 }
182 //----------------------------------------------------------------------------------------
183 NTSTATUS
184 CHubController::Initialize(
185 IN PDRIVER_OBJECT DriverObject,
186 IN PHCDCONTROLLER Controller,
187 IN PUSBHARDWAREDEVICE Device,
188 IN BOOLEAN IsRootHubDevice,
189 IN ULONG DeviceAddress)
190 {
191 NTSTATUS Status;
192 PCOMMON_DEVICE_EXTENSION DeviceExtension;
193 USHORT VendorID, DeviceID;
194 ULONG Dummy1;
195
196 DPRINT("CHubController::Initialize\n");
197
198 //
199 // initialize members
200 //
201 m_Controller = Controller;
202 m_Hardware = Device;
203 m_IsRootHubDevice = IsRootHubDevice;
204 m_DeviceAddress = DeviceAddress;
205 m_DriverObject = DriverObject;
206 KeInitializeSpinLock(&m_Lock);
207 InitializeListHead(&m_UsbDeviceList);
208
209 //
210 // allocate device address bitmap buffer
211 //
212 m_DeviceAddressBitmapBuffer = (PULONG)ExAllocatePoolWithTag(NonPagedPool, 16, TAG_USBOHCI);
213 if (!m_DeviceAddressBitmapBuffer)
214 {
215 //
216 // no memory
217 //
218 return STATUS_INSUFFICIENT_RESOURCES;
219 }
220
221 //
222 // initialize device address bitmap
223 //
224 RtlInitializeBitMap(&m_DeviceAddressBitmap, m_DeviceAddressBitmapBuffer, 128);
225 RtlClearAllBits(&m_DeviceAddressBitmap);
226
227
228 //
229 // create PDO
230 //
231 Status = CreatePDO(m_DriverObject, &m_HubControllerDeviceObject);
232 if (!NT_SUCCESS(Status))
233 {
234 //
235 // failed to create hub device object
236 //
237 return Status;
238 }
239
240 //
241 // get device extension
242 //
243 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_HubControllerDeviceObject->DeviceExtension;
244
245 //
246 // initialize device extension
247 //
248 DeviceExtension->IsFDO = FALSE;
249 DeviceExtension->IsHub = TRUE; //FIXME
250 DeviceExtension->Dispatcher = PDISPATCHIRP(this);
251
252 //
253 // intialize device descriptor
254 //
255 C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
256 RtlMoveMemory(&m_DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
257
258 if (NT_SUCCESS(m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &Dummy1, &Dummy1)))
259 {
260 //
261 // update device descriptor
262 //
263 m_DeviceDescriptor.idVendor = VendorID;
264 m_DeviceDescriptor.idProduct = DeviceID;
265 m_DeviceDescriptor.bcdUSB = 0x110; //FIXME
266 }
267
268 //
269 // Set the SCE Callback that the Hardware Device will call on port status change
270 //
271 Device->SetStatusChangeEndpointCallBack((PVOID)StatusChangeEndpointCallBack, this);
272
273 //
274 // clear init flag
275 //
276 m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
277
278 return STATUS_SUCCESS;
279 }
280
281 //
282 // Queries the ports to see if there has been a device connected or removed.
283 //
284 BOOLEAN
285 CHubController::QueryStatusChageEndpoint(
286 PIRP Irp)
287 {
288 ULONG PortCount, PortId;
289 PIO_STACK_LOCATION IoStack;
290 USHORT PortStatus, PortChange;
291 PURB Urb;
292 PUCHAR TransferBuffer;
293 UCHAR Changed = FALSE;
294
295 //
296 // get current stack location
297 //
298 IoStack = IoGetCurrentIrpStackLocation(Irp);
299 ASSERT(IoStack);
300
301 //
302 // Get the Urb
303 //
304 Urb = (PURB)IoStack->Parameters.Others.Argument1;
305 ASSERT(Urb);
306
307 //
308 // Get the number of ports and check each one for device connected
309 //
310 m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
311 DPRINT("SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, Urb->UrbBulkOrInterruptTransfer.TransferFlags, Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
312
313 TransferBuffer = (PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer;
314
315 //
316 // Loop the ports
317 //
318 for (PortId = 0; PortId < PortCount; PortId++)
319 {
320 m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
321
322 DPRINT("Port %d: Status %x, Change %x\n", PortId, PortStatus, PortChange);
323
324
325 //
326 // If theres a flag in PortChange return TRUE so the SCE Irp will be completed
327 //
328 if (PortChange != 0)
329 {
330 DPRINT1("Change state on port %d\n", PortId);
331 // Set the value for the port number
332 *TransferBuffer = 1 << ((PortId + 1) & 7);
333 Changed = TRUE;
334 }
335 }
336
337 return Changed;
338 }
339
340 //-----------------------------------------------------------------------------------------
341 NTSTATUS
342 CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject)
343 {
344 //
345 // store controller object
346 //
347 *HubDeviceObject = m_HubControllerDeviceObject;
348
349 return STATUS_SUCCESS;
350 }
351 //-----------------------------------------------------------------------------------------
352 NTSTATUS
353 CHubController::GetHubControllerSymbolicLink(
354 ULONG BufferLength,
355 PVOID Buffer,
356 PULONG RequiredLength)
357 {
358 if (!m_InterfaceEnabled)
359 {
360 //
361 // device interface not yet enabled
362 //
363 return STATUS_UNSUCCESSFUL;
364 }
365
366 if (BufferLength < (ULONG)m_HubDeviceInterfaceString.Length - 8)
367 {
368 //
369 // buffer too small
370 // length is without '\??\'
371 //
372 *RequiredLength = m_HubDeviceInterfaceString.Length- 8;
373
374 //
375 // done
376 //
377 return STATUS_BUFFER_OVERFLOW;
378 }
379
380 //
381 // copy symbolic link
382 //
383 RtlCopyMemory(Buffer, &m_HubDeviceInterfaceString.Buffer[4], m_HubDeviceInterfaceString.Length - 8);
384
385 //
386 // store length, length is without '\??\'
387 //
388 *RequiredLength = m_HubDeviceInterfaceString.Length - 8;
389
390 //
391 // done
392 //
393 return STATUS_SUCCESS;
394 }
395
396 //-----------------------------------------------------------------------------------------
397 NTSTATUS
398 CHubController::HandlePnp(
399 IN PDEVICE_OBJECT DeviceObject,
400 IN OUT PIRP Irp)
401 {
402 PIO_STACK_LOCATION IoStack;
403 PCOMMON_DEVICE_EXTENSION DeviceExtension;
404 PDEVICE_CAPABILITIES DeviceCapabilities;
405 PPNP_BUS_INFORMATION BusInformation;
406 PDEVICE_RELATIONS DeviceRelations;
407 NTSTATUS Status;
408 ULONG Index = 0, Length;
409 USHORT VendorID, DeviceID;
410 ULONG HiSpeed, NumPorts;
411 WCHAR Buffer[300];
412 LPWSTR DeviceName;
413
414 //
415 // get device extension
416 //
417 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
418
419 //
420 // sanity check
421 //
422 ASSERT(DeviceExtension->IsFDO == FALSE);
423
424 //
425 // get current stack location
426 //
427 IoStack = IoGetCurrentIrpStackLocation(Irp);
428
429 switch(IoStack->MinorFunction)
430 {
431 case IRP_MN_START_DEVICE:
432 {
433 DPRINT("CHubController::HandlePnp IRP_MN_START_DEVICE\n");
434 //
435 // register device interface
436 //
437 Status = SetDeviceInterface(TRUE);
438 break;
439 }
440 case IRP_MN_QUERY_STOP_DEVICE:
441 case IRP_MN_QUERY_REMOVE_DEVICE:
442 {
443 //
444 // sure
445 //
446 Status = STATUS_SUCCESS;
447 break;
448 }
449 case IRP_MN_QUERY_ID:
450 {
451 DPRINT("CHubController::HandlePnp IRP_MN_QUERY_ID Type %x\n", IoStack->Parameters.QueryId.IdType);
452
453 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
454 {
455 if (m_Hardware)
456 {
457 //
458 // query device id
459 //
460 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
461
462 if (HiSpeed == 0x200)
463 {
464 //
465 // USB 2.0 hub
466 //
467 swprintf(Buffer, L"USB\\ROOT_HUB20");
468 }
469 else
470 {
471 //
472 // USB 1.1 hub
473 //
474 swprintf(Buffer, L"USB\\ROOT_HUB");
475 }
476
477 DPRINT("Name %S\n", Buffer);
478
479 //
480 // calculate length
481 //
482 Length = (wcslen(Buffer) + 1);
483
484 //
485 // allocate buffer
486 //
487 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_USBOHCI);
488
489 if (!DeviceName)
490 {
491 //
492 // no memory
493 //
494 Status = STATUS_INSUFFICIENT_RESOURCES;
495 break;
496 }
497
498 //
499 // copy device name
500 //
501 wcscpy(DeviceName, Buffer);
502
503 //
504 // store result
505 //
506 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
507 Status = STATUS_SUCCESS;
508 break;
509 }
510 Status = STATUS_UNSUCCESSFUL;
511 PC_ASSERT(0);
512 break;
513 }
514
515 if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
516 {
517 if (m_Hardware)
518 {
519 //
520 // query device id
521 //
522 Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed);
523
524 if (!NT_SUCCESS(Status))
525 {
526 DPRINT1("CHubController::HandlePnp> failed to get hardware id %x\n", Status);
527 VendorID = 0x8086;
528 DeviceID = 0x3A37;
529 }
530
531 if (HiSpeed == 0x200)
532 {
533 //
534 // USB 2.0 hub
535 //
536 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
537 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID, DeviceID) + 1;
538 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
539 }
540 else
541 {
542 //
543 // USB 1.1 hub
544 //
545 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1;
546 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID, DeviceID) + 1;
547 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB") + 1;
548 }
549
550 Buffer[Index] = UNICODE_NULL;
551 Index++;
552
553
554 DPRINT("Name %S\n", Buffer);
555
556 //
557 // allocate buffer
558 //
559 DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Index * sizeof(WCHAR), TAG_USBOHCI);
560
561 if (!DeviceName)
562 {
563 //
564 // no memory
565 //
566 Status = STATUS_INSUFFICIENT_RESOURCES;
567 break;
568 }
569
570 //
571 // copy device name
572 //
573 RtlMoveMemory(DeviceName, Buffer, Index * sizeof(WCHAR));
574
575 //
576 // store result
577 //
578 Irp->IoStatus.Information = (ULONG_PTR)DeviceName;
579 Status = STATUS_SUCCESS;
580 break;
581 }
582 }
583 Status = STATUS_SUCCESS;
584 break;
585 }
586 case IRP_MN_QUERY_CAPABILITIES:
587 {
588 DPRINT("CHubController::HandlePnp IRP_MN_QUERY_CAPABILITIES\n");
589
590 DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
591
592 DeviceCapabilities->LockSupported = FALSE;
593 DeviceCapabilities->EjectSupported = FALSE;
594 DeviceCapabilities->Removable = FALSE;
595 DeviceCapabilities->DockDevice = FALSE;
596 DeviceCapabilities->UniqueID = FALSE;
597 DeviceCapabilities->SilentInstall = FALSE;
598 DeviceCapabilities->RawDeviceOK = FALSE;
599 DeviceCapabilities->SurpriseRemovalOK = FALSE;
600 DeviceCapabilities->Address = 0;
601 DeviceCapabilities->UINumber = 0;
602 DeviceCapabilities->DeviceD2 = 1;
603
604 /* FIXME */
605 DeviceCapabilities->HardwareDisabled = FALSE;
606 DeviceCapabilities->NoDisplayInUI = FALSE;
607 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
608 for (Index = 1; Index < PowerSystemMaximum; Index++)
609 DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
610 DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
611 DeviceCapabilities->D1Latency = 0;
612 DeviceCapabilities->D2Latency = 0;
613 DeviceCapabilities->D3Latency = 0;
614
615 Status = STATUS_SUCCESS;
616 break;
617 }
618 case IRP_MN_QUERY_INTERFACE:
619 {
620 DPRINT("CHubController::HandlePnp IRP_MN_QUERY_INTERFACE\n");
621
622 //
623 // handle device interface requests
624 //
625 Status = HandleQueryInterface(IoStack);
626 break;
627 }
628 case IRP_MN_REMOVE_DEVICE:
629 {
630 DPRINT("CHubController::HandlePnp IRP_MN_REMOVE_DEVICE\n");
631
632 //
633 // deactivate device interface for BUS PDO
634 //
635 SetDeviceInterface(FALSE);
636
637 //
638 // complete the request first
639 //
640 Irp->IoStatus.Status = STATUS_SUCCESS;
641 IoCompleteRequest(Irp, IO_NO_INCREMENT);
642
643 //
644 // now delete device
645 //
646 IoDeleteDevice(m_HubControllerDeviceObject);
647
648 //
649 // nullify pointer
650 //
651 m_HubControllerDeviceObject = 0;
652
653 //
654 // done
655 //
656 return STATUS_SUCCESS;
657 }
658 case IRP_MN_QUERY_DEVICE_RELATIONS:
659 {
660 DPRINT("CHubController::HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", IoStack->Parameters.QueryDeviceRelations.Type);
661
662 if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
663 {
664 //
665 // allocate device relations
666 //
667 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), TAG_USBOHCI);
668 if (!DeviceRelations)
669 {
670 //
671 // no memory
672 //
673 Status = STATUS_INSUFFICIENT_RESOURCES;
674 break;
675 }
676
677 //
678 // initialize device relations
679 //
680 DeviceRelations->Count = 1;
681 DeviceRelations->Objects[0] = DeviceObject;
682 ObReferenceObject(DeviceObject);
683
684 //
685 // done
686 //
687 Status = STATUS_SUCCESS;
688 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
689 }
690 else
691 {
692 //
693 // not handled
694 //
695 Status = Irp->IoStatus.Status;
696 }
697 break;
698 }
699 case IRP_MN_QUERY_BUS_INFORMATION:
700 {
701 DPRINT("CHubController::HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n");
702
703 //
704 // allocate buffer for bus information
705 //
706 BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
707 if (BusInformation)
708 {
709 //
710 // copy BUS guid
711 //
712 RtlMoveMemory(&BusInformation->BusTypeGuid, &GUID_BUS_TYPE_USB, sizeof(GUID));
713
714 //
715 // set bus type
716 //
717 BusInformation->LegacyBusType = PNPBus;
718 BusInformation->BusNumber = 0;
719
720 Status = STATUS_SUCCESS;
721 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
722 }
723 else
724 {
725 //
726 // no memory
727 //
728 Status = STATUS_INSUFFICIENT_RESOURCES;
729 }
730 break;
731 }
732 case IRP_MN_STOP_DEVICE:
733 {
734 DPRINT("CHubController::HandlePnp IRP_MN_STOP_DEVICE\n");
735 //
736 // stop device
737 //
738 Status = STATUS_SUCCESS;
739 break;
740 }
741 default:
742 {
743 //
744 // ignore request with default status
745 //
746 Status = Irp->IoStatus.Status;
747 break;
748 }
749 }
750
751 //
752 // complete request
753 //
754 Irp->IoStatus.Status = Status;
755 IoCompleteRequest(Irp, IO_NO_INCREMENT);
756
757 //
758 // done
759 //
760 return Status;
761 }
762
763 //-----------------------------------------------------------------------------------------
764 NTSTATUS
765 CHubController::HandlePower(
766 IN PDEVICE_OBJECT DeviceObject,
767 IN OUT PIRP Irp)
768 {
769 UNIMPLEMENTED
770 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
771 IoCompleteRequest(Irp, IO_NO_INCREMENT);
772 return STATUS_NOT_IMPLEMENTED;
773 }
774
775 //-----------------------------------------------------------------------------------------
776 NTSTATUS
777 CHubController::HandleIsochronousTransfer(
778 IN OUT PIRP Irp,
779 PURB Urb)
780 {
781 PUSBDEVICE UsbDevice;
782 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
783
784 //
785 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
786 //
787 EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbIsochronousTransfer.PipeHandle;
788
789 if (!EndPointDesc)
790 {
791 DPRINT1("No EndpointDesc\n");
792 Urb->UrbIsochronousTransfer.Hdr.Status = USBD_STATUS_INVALID_PIPE_HANDLE;
793 return STATUS_INVALID_PARAMETER;
794 }
795
796 //
797 // sanity checks
798 //
799 ASSERT(EndPointDesc);
800 ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS);
801
802 //
803 // check if this is a valid usb device handle
804 //
805 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
806 {
807 DPRINT1("HandleIsochronousTransfer invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
808
809 //
810 // invalid device handle
811 //
812 return STATUS_DEVICE_NOT_CONNECTED;
813 }
814
815 //
816 // get device
817 //
818 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
819
820 return UsbDevice->SubmitIrp(Irp);
821 }
822
823 //-----------------------------------------------------------------------------------------
824 NTSTATUS
825 CHubController::HandleBulkOrInterruptTransfer(
826 IN OUT PIRP Irp,
827 PURB Urb)
828 {
829 PUSBDEVICE UsbDevice;
830 PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
831 //
832 // First check if the request is for the Status Change Endpoint
833 //
834
835 //
836 // Is the Request for the root hub
837 //
838 if (Urb->UrbHeader.UsbdDeviceHandle == 0)
839 {
840 ASSERT(m_PendingSCEIrp == NULL);
841 if (QueryStatusChageEndpoint(Irp))
842 {
843 StatusChangeEndpointCallBack(this);
844 return STATUS_SUCCESS;
845 }
846
847 //
848 // Else pend the IRP, to be completed when a device connects or disconnects.
849 //
850 DPRINT("Pending SCE Irp\n");;
851 m_PendingSCEIrp = Irp;
852 IoMarkIrpPending(Irp);
853 return STATUS_PENDING;
854 }
855
856 //
857 // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
858 //
859 EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
860
861 //
862 // sanity checks
863 //
864 ASSERT(EndPointDesc);
865 ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK || (EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT);
866
867 //
868 // check if this is a valid usb device handle
869 //
870 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
871 {
872 DPRINT1("HandleBuldOrInterruptTransfer invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
873
874 //
875 // invalid device handle
876 //
877 return STATUS_DEVICE_NOT_CONNECTED;
878 }
879
880 //
881 // get device
882 //
883 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
884
885 return UsbDevice->SubmitIrp(Irp);
886 }
887
888 //-----------------------------------------------------------------------------------------
889 NTSTATUS
890 CHubController::HandleClassOther(
891 IN OUT PIRP Irp,
892 PURB Urb)
893 {
894 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
895 USHORT PortStatus = 0, PortChange = 0;
896 PUSHORT Buffer;
897 ULONG NumPort;
898 ULONG PortId;
899
900 DPRINT("CHubController::HandleClassOther> Request %x Value %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value);
901
902 //
903 // get number of ports available
904 //
905 Status = m_Hardware->GetDeviceDetails(NULL, NULL, &NumPort, NULL);
906 PC_ASSERT(Status == STATUS_SUCCESS);
907
908 //
909 // sanity check
910 //
911 PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < (USHORT)NumPort);
912
913 //
914 // port range reported start from 1 -n
915 // convert back port id so it matches the hardware
916 //
917 PortId = Urb->UrbControlVendorClassRequest.Index - 1;
918
919 //
920 // check request code
921 //
922 switch(Urb->UrbControlVendorClassRequest.Request)
923 {
924 case USB_REQUEST_GET_STATUS:
925 {
926 //
927 // sanity check
928 //
929 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength == sizeof(USHORT) * 2);
930 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
931
932 //
933 // get port status
934 //
935 Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange);
936
937 if (NT_SUCCESS(Status))
938 {
939 //
940 // request contains buffer of 2 ushort which are used from submitting port status and port change status
941 //
942 DPRINT("PortId %x PortStatus %x PortChange %x\n", PortId, PortStatus, PortChange);
943 Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer;
944
945 //
946 // store status, then port change
947 //
948 *Buffer = PortStatus;
949 Buffer++;
950 *Buffer = PortChange;
951 }
952
953 //
954 // done
955 //
956 break;
957 }
958 case USB_REQUEST_CLEAR_FEATURE:
959 {
960 switch (Urb->UrbControlVendorClassRequest.Value)
961 {
962 case C_PORT_CONNECTION:
963 Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION);
964 break;
965 case C_PORT_RESET:
966 Status= m_Hardware->ClearPortStatus(PortId, C_PORT_RESET);
967 break;
968 default:
969 DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
970 break;
971 }
972
973 Status = STATUS_SUCCESS;
974 break;
975 }
976 case USB_REQUEST_SET_FEATURE:
977 {
978 //
979 // request set feature
980 //
981 switch(Urb->UrbControlVendorClassRequest.Value)
982 {
983 case PORT_ENABLE:
984 {
985 //
986 // port enable
987 //
988 Status = m_Hardware->SetPortFeature(PortId, PORT_ENABLE);
989 break;
990 }
991
992 case PORT_SUSPEND:
993 {
994 //
995 // set suspend port feature
996 //
997 Status = m_Hardware->SetPortFeature(PortId, PORT_SUSPEND);
998 break;
999 }
1000 case PORT_POWER:
1001 {
1002 //
1003 // set power feature on port
1004 //
1005 Status = m_Hardware->SetPortFeature(PortId, PORT_POWER);
1006 break;
1007 }
1008
1009 case PORT_RESET:
1010 {
1011 //
1012 // reset port feature
1013 //
1014 Status = m_Hardware->SetPortFeature(PortId, PORT_RESET);
1015 PC_ASSERT(Status == STATUS_SUCCESS);
1016 break;
1017 }
1018 default:
1019 DPRINT1("Unsupported request id %x\n", Urb->UrbControlVendorClassRequest.Value);
1020 PC_ASSERT(FALSE);
1021 }
1022 break;
1023 }
1024 default:
1025 DPRINT1("CHubController::HandleClassOther Unknown request code %x\n", Urb->UrbControlVendorClassRequest.Request);
1026 PC_ASSERT(0);
1027 Status = STATUS_INVALID_DEVICE_REQUEST;
1028 }
1029 return Status;
1030 }
1031
1032 //-----------------------------------------------------------------------------------------
1033 NTSTATUS
1034 CHubController::HandleSelectConfiguration(
1035 IN OUT PIRP Irp,
1036 PURB Urb)
1037 {
1038 PUSBDEVICE UsbDevice;
1039 PUSBD_INTERFACE_INFORMATION InterfaceInfo;
1040
1041 //
1042 // is the request for the Root Hub
1043 //
1044 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1045 {
1046 //
1047 // FIXME: support setting device to unconfigured state
1048 //
1049 PC_ASSERT(Urb->UrbSelectConfiguration.ConfigurationDescriptor);
1050
1051 //
1052 // set device handle
1053 //
1054 Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)&ROOTHUB2_CONFIGURATION_DESCRIPTOR;
1055
1056 //
1057 // copy interface info
1058 //
1059 InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
1060
1061 InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&ROOTHUB2_INTERFACE_DESCRIPTOR;
1062 InterfaceInfo->Class = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceClass;
1063 InterfaceInfo->SubClass = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceSubClass;
1064 InterfaceInfo->Protocol = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceProtocol;
1065 InterfaceInfo->Reserved = 0;
1066
1067 //
1068 // sanity check
1069 //
1070 PC_ASSERT(InterfaceInfo->NumberOfPipes == 1);
1071
1072 //
1073 // copy pipe info
1074 //
1075 InterfaceInfo->Pipes[0].MaximumPacketSize = ROOTHUB2_ENDPOINT_DESCRIPTOR.wMaxPacketSize;
1076 InterfaceInfo->Pipes[0].EndpointAddress = ROOTHUB2_ENDPOINT_DESCRIPTOR.bEndpointAddress;
1077 InterfaceInfo->Pipes[0].Interval = ROOTHUB2_ENDPOINT_DESCRIPTOR.bInterval;
1078 InterfaceInfo->Pipes[0].PipeType = (USBD_PIPE_TYPE)(ROOTHUB2_ENDPOINT_DESCRIPTOR.bmAttributes & USB_ENDPOINT_TYPE_MASK);
1079 InterfaceInfo->Pipes[0].PipeHandle = (PVOID)&ROOTHUB2_ENDPOINT_DESCRIPTOR;
1080
1081 return STATUS_SUCCESS;
1082 }
1083 else
1084 {
1085 //
1086 // check if this is a valid usb device handle
1087 //
1088 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1089 {
1090 DPRINT1("HandleSelectConfiguration invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1091
1092 //
1093 // invalid device handle
1094 //
1095 return STATUS_DEVICE_NOT_CONNECTED;
1096 }
1097
1098 //
1099 // get device
1100 //
1101 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1102
1103 //
1104 // select configuration
1105 //
1106 return UsbDevice->SelectConfiguration(Urb->UrbSelectConfiguration.ConfigurationDescriptor, &Urb->UrbSelectConfiguration.Interface, &Urb->UrbSelectConfiguration.ConfigurationHandle);
1107 }
1108 }
1109
1110 //-----------------------------------------------------------------------------------------
1111 NTSTATUS
1112 CHubController::HandleSelectInterface(
1113 IN OUT PIRP Irp,
1114 PURB Urb)
1115 {
1116 PUSBDEVICE UsbDevice;
1117
1118 //
1119 // sanity check
1120 //
1121 PC_ASSERT(Urb->UrbSelectInterface.ConfigurationHandle);
1122
1123 //
1124 // is the request for the Root Hub
1125 //
1126 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1127 {
1128 //
1129 // no op for root hub
1130 //
1131 return STATUS_SUCCESS;
1132 }
1133 else
1134 {
1135 //
1136 // check if this is a valid usb device handle
1137 //
1138 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1139 {
1140 DPRINT1("HandleSelectInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1141
1142 //
1143 // invalid device handle
1144 //
1145 return STATUS_DEVICE_NOT_CONNECTED;
1146 }
1147
1148 //
1149 // get device
1150 //
1151 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1152
1153 //
1154 // select interface
1155 //
1156 return UsbDevice->SelectInterface(Urb->UrbSelectInterface.ConfigurationHandle, &Urb->UrbSelectInterface.Interface);
1157 }
1158 }
1159
1160 //-----------------------------------------------------------------------------------------
1161 NTSTATUS
1162 CHubController::HandleGetStatusFromDevice(
1163 IN OUT PIRP Irp,
1164 PURB Urb)
1165 {
1166 PUSHORT DeviceStatus;
1167 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1168 NTSTATUS Status;
1169 PUSBDEVICE UsbDevice;
1170
1171 //
1172 // sanity checks
1173 //
1174 PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
1175 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
1176 PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
1177
1178 //
1179 // get status buffer
1180 //
1181 DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
1182
1183
1184 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1185 {
1186 //
1187 // FIXME need more flags ?
1188 //
1189 *DeviceStatus = USB_PORT_STATUS_CONNECT;
1190 return STATUS_SUCCESS;
1191 }
1192
1193 //
1194 // check if this is a valid usb device handle
1195 //
1196 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1197 {
1198 DPRINT1("HandleGetStatusFromDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1199
1200 //
1201 // invalid device handle
1202 //
1203 return STATUS_DEVICE_NOT_CONNECTED;
1204 }
1205
1206 //
1207 // get device
1208 //
1209 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1210
1211
1212 //
1213 // generate setup packet
1214 //
1215 CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
1216 CtrlSetup.wValue.LowByte = 0;
1217 CtrlSetup.wValue.HiByte = 0;
1218 CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index;
1219 CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
1220 CtrlSetup.bmRequestType.B = 0x80;
1221
1222 //
1223 // submit setup packet
1224 //
1225 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1226 ASSERT(Status == STATUS_SUCCESS);
1227 DPRINT("CHubController::HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus);
1228
1229 //
1230 // done
1231 //
1232 return Status;
1233 }
1234
1235 //-----------------------------------------------------------------------------------------
1236 NTSTATUS
1237 CHubController::HandleClassDevice(
1238 IN OUT PIRP Irp,
1239 IN OUT PURB Urb)
1240 {
1241 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1242 PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
1243 ULONG PortCount, Dummy2;
1244 USHORT Dummy1;
1245 PUSBDEVICE UsbDevice;
1246 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1247
1248 DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
1249
1250 //
1251 // check class request type
1252 //
1253 switch(Urb->UrbControlVendorClassRequest.Request)
1254 {
1255 case USB_REQUEST_GET_STATUS:
1256 {
1257 //
1258 // check if this is a valid usb device handle
1259 //
1260 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1261 {
1262 DPRINT1("USB_REQUEST_GET_STATUS invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1263
1264 //
1265 // invalid device handle
1266 //
1267 return STATUS_DEVICE_NOT_CONNECTED;
1268 }
1269
1270 //
1271 // get device
1272 //
1273 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1274
1275
1276 //
1277 // generate setup packet
1278 //
1279 CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
1280 CtrlSetup.wValue.LowByte = Urb->UrbControlVendorClassRequest.Index;
1281 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1282 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1283 CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
1284 CtrlSetup.bmRequestType.B = 0xA0;
1285
1286 //
1287 // submit setup packet
1288 //
1289 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1290 ASSERT(Status == STATUS_SUCCESS);
1291 break;
1292 }
1293 case USB_REQUEST_GET_DESCRIPTOR:
1294 {
1295 switch (Urb->UrbControlVendorClassRequest.Value >> 8)
1296 {
1297 case USB_DEVICE_CLASS_RESERVED: // FALL THROUGH
1298 case USB_DEVICE_CLASS_HUB:
1299 {
1300 //
1301 // sanity checks
1302 //
1303 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
1304 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength >= sizeof(USB_HUB_DESCRIPTOR));
1305
1306 //
1307 // get hub descriptor
1308 //
1309 UsbHubDescriptor = (PUSB_HUB_DESCRIPTOR)Urb->UrbControlVendorClassRequest.TransferBuffer;
1310
1311 //
1312 // one hub is handled
1313 //
1314 UsbHubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
1315 Urb->UrbControlVendorClassRequest.TransferBufferLength = sizeof(USB_HUB_DESCRIPTOR);
1316
1317 //
1318 // type should 0x29 according to msdn
1319 //
1320 UsbHubDescriptor->bDescriptorType = 0x29;
1321
1322 //
1323 // get port count
1324 //
1325 Status = m_Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &PortCount, &Dummy2);
1326 PC_ASSERT(Status == STATUS_SUCCESS);
1327
1328 //
1329 // FIXME: retrieve values
1330 //
1331 UsbHubDescriptor->bNumberOfPorts = (UCHAR)PortCount;
1332 UsbHubDescriptor->wHubCharacteristics = 0x00;
1333 UsbHubDescriptor->bPowerOnToPowerGood = 0x01;
1334 UsbHubDescriptor->bHubControlCurrent = 0x00;
1335
1336 //
1337 // done
1338 //
1339 Status = STATUS_SUCCESS;
1340 break;
1341 }
1342 default:
1343 DPRINT1("CHubController::HandleClassDevice Class %x not implemented\n", Urb->UrbControlVendorClassRequest.Value >> 8);
1344 break;
1345 }
1346 break;
1347 }
1348 default:
1349 DPRINT1("CHubController::HandleClassDevice Type %x not implemented\n", Urb->UrbControlVendorClassRequest.Request);
1350 }
1351
1352 return Status;
1353 }
1354
1355 //-----------------------------------------------------------------------------------------
1356 NTSTATUS
1357 CHubController::HandleGetDescriptorFromInterface(
1358 IN OUT PIRP Irp,
1359 IN OUT PURB Urb)
1360 {
1361 PUSBDEVICE UsbDevice;
1362 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1363 NTSTATUS Status;
1364
1365 //
1366 // sanity check
1367 //
1368 ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
1369 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1370
1371 //
1372 // check if this is a valid usb device handle
1373 //
1374 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1375 {
1376 DPRINT1("HandleGetDescriptorFromInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1377
1378 //
1379 // invalid device handle
1380 //
1381 return STATUS_DEVICE_NOT_CONNECTED;
1382 }
1383
1384 //
1385 // get device
1386 //
1387 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1388
1389 //
1390 // generate setup packet
1391 //
1392 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1393 CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1394 CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1395 CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1396 CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1397 CtrlSetup.bmRequestType.B = 0x81;
1398
1399 //
1400 // submit setup packet
1401 //
1402 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1403 ASSERT(Status == STATUS_SUCCESS);
1404
1405 //
1406 // done
1407 //
1408 return Status;
1409 }
1410
1411 //-----------------------------------------------------------------------------------------
1412 NTSTATUS
1413 CHubController::HandleGetDescriptor(
1414 IN OUT PIRP Irp,
1415 IN OUT PURB Urb)
1416 {
1417 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1418 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
1419 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1420 PUCHAR Buffer;
1421 PUSBDEVICE UsbDevice;
1422 ULONG Length;
1423
1424 DPRINT("CHubController::HandleGetDescriptor\n");
1425
1426 //
1427 // check descriptor type
1428 //
1429 switch(Urb->UrbControlDescriptorRequest.DescriptorType)
1430 {
1431 case USB_DEVICE_DESCRIPTOR_TYPE:
1432 {
1433 //
1434 // sanity check
1435 //
1436 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1437 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1438
1439 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1440 {
1441 //
1442 // copy root hub device descriptor
1443 //
1444 RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
1445 Status = STATUS_SUCCESS;
1446 }
1447 else
1448 {
1449 //
1450 // check if this is a valid usb device handle
1451 //
1452 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1453 {
1454 DPRINT1("HandleGetDescriptor invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1455
1456 //
1457 // invalid device handle
1458 //
1459 return STATUS_DEVICE_NOT_CONNECTED;
1460 }
1461
1462 //
1463 // get device
1464 //
1465 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1466
1467 //
1468 // retrieve device descriptor from device
1469 //
1470 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer);
1471 Status = STATUS_SUCCESS;
1472 }
1473 break;
1474 }
1475 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
1476 {
1477 //
1478 // sanity checks
1479 //
1480 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1481 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
1482
1483 if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
1484 {
1485 //
1486 // request is for the root bus controller
1487 //
1488 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR));
1489
1490 //
1491 // get configuration descriptor, very retarded!
1492 //
1493 ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer;
1494
1495 //
1496 // check if buffer can hold interface and endpoint descriptor
1497 //
1498 if (ConfigurationDescriptor->wTotalLength > Urb->UrbControlDescriptorRequest.TransferBufferLength)
1499 {
1500 //
1501 // buffer too small
1502 //
1503 Status = STATUS_SUCCESS;
1504 ASSERT(FALSE);
1505 break;
1506 }
1507
1508 //
1509 // copy interface descriptor template
1510 //
1511 Buffer = (PUCHAR)(ConfigurationDescriptor + 1);
1512 RtlCopyMemory(Buffer, &ROOTHUB2_INTERFACE_DESCRIPTOR, sizeof(USB_INTERFACE_DESCRIPTOR));
1513
1514 //
1515 // copy end point descriptor template
1516 //
1517 Buffer += sizeof(USB_INTERFACE_DESCRIPTOR);
1518 RtlCopyMemory(Buffer, &ROOTHUB2_ENDPOINT_DESCRIPTOR, sizeof(USB_ENDPOINT_DESCRIPTOR));
1519
1520 //
1521 // done
1522 //
1523 Status = STATUS_SUCCESS;
1524
1525 }
1526 else
1527 {
1528 //
1529 // check if this is a valid usb device handle
1530 //
1531 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1532 {
1533 DPRINT1("USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1534
1535 //
1536 // invalid device handle
1537 //
1538 return STATUS_DEVICE_NOT_CONNECTED;
1539 }
1540
1541 //
1542 // get device
1543 //
1544 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1545
1546 if (sizeof(USB_CONFIGURATION_DESCRIPTOR) > Urb->UrbControlDescriptorRequest.TransferBufferLength)
1547 {
1548 //
1549 // buffer too small
1550 //
1551 Urb->UrbControlDescriptorRequest.TransferBufferLength = UsbDevice->GetConfigurationDescriptorsLength();
1552
1553 //
1554 // bail out
1555 //
1556 Status = STATUS_SUCCESS;
1557 break;
1558 }
1559
1560 //
1561 // perform work in IUSBDevice
1562 //
1563 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength, &Length);
1564
1565 //
1566 // store result size
1567 //
1568 Urb->UrbControlDescriptorRequest.TransferBufferLength = Length;
1569 Status = STATUS_SUCCESS;
1570 }
1571 break;
1572 }
1573 case USB_STRING_DESCRIPTOR_TYPE:
1574 {
1575 //
1576 // sanity check
1577 //
1578 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
1579 PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
1580
1581 //
1582 // check if this is a valid usb device handle
1583 //
1584 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1585 {
1586 DPRINT1("USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1587
1588 //
1589 // invalid device handle
1590 //
1591 return STATUS_DEVICE_NOT_CONNECTED;
1592 }
1593
1594 //
1595 // get device
1596 //
1597 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1598
1599 //
1600 // generate setup packet
1601 //
1602 CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1603 CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
1604 CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
1605 CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
1606 CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
1607 CtrlSetup.bmRequestType.B = 0x80;
1608
1609 //
1610 // submit setup packet
1611 //
1612 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
1613 break;
1614 }
1615 default:
1616 DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", Urb->UrbControlDescriptorRequest.DescriptorType);
1617 break;
1618 }
1619
1620 //
1621 // done
1622 //
1623 return Status;
1624 }
1625
1626 //-----------------------------------------------------------------------------------------
1627 NTSTATUS
1628 CHubController::HandleClassEndpoint(
1629 IN OUT PIRP Irp,
1630 IN OUT PURB Urb)
1631 {
1632 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1633 NTSTATUS Status;
1634 PUSBDEVICE UsbDevice;
1635
1636 //
1637 // sanity check
1638 //
1639 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
1640 PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1641 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1642
1643 //
1644 // check if this is a valid usb device handle
1645 //
1646 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1647 {
1648 DPRINT1("HandleClassEndpoint invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1649
1650 //
1651 // invalid device handle
1652 //
1653 return STATUS_DEVICE_NOT_CONNECTED;
1654 }
1655
1656 //
1657 // get device
1658 //
1659 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1660
1661
1662 DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
1663 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
1664 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
1665 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
1666 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1667 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
1668 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1669 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
1670 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
1671
1672 //
1673 // initialize setup packet
1674 //
1675 CtrlSetup.bmRequestType.B = 0x22; //FIXME: Const.
1676 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1677 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1678 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1679 CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
1680
1681 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1682 {
1683 //
1684 // data direction is device to host
1685 //
1686 CtrlSetup.bmRequestType.B |= 0x80;
1687 }
1688
1689
1690 //
1691 // issue request
1692 //
1693 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1694
1695 //
1696 // assert on failure
1697 //
1698 PC_ASSERT(NT_SUCCESS(Status));
1699
1700
1701 //
1702 // done
1703 //
1704 return Status;
1705 }
1706
1707 NTSTATUS
1708 CHubController::HandleSyncResetAndClearStall(
1709 IN OUT PIRP Irp,
1710 IN OUT PURB Urb)
1711 {
1712 NTSTATUS Status = STATUS_SUCCESS;
1713 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1714 ULONG Type;
1715
1716 //
1717 // sanity check
1718 //
1719 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1720 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1721 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
1722
1723 //
1724 // check if this is a valid usb device handle
1725 //
1726 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1727 {
1728 DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1729
1730 //
1731 // invalid device handle
1732 //
1733 return STATUS_DEVICE_NOT_CONNECTED;
1734 }
1735
1736 //
1737 // get endpoint descriptor
1738 //
1739 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
1740
1741 //
1742 // get type
1743 //
1744 Type = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
1745 if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS)
1746 {
1747 //
1748 // clear stall
1749 //
1750 Status = HandleClearStall(Irp, Urb);
1751 }
1752 DPRINT1("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status);
1753
1754 //
1755 // FIXME reset data toggle
1756 //
1757
1758 //
1759 // done
1760 //
1761 return Status;
1762 }
1763
1764 NTSTATUS
1765 CHubController::HandleAbortPipe(
1766 IN OUT PIRP Irp,
1767 IN OUT PURB Urb)
1768 {
1769 NTSTATUS Status;
1770 PUSBDEVICE UsbDevice;
1771 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1772
1773 //
1774 // sanity check
1775 //
1776 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1777 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1778 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
1779
1780 //
1781 // check if this is a valid usb device handle
1782 //
1783 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1784 {
1785 DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1786
1787 //
1788 // invalid device handle
1789 //
1790 return STATUS_DEVICE_NOT_CONNECTED;
1791 }
1792
1793 //
1794 // get endpoint descriptor
1795 //
1796 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
1797
1798 //
1799 // get device
1800 //
1801 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1802
1803
1804 //
1805 // issue request
1806 //
1807 Status = UsbDevice->AbortPipe(EndpointDescriptor);
1808 DPRINT1("URB_FUNCTION_ABORT_PIPE Status %x\n", Status);
1809
1810 //
1811 // done
1812 //
1813 return Status;
1814 }
1815
1816
1817 //-----------------------------------------------------------------------------------------
1818 NTSTATUS
1819 CHubController::HandleClearStall(
1820 IN OUT PIRP Irp,
1821 IN OUT PURB Urb)
1822 {
1823 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1824 NTSTATUS Status;
1825 PUSBDEVICE UsbDevice;
1826 PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
1827
1828
1829 //
1830 // sanity check
1831 //
1832 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1833 PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
1834 PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
1835
1836 //
1837 // check if this is a valid usb device handle
1838 //
1839 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1840 {
1841 DPRINT1("HandleClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1842
1843 //
1844 // invalid device handle
1845 //
1846 return STATUS_DEVICE_NOT_CONNECTED;
1847 }
1848
1849 //
1850 // get endpoint descriptor
1851 //
1852 EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
1853
1854 //
1855 // get device
1856 //
1857 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1858 DPRINT1("URB_FUNCTION_SYNC_CLEAR_STALL\n");
1859
1860 //
1861 // initialize setup packet
1862 //
1863 CtrlSetup.bmRequestType.B = 0x02;
1864 CtrlSetup.bRequest = USB_REQUEST_CLEAR_FEATURE;
1865 CtrlSetup.wValue.W = USB_FEATURE_ENDPOINT_STALL;
1866 CtrlSetup.wIndex.W = EndpointDescriptor->bEndpointAddress;
1867 CtrlSetup.wLength = 0;
1868 CtrlSetup.wValue.W = 0;
1869
1870 //
1871 // issue request
1872 //
1873 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0);
1874
1875 DPRINT1("URB_FUNCTION_CLEAR_STALL Status %x\n", Status);
1876
1877 //
1878 // done
1879 //
1880 return Status;
1881 }
1882
1883
1884 //-----------------------------------------------------------------------------------------
1885 NTSTATUS
1886 CHubController::HandleClassInterface(
1887 IN OUT PIRP Irp,
1888 IN OUT PURB Urb)
1889 {
1890 USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1891 NTSTATUS Status;
1892 PUSBDEVICE UsbDevice;
1893
1894 //
1895 // sanity check
1896 //
1897 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1898 //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
1899 PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
1900
1901 //
1902 // check if this is a valid usb device handle
1903 //
1904 if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
1905 {
1906 DPRINT1("HandleClassInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
1907
1908 //
1909 // invalid device handle
1910 //
1911 return STATUS_DEVICE_NOT_CONNECTED;
1912 }
1913
1914 //
1915 // get device
1916 //
1917 UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
1918
1919
1920 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
1921 DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
1922 DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
1923 DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
1924 DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
1925 DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
1926 DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
1927 DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
1928 DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
1929
1930 //
1931 // initialize setup packet
1932 //
1933 CtrlSetup.bmRequestType.B = 0x21;
1934 CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
1935 CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
1936 CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
1937 CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
1938
1939 if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1940 {
1941 //
1942 // data direction is device to host
1943 //
1944 CtrlSetup.bmRequestType.B |= 0x80;
1945 }
1946
1947 //
1948 // issue request
1949 //
1950 Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
1951
1952 //
1953 // assert on failure
1954 //
1955 if (!NT_SUCCESS(Status))
1956 {
1957 //
1958 // display error
1959 //
1960 DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb->UrbHeader.Status);
1961 }
1962
1963 //
1964 // done
1965 //
1966 return Status;
1967 }
1968
1969 //-----------------------------------------------------------------------------------------
1970 NTSTATUS
1971 CHubController::HandleDeviceControl(
1972 IN PDEVICE_OBJECT DeviceObject,
1973 IN OUT PIRP Irp)
1974 {
1975 PIO_STACK_LOCATION IoStack;
1976 PCOMMON_DEVICE_EXTENSION DeviceExtension;
1977 PURB Urb;
1978 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
1979
1980 //
1981 // get current stack location
1982 //
1983 IoStack = IoGetCurrentIrpStackLocation(Irp);
1984
1985 //
1986 // get device extension
1987 //
1988 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1989
1990 //
1991 // determine which request should be performed
1992 //
1993 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
1994 {
1995 case IOCTL_INTERNAL_USB_SUBMIT_URB:
1996 {
1997 //
1998 // get urb
1999 //
2000 Urb = (PURB)IoStack->Parameters.Others.Argument1;
2001 PC_ASSERT(Urb);
2002
2003 switch (Urb->UrbHeader.Function)
2004 {
2005 case URB_FUNCTION_SYNC_RESET_PIPE:
2006 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
2007 Status = HandleSyncResetAndClearStall(Irp, Urb);
2008 break;
2009 case URB_FUNCTION_ABORT_PIPE:
2010 Status = HandleAbortPipe(Irp, Urb);
2011 break;
2012 case URB_FUNCTION_SYNC_CLEAR_STALL:
2013 Status = HandleClearStall(Irp, Urb);
2014 break;
2015 case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
2016 Status = HandleGetDescriptorFromInterface(Irp, Urb);
2017 break;
2018 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
2019 Status = HandleGetDescriptor(Irp, Urb);
2020 break;
2021 case URB_FUNCTION_CLASS_DEVICE:
2022 Status = HandleClassDevice(Irp, Urb);
2023 break;
2024 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
2025 Status = HandleGetStatusFromDevice(Irp, Urb);
2026 break;
2027 case URB_FUNCTION_SELECT_CONFIGURATION:
2028 Status = HandleSelectConfiguration(Irp, Urb);
2029 break;
2030 case URB_FUNCTION_SELECT_INTERFACE:
2031 Status = HandleSelectInterface(Irp, Urb);
2032 break;
2033 case URB_FUNCTION_CLASS_OTHER:
2034 Status = HandleClassOther(Irp, Urb);
2035 break;
2036 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
2037 Status = HandleBulkOrInterruptTransfer(Irp, Urb);
2038 break;
2039 case URB_FUNCTION_ISOCH_TRANSFER:
2040 Status = HandleIsochronousTransfer(Irp, Urb);
2041 break;
2042 case URB_FUNCTION_CLASS_INTERFACE:
2043 Status = HandleClassInterface(Irp, Urb);
2044 break;
2045 case URB_FUNCTION_CLASS_ENDPOINT:
2046 Status = HandleClassEndpoint(Irp, Urb);
2047 break;
2048 default:
2049 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
2050 break;
2051 }
2052 //
2053 // request completed
2054 //
2055 break;
2056 }
2057 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
2058 {
2059 DPRINT("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", this);
2060
2061 if (IoStack->Parameters.Others.Argument1)
2062 {
2063 //
2064 // store object as device handle
2065 //
2066 *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this;
2067 Status = STATUS_SUCCESS;
2068 }
2069 else
2070 {
2071 //
2072 // mis-behaving hub driver
2073 //
2074 Status = STATUS_INVALID_DEVICE_REQUEST;
2075 }
2076
2077 //
2078 // request completed
2079 //
2080 break;
2081 }
2082 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
2083 {
2084 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
2085
2086 //
2087 // this is the first request send, it delivers the PDO to the caller
2088 //
2089 if (IoStack->Parameters.Others.Argument1)
2090 {
2091 //
2092 // store root hub pdo object
2093 //
2094 *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject;
2095 }
2096
2097 if (IoStack->Parameters.Others.Argument2)
2098 {
2099 //
2100 // documentation claims to deliver the hcd controller object, although it is wrong
2101 //
2102 *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject;
2103 }
2104
2105 //
2106 // request completed
2107 //
2108 Status = STATUS_SUCCESS;
2109 break;
2110 }
2111 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
2112 {
2113 DPRINT("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
2114
2115 //
2116 // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver
2117 // requests this ioctl to deliver the number of presents.
2118
2119 if (IoStack->Parameters.Others.Argument1)
2120 {
2121 //
2122 // FIXME / verify: there is only one hub
2123 //
2124 *(PULONG)IoStack->Parameters.Others.Argument1 = 1;
2125 }
2126
2127 //
2128 // request completed
2129 //
2130 Status = STATUS_SUCCESS;
2131 Irp->IoStatus.Information = sizeof(ULONG);
2132 break;
2133 }
2134 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
2135 {
2136 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n");
2137 Status = STATUS_SUCCESS;
2138 break;
2139 }
2140 default:
2141 {
2142 DPRINT1("HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n",
2143 IoStack->Parameters.DeviceIoControl.IoControlCode,
2144 IoStack->Parameters.DeviceIoControl.InputBufferLength,
2145 IoStack->Parameters.DeviceIoControl.OutputBufferLength);
2146 break;
2147 }
2148 }
2149 if (Status != STATUS_PENDING)
2150 {
2151 Irp->IoStatus.Status = Status;
2152 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2153 }
2154
2155 return Status;
2156 }
2157
2158 //-----------------------------------------------------------------------------------------
2159 PUSBHARDWAREDEVICE
2160 CHubController::GetUsbHardware()
2161 {
2162 return m_Hardware;
2163 }
2164
2165 //-----------------------------------------------------------------------------------------
2166 ULONG
2167 CHubController::AcquireDeviceAddress()
2168 {
2169 KIRQL OldLevel;
2170 ULONG DeviceAddress;
2171
2172 //
2173 // acquire device lock
2174 //
2175 KeAcquireSpinLock(&m_Lock, &OldLevel);
2176
2177 //
2178 // find address
2179 //
2180 DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0);
2181 if (DeviceAddress != MAXULONG)
2182 {
2183 //
2184 // reserve address
2185 //
2186 RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2187
2188 //
2189 // device addresses start from 0x1 - 0xFF
2190 //
2191 DeviceAddress++;
2192 }
2193
2194 //
2195 // release spin lock
2196 //
2197 KeReleaseSpinLock(&m_Lock, OldLevel);
2198
2199 //
2200 // return device address
2201 //
2202 return DeviceAddress;
2203 }
2204 //-----------------------------------------------------------------------------------------
2205 VOID
2206 CHubController::ReleaseDeviceAddress(
2207 ULONG DeviceAddress)
2208 {
2209 KIRQL OldLevel;
2210
2211 //
2212 // acquire device lock
2213 //
2214 KeAcquireSpinLock(&m_Lock, &OldLevel);
2215
2216 //
2217 // sanity check
2218 //
2219 PC_ASSERT(DeviceAddress != 0);
2220
2221 //
2222 // convert back to bit number
2223 //
2224 DeviceAddress--;
2225
2226 //
2227 // clear bit
2228 //
2229 RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1);
2230
2231 //
2232 // release lock
2233 //
2234 KeReleaseSpinLock(&m_Lock, OldLevel);
2235 }
2236 //-----------------------------------------------------------------------------------------
2237 NTSTATUS
2238 CHubController::RemoveUsbDevice(
2239 PUSBDEVICE UsbDevice)
2240 {
2241 PUSBDEVICE_ENTRY DeviceEntry;
2242 PLIST_ENTRY Entry;
2243 NTSTATUS Status = STATUS_UNSUCCESSFUL;
2244 KIRQL OldLevel;
2245
2246 //
2247 // acquire lock
2248 //
2249 KeAcquireSpinLock(&m_Lock, &OldLevel);
2250
2251 //
2252 // point to first entry
2253 //
2254 Entry = m_UsbDeviceList.Flink;
2255
2256 //
2257 // find matching entry
2258 //
2259 while(Entry != &m_UsbDeviceList)
2260 {
2261 //
2262 // get entry
2263 //
2264 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2265
2266 //
2267 // is it current entry
2268 //
2269 if (DeviceEntry->Device == UsbDevice)
2270 {
2271 //
2272 // remove entry
2273 //
2274 RemoveEntryList(Entry);
2275
2276 //
2277 // free entry
2278 //
2279 ExFreePoolWithTag(DeviceEntry, TAG_USBOHCI);
2280
2281 //
2282 // done
2283 //
2284 Status = STATUS_SUCCESS;
2285 break;
2286 }
2287
2288 //
2289 // goto next device
2290 //
2291 Entry = Entry->Flink;
2292 }
2293
2294 //
2295 // release lock
2296 //
2297 KeReleaseSpinLock(&m_Lock, OldLevel);
2298
2299 //
2300 // return result
2301 //
2302 return Status;
2303 }
2304 //-----------------------------------------------------------------------------------------
2305 BOOLEAN
2306 CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice)
2307 {
2308 PUSBDEVICE_ENTRY DeviceEntry;
2309 PLIST_ENTRY Entry;
2310 KIRQL OldLevel;
2311 BOOLEAN Result = FALSE;
2312
2313 //
2314 // acquire lock
2315 //
2316 KeAcquireSpinLock(&m_Lock, &OldLevel);
2317
2318 //
2319 // point to first entry
2320 //
2321 Entry = m_UsbDeviceList.Flink;
2322
2323 //
2324 // find matching entry
2325 //
2326 while(Entry != &m_UsbDeviceList)
2327 {
2328 //
2329 // get entry
2330 //
2331 DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry);
2332
2333 //
2334 // is it current entry
2335 //
2336 if (DeviceEntry->Device == UsbDevice)
2337 {
2338 //
2339 // device is valid
2340 //
2341 Result = TRUE;
2342 break;
2343 }
2344
2345 //
2346 // goto next device
2347 //
2348 Entry = Entry->Flink;
2349 }
2350
2351 //
2352 // release lock
2353 //
2354 KeReleaseSpinLock(&m_Lock, OldLevel);
2355
2356 //
2357 // return result
2358 //
2359 return Result;
2360
2361 }
2362
2363 //-----------------------------------------------------------------------------------------
2364 NTSTATUS
2365 CHubController::AddUsbDevice(
2366 PUSBDEVICE UsbDevice)
2367 {
2368 PUSBDEVICE_ENTRY DeviceEntry;
2369 KIRQL OldLevel;
2370
2371 //
2372 // allocate device entry
2373 //
2374 DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBOHCI);
2375 if (!DeviceEntry)
2376 {
2377 //
2378 // no memory
2379 //
2380 return STATUS_INSUFFICIENT_RESOURCES;
2381 }
2382
2383 //
2384 // initialize entry
2385 //
2386 DeviceEntry->Device = UsbDevice;
2387
2388 //
2389 // acquire lock
2390 //
2391 KeAcquireSpinLock(&m_Lock, &OldLevel);
2392
2393 //
2394 // insert entry
2395 //
2396 InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry);
2397
2398 //
2399 // release spin lock
2400 //
2401 KeReleaseSpinLock(&m_Lock, OldLevel);
2402
2403 //
2404 // done
2405 //
2406 return STATUS_SUCCESS;
2407 }
2408
2409 //-----------------------------------------------------------------------------------------
2410 VOID
2411 CHubController::SetNotification(
2412 PVOID CallbackContext,
2413 PRH_INIT_CALLBACK CallbackRoutine)
2414 {
2415 KIRQL OldLevel;
2416
2417 //
2418 // acquire hub controller lock
2419 //
2420 KeAcquireSpinLock(&m_Lock, &OldLevel);
2421
2422 //
2423 // now set the callback routine and context of the hub
2424 //
2425 m_HubCallbackContext = CallbackContext;
2426 m_HubCallbackRoutine = CallbackRoutine;
2427
2428 //
2429 // release hub controller lock
2430 //
2431 KeReleaseSpinLock(&m_Lock, OldLevel);
2432 }
2433
2434 //=================================================================================================
2435 //
2436 // Generic Interface functions
2437 //
2438 VOID
2439 USB_BUSIFFN
2440 USBI_InterfaceReference(
2441 PVOID BusContext)
2442 {
2443 CHubController * Controller = (CHubController*)BusContext;
2444
2445 DPRINT("USBH_InterfaceReference\n");
2446
2447 //
2448 // add reference
2449 //
2450 Controller->AddRef();
2451 }
2452
2453 VOID
2454 USB_BUSIFFN
2455 USBI_InterfaceDereference(
2456 PVOID BusContext)
2457 {
2458 CHubController * Controller = (CHubController*)BusContext;
2459
2460 DPRINT("USBH_InterfaceDereference\n");
2461
2462 //
2463 // release
2464 //
2465 Controller->Release();
2466 }
2467 //=================================================================================================
2468 //
2469 // USB Hub Interface functions
2470 //
2471 NTSTATUS
2472 USB_BUSIFFN
2473 USBHI_CreateUsbDevice(
2474 PVOID BusContext,
2475 PUSB_DEVICE_HANDLE *NewDevice,
2476 PUSB_DEVICE_HANDLE HubDeviceHandle,
2477 USHORT PortStatus,
2478 USHORT PortNumber)
2479 {
2480 PUSBDEVICE NewUsbDevice;
2481 CHubController * Controller;
2482 NTSTATUS Status;
2483
2484 DPRINT("USBHI_CreateUsbDevice PortStatus %x\n", PortStatus);
2485
2486 //
2487 // first get hub controller
2488 //
2489 Controller = (CHubController *)BusContext;
2490
2491 //
2492 // sanity check
2493 //
2494 PC_ASSERT(Controller);
2495 PC_ASSERT(BusContext == HubDeviceHandle);
2496
2497 //
2498 // now allocate usb device
2499 //
2500 Status = CreateUSBDevice(&NewUsbDevice);
2501
2502 //
2503 // check for success
2504 //
2505 if (!NT_SUCCESS(Status))
2506 {
2507 //
2508 // release controller
2509 //
2510 Controller->Release();
2511 DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status);
2512 return Status;
2513 }
2514
2515 //
2516 // now initialize device
2517 //
2518 Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(),PVOID(Controller), PortNumber, PortStatus);
2519
2520 //
2521 // check for success
2522 //
2523 if (!NT_SUCCESS(Status))
2524 {
2525 //
2526 // release usb device
2527 //
2528 NewUsbDevice->Release();
2529 DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status);
2530 return Status;
2531 }
2532
2533 //
2534 // insert into list
2535 //
2536 Status = Controller->AddUsbDevice(NewUsbDevice);
2537 //
2538 // check for success
2539 //
2540 if (!NT_SUCCESS(Status))
2541 {
2542 //
2543 // release usb device
2544 //
2545 NewUsbDevice->Release();
2546
2547 DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status);
2548 return Status;
2549 }
2550
2551 //
2552 // store the handle
2553 //
2554 *NewDevice = NewUsbDevice;
2555
2556 //
2557 // done
2558 //
2559 return STATUS_SUCCESS;
2560 }
2561
2562 NTSTATUS
2563 USB_BUSIFFN
2564 USBHI_InitializeUsbDevice(
2565 PVOID BusContext,
2566 PUSB_DEVICE_HANDLE DeviceHandle)
2567 {
2568 PUSBDEVICE UsbDevice;
2569 CHubController * Controller;
2570 ULONG DeviceAddress;
2571 NTSTATUS Status;
2572 ULONG Index = 0;
2573
2574 DPRINT("USBHI_InitializeUsbDevice\n");
2575
2576 //
2577 // first get controller
2578 //
2579 Controller = (CHubController *)BusContext;
2580 PC_ASSERT(Controller);
2581
2582 //
2583 // get device object
2584 //
2585 UsbDevice = (PUSBDEVICE)DeviceHandle;
2586 PC_ASSERT(UsbDevice);
2587
2588 //
2589 // validate device handle
2590 //
2591 if (!Controller->ValidateUsbDevice(UsbDevice))
2592 {
2593 DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle);
2594
2595 //
2596 // invalid device handle
2597 //
2598 return STATUS_DEVICE_NOT_CONNECTED;
2599 }
2600
2601 //
2602 // now reserve an address
2603 //
2604 DeviceAddress = Controller->AcquireDeviceAddress();
2605
2606 //
2607 // is the device address valid
2608 //
2609 if (DeviceAddress == MAXULONG)
2610 {
2611 //
2612 // failed to get an device address from the device address pool
2613 //
2614 DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n");
2615 return STATUS_DEVICE_DATA_ERROR;
2616 }
2617
2618 do
2619 {
2620 //
2621 // now set the device address
2622 //
2623 Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress);
2624
2625 if (NT_SUCCESS(Status))
2626 break;
2627
2628 }while(Index++ < 3 );
2629
2630 //
2631 // check for failure
2632 //
2633 if (!NT_SUCCESS(Status))
2634 {
2635 //
2636 // failed to set device address
2637 //
2638 DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status);
2639
2640 //
2641 // release address
2642 //
2643 Controller->ReleaseDeviceAddress(DeviceAddress);
2644
2645 //
2646 // return error
2647 //
2648 return STATUS_DEVICE_DATA_ERROR;
2649 }
2650
2651 //
2652 // done
2653 //
2654 return STATUS_SUCCESS;
2655 }
2656
2657 NTSTATUS
2658 USB_BUSIFFN
2659 USBHI_GetUsbDescriptors(
2660 PVOID BusContext,
2661 PUSB_DEVICE_HANDLE DeviceHandle,
2662 PUCHAR DeviceDescriptorBuffer,
2663 PULONG DeviceDescriptorBufferLength,
2664 PUCHAR ConfigDescriptorBuffer,
2665 PULONG ConfigDescriptorBufferLength)
2666 {
2667 PUSBDEVICE UsbDevice;
2668 CHubController * Controller;
2669
2670 DPRINT("USBHI_GetUsbDescriptors\n");
2671
2672 //
2673 // sanity check
2674 //
2675 PC_ASSERT(DeviceDescriptorBuffer);
2676 PC_ASSERT(DeviceDescriptorBufferLength);
2677 PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR));
2678 PC_ASSERT(ConfigDescriptorBufferLength);
2679 PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR));
2680
2681 //
2682 // first get controller
2683 //
2684 Controller = (CHubController *)BusContext;
2685 PC_ASSERT(Controller);
2686
2687
2688 //
2689 // get device object
2690 //
2691 UsbDevice = (PUSBDEVICE)DeviceHandle;
2692 PC_ASSERT(UsbDevice);
2693
2694 //
2695 // validate device handle
2696 //
2697 if (!Controller->ValidateUsbDevice(UsbDevice))
2698 {
2699 DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle);
2700
2701 //
2702 // invalid device handle
2703 //
2704 return STATUS_DEVICE_NOT_CONNECTED;
2705 }
2706
2707 //
2708 // get device descriptor
2709 //
2710 UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer);
2711
2712 //
2713 // store result length
2714 //
2715 *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
2716
2717 //
2718 // get configuration descriptor
2719 //
2720 UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength);
2721
2722 //
2723 // complete the request
2724 //
2725 return STATUS_SUCCESS;
2726 }
2727
2728 NTSTATUS
2729 USB_BUSIFFN
2730 USBHI_RemoveUsbDevice(
2731 PVOID BusContext,
2732 PUSB_DEVICE_HANDLE DeviceHandle,
2733 ULONG Flags)
2734 {
2735 PUSBDEVICE UsbDevice;
2736 CHubController * Controller;
2737 NTSTATUS Status;
2738
2739 DPRINT("USBHI_RemoveUsbDevice\n");
2740
2741 //
2742 // first get controller
2743 //
2744 Controller = (CHubController *)BusContext;
2745 PC_ASSERT(Controller);
2746
2747 //
2748 // get device object
2749 //
2750 UsbDevice = (PUSBDEVICE)DeviceHandle;
2751 PC_ASSERT(UsbDevice);
2752
2753 //
2754 // validate device handle
2755 //
2756 if (!Controller->ValidateUsbDevice(UsbDevice))
2757 {
2758 DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle);
2759
2760 //
2761 // invalid device handle
2762 //
2763 return STATUS_DEVICE_NOT_CONNECTED;
2764 }
2765
2766 //
2767 // check if there were flags passed
2768 //
2769 if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY)
2770 {
2771 //
2772 // ignore flags for now
2773 //
2774 return STATUS_SUCCESS;
2775 }
2776
2777 //
2778 // remove device
2779 //
2780 Status = Controller->RemoveUsbDevice(UsbDevice);
2781 if (!NT_SUCCESS(Status))
2782 {
2783 //
2784 // invalid device handle
2785 //
2786 DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice);
2787 PC_ASSERT(0);
2788 return STATUS_DEVICE_NOT_CONNECTED;
2789 }
2790
2791 //
2792 // release usb device
2793 //
2794 UsbDevice->Release();
2795
2796 //
2797 // done
2798 //
2799 return STATUS_SUCCESS;
2800 }
2801
2802 NTSTATUS
2803 USB_BUSIFFN
2804 USBHI_RestoreUsbDevice(
2805 PVOID BusContext,
2806 PUSB_DEVICE_HANDLE OldDeviceHandle,
2807 PUSB_DEVICE_HANDLE NewDeviceHandle)
2808 {
2809 PUSBDEVICE OldUsbDevice, NewUsbDevice;
2810 CHubController * Controller;
2811
2812 DPRINT("USBHI_RestoreUsbDevice\n");
2813
2814 //
2815 // first get controller
2816 //
2817 Controller = (CHubController *)BusContext;
2818 PC_ASSERT(Controller);
2819
2820 //
2821 // get device object
2822 //
2823 OldUsbDevice = (PUSBDEVICE)OldDeviceHandle;
2824 NewUsbDevice = (PUSBDEVICE)NewDeviceHandle;
2825 PC_ASSERT(OldUsbDevice);
2826 PC_ASSERT(NewDeviceHandle);
2827
2828 //
2829 // validate device handle
2830 //
2831 PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice));
2832 PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
2833
2834 DPRINT("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
2835 DPRINT("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
2836
2837 //
2838 // remove old device handle
2839 //
2840 USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0);
2841
2842 return STATUS_SUCCESS;
2843 }
2844
2845 NTSTATUS
2846 USB_BUSIFFN
2847 USBHI_QueryDeviceInformation(
2848 PVOID BusContext,
2849 PUSB_DEVICE_HANDLE DeviceHandle,
2850 PVOID DeviceInformationBuffer,
2851 ULONG DeviceInformationBufferLength,
2852 PULONG LengthReturned)
2853 {
2854 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
2855 PUSBDEVICE UsbDevice;
2856 CHubController * Controller;
2857
2858 DPRINT("USBHI_QueryDeviceInformation %p\n", BusContext);
2859
2860 //
2861 // sanity check
2862 //
2863 PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0));
2864 PC_ASSERT(DeviceInformationBuffer);
2865 PC_ASSERT(LengthReturned);
2866
2867 //
2868 // get controller object
2869 //
2870 Controller = (CHubController*)BusContext;
2871 PC_ASSERT(Controller);
2872
2873 //
2874 // get device object
2875 //
2876 UsbDevice = (PUSBDEVICE)DeviceHandle;
2877 PC_ASSERT(UsbDevice);
2878
2879 if (BusContext != DeviceHandle)
2880 {
2881 //
2882 // validate device handle
2883 //
2884 if (!Controller->ValidateUsbDevice(UsbDevice))
2885 {
2886 DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle);
2887
2888 //
2889 // invalid device handle
2890 //
2891 return STATUS_DEVICE_NOT_CONNECTED;
2892 }
2893
2894 //
2895 // access information buffer
2896 //
2897 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2898
2899 //
2900 // initialize with default values
2901 //
2902 DeviceInfo->InformationLevel = 0;
2903 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2904 DeviceInfo->PortNumber = UsbDevice->GetPort();
2905 DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
2906 DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
2907 DeviceInfo->HubAddress = 0; //FIXME
2908 DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
2909 DeviceInfo->DeviceType = UsbDevice->GetType();
2910 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2911
2912 //
2913 // get device descriptor
2914 //
2915 UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
2916
2917 //
2918 // FIXME return pipe information
2919 //
2920
2921 //
2922 // store result length
2923 //
2924 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
2925
2926 return STATUS_SUCCESS;
2927 }
2928
2929 //
2930 // access information buffer
2931 //
2932 DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
2933
2934 //
2935 // initialize with default values
2936 //
2937 DeviceInfo->InformationLevel = 0;
2938 DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
2939 DeviceInfo->PortNumber = 0;
2940 DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
2941 DeviceInfo->DeviceAddress = 0;
2942 DeviceInfo->HubAddress = 0; //FIXME
2943 DeviceInfo->DeviceSpeed = UsbFullSpeed; //FIXME
2944 DeviceInfo->DeviceType = Usb11Device; //FIXME
2945 DeviceInfo->NumberOfOpenPipes = 0; //FIXME
2946
2947 //
2948 // get device descriptor
2949 //
2950 RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR));
2951
2952 //
2953 // FIXME return pipe information
2954 //
2955
2956 //
2957 // store result length
2958 //
2959 #ifdef _MSC_VER
2960 *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]);
2961 #else
2962 *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0);
2963 #endif
2964 //
2965 // done
2966 //
2967 return STATUS_SUCCESS;
2968 }
2969
2970 NTSTATUS
2971 USB_BUSIFFN
2972 USBHI_GetControllerInformation(
2973 PVOID BusContext,
2974 PVOID ControllerInformationBuffer,
2975 ULONG ControllerInformationBufferLength,
2976 PULONG LengthReturned)
2977 {
2978 PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
2979
2980 DPRINT("USBHI_GetControllerInformation\n");
2981
2982 //
2983 // sanity checks
2984 //
2985 PC_ASSERT(ControllerInformationBuffer);
2986 PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0));
2987
2988 //
2989 // get controller info buffer
2990 //
2991 ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer;
2992
2993 //
2994 // FIXME only version 0 is supported for now
2995 //
2996 PC_ASSERT(ControllerInfo->InformationLevel == 0);
2997
2998 //
2999 // fill in information
3000 //
3001 ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0);
3002 ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME
3003 ControllerInfo->IsHighSpeedController = FALSE;
3004
3005 //
3006 // set length returned
3007 //
3008 *LengthReturned = ControllerInfo->ActualLength;
3009
3010 //
3011 // done
3012 //
3013 return STATUS_SUCCESS;
3014 }
3015
3016 NTSTATUS
3017 USB_BUSIFFN
3018 USBHI_ControllerSelectiveSuspend(
3019 PVOID BusContext,
3020 BOOLEAN Enable)
3021 {
3022 UNIMPLEMENTED
3023 return STATUS_NOT_IMPLEMENTED;
3024 }
3025
3026 NTSTATUS
3027 USB_BUSIFFN
3028 USBHI_GetExtendedHubInformation(
3029 PVOID BusContext,
3030 PDEVICE_OBJECT HubPhysicalDeviceObject,
3031 PVOID HubInformationBuffer,
3032 ULONG HubInformationBufferLength,
3033 PULONG LengthReturned)
3034 {
3035 PUSB_EXTHUB_INFORMATION_0 HubInfo;
3036 CHubController * Controller;
3037 PUSBHARDWAREDEVICE Hardware;
3038 ULONG Index;
3039 ULONG NumPort, Dummy2;
3040 USHORT Dummy1;
3041 NTSTATUS Status;
3042
3043 DPRINT("USBHI_GetExtendedHubInformation\n");
3044
3045 //
3046 // sanity checks
3047 //
3048 PC_ASSERT(HubInformationBuffer);
3049 PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0));
3050 PC_ASSERT(LengthReturned);
3051
3052 //
3053 // get hub controller
3054 //
3055 Controller = (CHubController *)BusContext;
3056 PC_ASSERT(Controller);
3057
3058 //
3059 // get usb hardware device
3060 //
3061 Hardware = Controller->GetUsbHardware();
3062
3063 //
3064 // retrieve number of ports
3065 //
3066 Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2);
3067 if (!NT_SUCCESS(Status))
3068 {
3069 //
3070 // failed to get hardware details, ouch ;)
3071 //
3072 DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status);
3073 return Status;
3074 }
3075
3076 //
3077 // get hub information buffer
3078 //
3079 HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer;
3080
3081 //
3082 // initialize hub information
3083 //
3084 HubInfo->InformationLevel = 0;
3085
3086 //
3087 // store port count
3088 //
3089 HubInfo->NumberOfPorts = NumPort;
3090
3091 //
3092 // initialize port information
3093 //
3094 for(Index = 0; Index < NumPort; Index++)
3095 {
3096 HubInfo->Port[Index].PhysicalPortNumber = Index + 1;
3097 HubInfo->Port[Index].PortLabelNumber = Index + 1;
3098 HubInfo->Port[Index].VidOverride = 0;
3099 HubInfo->Port[Index].PidOverride = 0;
3100 HubInfo->Port[Index].PortAttributes = 0; //FIXME
3101 }
3102
3103 //
3104 // store result length
3105 //
3106 #ifdef _MSC_VER
3107 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]);
3108 #else
3109 *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts;
3110 #endif
3111
3112 //
3113 // done
3114 //
3115 return STATUS_SUCCESS;
3116 }
3117
3118 NTSTATUS
3119 USB_BUSIFFN
3120 USBHI_GetRootHubSymbolicName(
3121 PVOID BusContext,
3122 PVOID HubSymNameBuffer,
3123 ULONG HubSymNameBufferLength,
3124 PULONG HubSymNameActualLength)
3125 {
3126 UNIMPLEMENTED
3127 return STATUS_NOT_IMPLEMENTED;
3128 }
3129
3130 PVOID
3131 USB_BUSIFFN
3132 USBHI_GetDeviceBusContext(
3133 PVOID HubBusContext,
3134 PVOID DeviceHandle)
3135 {
3136 UNIMPLEMENTED
3137 return NULL;
3138 }
3139
3140 NTSTATUS
3141 USB_BUSIFFN
3142 USBHI_RootHubInitNotification(
3143 PVOID BusContext,
3144 PVOID CallbackContext,
3145 PRH_INIT_CALLBACK CallbackRoutine)
3146 {
3147 CHubController * Controller;
3148
3149 DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext);
3150
3151 //
3152 // get controller object
3153 //
3154 Controller = (CHubController*)BusContext;
3155 PC_ASSERT(Controller);
3156
3157 //
3158 // set notification routine
3159 //
3160 Controller->SetNotification(CallbackContext, CallbackRoutine);
3161
3162 //
3163 // FIXME: determine when to perform callback
3164 //
3165 CallbackRoutine(CallbackContext);
3166
3167 //
3168 // done
3169 //
3170 return STATUS_SUCCESS;
3171 }
3172
3173 VOID
3174 USB_BUSIFFN
3175 USBHI_FlushTransfers(
3176 PVOID BusContext,
3177 PVOID DeviceHandle)
3178 {
3179 UNIMPLEMENTED
3180 }
3181
3182 VOID
3183 USB_BUSIFFN
3184 USBHI_SetDeviceHandleData(
3185 PVOID BusContext,
3186 PVOID DeviceHandle,
3187 PDEVICE_OBJECT UsbDevicePdo)
3188 {
3189 PUSBDEVICE UsbDevice;
3190 CHubController * Controller;
3191
3192 //
3193 // get controller
3194 //
3195 Controller = (CHubController *)BusContext;
3196 PC_ASSERT(Controller);
3197
3198 //
3199 // get device handle
3200 //
3201 UsbDevice = (PUSBDEVICE)DeviceHandle;
3202
3203 //
3204 // validate device handle
3205 //
3206 if (!Controller->ValidateUsbDevice(UsbDevice))
3207 {
3208 DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle);
3209
3210 //
3211 // invalid handle
3212 //
3213 return;
3214 }
3215 else
3216 {
3217 //
3218 // usbhub sends this request as a part of the Pnp startup sequence
3219 // looks like we need apply a dragon voodoo to fixup the device stack
3220 // otherwise usbhub will cause a bugcheck
3221 //
3222 DPRINT("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo);
3223
3224 //
3225 // sanity check
3226 //
3227 PC_ASSERT(UsbDevicePdo->AttachedDevice);
3228
3229 //
3230 // should be usbstor
3231 // fixup device stack voodoo part #2
3232 //
3233 UsbDevicePdo->AttachedDevice->StackSize++;
3234
3235 //
3236 // set device handle data
3237 //
3238 UsbDevice->SetDeviceHandleData(UsbDevicePdo);
3239 }
3240 }
3241
3242 //=================================================================================================
3243 //
3244 // USB Device Interface functions
3245 //
3246
3247 VOID
3248 USB_BUSIFFN
3249 USBDI_GetUSBDIVersion(
3250 PVOID BusContext,
3251 PUSBD_VERSION_INFORMATION VersionInformation,
3252 PULONG HcdCapabilites)
3253 {
3254 CHubController * Controller;
3255 PUSBHARDWAREDEVICE Device;
3256 ULONG Speed, Dummy2;
3257 USHORT Dummy1;
3258
3259 DPRINT("USBDI_GetUSBDIVersion\n");
3260
3261 //
3262 // get controller
3263 //
3264 Controller = (CHubController*)BusContext;
3265
3266 //
3267 // get usb hardware
3268 //
3269 Device = Controller->GetUsbHardware();
3270 PC_ASSERT(Device);
3271
3272 if (VersionInformation)
3273 {
3274 //
3275 // windows xp supported
3276 //
3277 VersionInformation->USBDI_Version = 0x00000500;
3278
3279 //
3280 // get device speed
3281 //
3282 Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed);
3283
3284 //
3285 // store speed details
3286 //
3287 VersionInformation->Supported_USB_Version = Speed;
3288 }
3289
3290 //
3291 // no flags supported
3292 //
3293 *HcdCapabilites = 0;
3294 }
3295
3296 NTSTATUS
3297 USB_BUSIFFN
3298 USBDI_QueryBusTime(
3299 PVOID BusContext,
3300 PULONG CurrentFrame)
3301 {
3302 UNIMPLEMENTED
3303 return STATUS_NOT_IMPLEMENTED;
3304 }
3305
3306 NTSTATUS
3307 USB_BUSIFFN
3308 USBDI_SubmitIsoOutUrb(
3309 PVOID BusContext,
3310 PURB Urb)
3311 {
3312 UNIMPLEMENTED
3313 return STATUS_NOT_IMPLEMENTED;
3314 }
3315