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