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