// usb.h - internal USB/xHCI driver interfaces shared across usb.sys translation units. #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef USB_DEBUG_VERBOSE #define USB_DEBUG_VERBOSE 0 #endif #if USB_DEBUG_VERBOSE #define UsbTrace DbgPrint #else static __inline void UsbTrace(const char* fmt, ...) { (void)fmt; } #endif #define PCI_VENDOR_INVALID 0xFFFFu #define PCI_CLASS_SERIAL_BUS 0x0Cu #define PCI_SUBCLASS_USB 0x03u #define PCI_PROGIF_XHCI 0x30u #define PCI_REG_VENDOR_DEVICE 0x00u #define PCI_REG_COMMAND 0x04u #define PCI_REG_CLASS 0x08u #define PCI_REG_BAR0 0x10u #define PCI_COMMAND_MEMORY (1u << 1) #define PCI_COMMAND_MASTER (1u << 2) #define PCI_COMMAND_INTX_DISABLE (1u << 10) #define XHCI_CAP_CAPLENGTH 0x00u #define XHCI_CAP_HCSPARAMS1 0x04u #define XHCI_CAP_HCSPARAMS2 0x08u #define XHCI_CAP_HCCPARAMS1 0x10u #define XHCI_CAP_DBOFF 0x14u #define XHCI_CAP_RTSOFF 0x18u #define XHCI_OP_USBCMD 0x00u #define XHCI_OP_USBSTS 0x04u #define XHCI_OP_PAGESIZE 0x08u #define XHCI_OP_DNCTRL 0x14u #define XHCI_OP_CRCR 0x18u #define XHCI_OP_DCBAAP 0x30u #define XHCI_OP_CONFIG 0x38u #define XHCI_OP_PORT_BASE 0x400u #define XHCI_OP_PORT_STRIDE 0x10u #define XHCI_USBCMD_RS (1u << 0) #define XHCI_USBCMD_HCRST (1u << 1) #define XHCI_USBCMD_INTE (1u << 2) #define XHCI_USBCMD_HSEE (1u << 3) #define XHCI_USBSTS_HCH (1u << 0) #define XHCI_USBSTS_HSE (1u << 2) #define XHCI_USBSTS_EINT (1u << 3) #define XHCI_USBSTS_PCD (1u << 4) #define XHCI_USBSTS_CNR (1u << 11) #define XHCI_USBSTS_HCE (1u << 12) #define XHCI_USBSTS_CLEAR_MASK (XHCI_USBSTS_HSE | XHCI_USBSTS_EINT | \ XHCI_USBSTS_PCD | XHCI_USBSTS_HCE) #define XHCI_IMAN_IP (1u << 0) #define XHCI_IMAN_IE (1u << 1) #define XHCI_PORTSC_CCS (1u << 0) #define XHCI_PORTSC_PED (1u << 1) #define XHCI_PORTSC_OCA (1u << 3) #define XHCI_PORTSC_PR (1u << 4) #define XHCI_PORTSC_PP (1u << 9) #define XHCI_PORTSC_SPEED_SHIFT 10u #define XHCI_PORTSC_SPEED_MASK (0xFu << XHCI_PORTSC_SPEED_SHIFT) #define XHCI_PORTSC_CSC (1u << 17) #define XHCI_PORTSC_PEC (1u << 18) #define XHCI_PORTSC_WRC (1u << 19) #define XHCI_PORTSC_OCC (1u << 20) #define XHCI_PORTSC_PRC (1u << 21) #define XHCI_PORTSC_PLC (1u << 22) #define XHCI_PORTSC_CEC (1u << 23) #define XHCI_PORTSC_CHANGE_MASK (XHCI_PORTSC_CSC | XHCI_PORTSC_PEC | \ XHCI_PORTSC_WRC | XHCI_PORTSC_OCC | \ XHCI_PORTSC_PRC | XHCI_PORTSC_PLC | \ XHCI_PORTSC_CEC) #define XHCI_EXT_CAP_LEGACY 0x01u #define XHCI_EXT_CAP_PROTOCOL 0x02u #define XHCI_LEGSUP_BIOS_OWNED (1u << 16) #define XHCI_LEGSUP_OS_OWNED (1u << 24) #define XHCI_TRB_TYPE_SHIFT 10u #define XHCI_TRB_TYPE_MASK 0x3Fu #define XHCI_TRB_CYCLE (1u << 0) #define XHCI_TRB_LINK_TC (1u << 1) #define XHCI_TRB_TYPE_LINK 6u #define XHCI_TRB_TYPE_NOOP_CMD 23u #define XHCI_TRB_TYPE_CMD_DONE 33u #define XHCI_TRB_TYPE_PORT_SC 34u #define XHCI_TRB_TYPE_TRANSFER 32u #define XHCI_TRB_TYPE_NORMAL 1u #define XHCI_TRB_TYPE_SETUP 2u #define XHCI_TRB_TYPE_DATA 3u #define XHCI_TRB_TYPE_STATUS 4u #define XHCI_TRB_TYPE_ENABLE_SLOT 9u #define XHCI_TRB_TYPE_DISABLE_SLOT 10u #define XHCI_TRB_TYPE_ADDRESS_DEVICE 11u #define XHCI_TRB_TYPE_CONFIGURE_ENDPOINT 12u #define XHCI_CC_SUCCESS 1u #define XHCI_TRB_ISP (1u << 2) #define XHCI_TRB_IOC (1u << 5) #define XHCI_TRB_IDT (1u << 6) #define XHCI_TRB_DATA_DIR_IN (1u << 16) #define XHCI_TRB_SETUP_TRT_NONE (0u << 16) #define XHCI_TRB_SETUP_TRT_IN (3u << 16) #define XHCI_TRB_STATUS_DIR_IN (1u << 16) #define XHCI_HCC1_CSZ (1u << 2) #define XHCI_CONTEXT_ENTRIES(n) ((uint32_t)(n) << 27) #define XHCI_SLOT_SPEED(s) ((uint32_t)(s) << 20) #define XHCI_SLOT_ROOT_PORT(p) ((uint32_t)(p) << 16) #define XHCI_EP_TYPE_CONTROL (4u << 3) #define XHCI_EP_TYPE_BULK_OUT (2u << 3) #define XHCI_EP_TYPE_BULK_IN (6u << 3) #define XHCI_EP_TYPE_INT_IN (7u << 3) #define XHCI_EP_CERR_3 (3u << 1) #define XHCI_EP_DCS 1ull #define USB_REQ_GET_DESCRIPTOR 0x06u #define USB_REQ_SET_CONFIGURATION 0x09u #define USB_REQ_SET_IDLE 0x0Au #define USB_REQ_SET_PROTOCOL 0x0Bu #define USB_REQ_GET_STATUS 0x00u #define USB_REQ_CLEAR_FEATURE 0x01u #define USB_REQ_SET_FEATURE 0x03u #define USB_DESC_DEVICE 0x01u #define USB_DESC_CONFIGURATION 0x02u #define USB_DESC_INTERFACE 0x04u #define USB_DESC_ENDPOINT 0x05u #define USB_DESC_HUB 0x29u #define USB_DESC_SUPERSPEED_HUB 0x2Au #define USB_DESC_HID 0x21u #define USB_DESC_CS_INTERFACE 0x24u #define USB_DIR_OUT 0x00u #define USB_DIR_IN 0x80u #define USB_TYPE_STANDARD 0x00u #define USB_TYPE_CLASS 0x20u #define USB_RECIP_DEVICE 0x00u #define USB_RECIP_OTHER 0x03u #define USB_RECIP_INTERFACE 0x01u #define USB_ENDPOINT_DIR_IN 0x80u #define USB_ENDPOINT_NUMBER_MASK 0x0Fu #define USB_ENDPOINT_ATTR_TYPE_MASK 0x03u #define USB_ENDPOINT_TYPE_CONTROL 0x00u #define USB_ENDPOINT_TYPE_ISOCH 0x01u #define USB_ENDPOINT_TYPE_BULK 0x02u #define USB_ENDPOINT_TYPE_INTERRUPT 0x03u #define USB_CLASS_HID 0x03u #define USB_CLASS_MASS_STORAGE 0x08u #define USB_CLASS_HUB 0x09u #define USB_HUB_PORT_FEAT_CONNECTION 0u #define USB_HUB_PORT_FEAT_ENABLE 1u #define USB_HUB_PORT_FEAT_SUSPEND 2u #define USB_HUB_PORT_FEAT_OVER_CURRENT 3u #define USB_HUB_PORT_FEAT_RESET 4u #define USB_HUB_PORT_FEAT_POWER 8u #define USB_HUB_PORT_FEAT_C_CONNECTION 16u #define USB_HUB_PORT_FEAT_C_ENABLE 17u #define USB_HUB_PORT_FEAT_C_RESET 20u #define USB_HUB_PORT_STATUS_CONNECTION (1u << 0) #define USB_HUB_PORT_STATUS_ENABLE (1u << 1) #define USB_HUB_PORT_STATUS_LOW_SPEED (1u << 9) #define USB_HUB_PORT_STATUS_HIGH_SPEED (1u << 10) #define USB_HUB_PORT_CHANGE_CONNECTION (1u << 0) #define USB_HUB_PORT_CHANGE_ENABLE (1u << 1) #define USB_HUB_PORT_CHANGE_RESET (1u << 4) #define USB_MASS_SUBCLASS_SCSI 0x06u #define USB_MASS_PROTOCOL_BOT 0x50u #define USB_HID_SUBCLASS_BOOT 0x01u #define USB_HID_PROTOCOL_KEYBOARD 0x01u #define USB_HID_PROTOCOL_MOUSE 0x02u #define USB_MASS_BOT_CBW_SIGNATURE 0x43425355u #define USB_MASS_BOT_CSW_SIGNATURE 0x53425355u #define USB_MASS_BOT_CSW_PASSED 0u #define USB_MASS_BOT_CSW_FAILED 1u #define SCSI_TEST_UNIT_READY 0x00u #define SCSI_REQUEST_SENSE 0x03u #define SCSI_INQUIRY 0x12u #define SCSI_READ_10 0x28u #define SCSI_WRITE_10 0x2Au #define SCSI_READ_CAPACITY_10 0x25u #define XHCI_RING_TRBS 256u #define XHCI_EVENT_TRBS 256u #define XHCI_DCBAA_ENTRIES 256u #define XHCI_MMIO_FLOOR_BYTES 0x10000u #define XHCI_MAX_SCRATCHPADS 1024u #define XHCI_MAX_TRACKED_SLOTS 64u #define XHCI_MAX_ROOT_PORTS 255u #define XHCI_EP0_RING_TRBS 256u #define XHCI_HID_RING_TRBS 256u #define XHCI_BULK_RING_TRBS 256u #define XHCI_PIPE_RING_TRBS 256u #define XHCI_MAX_HID_REPORT 16u #define USB_STORAGE_DMA_PAGES 1u #define USB_STORAGE_MAX_BYTES (USB_STORAGE_DMA_PAGES * PAGE_SIZE) #define USB_STORAGE_SECTOR_SIZE 512u #define USB_MAX_TRACKED_INTERFACES 8u #define USB_MAX_TRACKED_ENDPOINTS 8u #define USB_MAX_DEVICE_ID_TEXT 96u #define USB_MAX_PIPES 32u #define USB_IOCTL_SUBMIT_URB 0x55534201u /* USB1 */ #define USB_ROOT_HUB_MAX_PORTS XHCI_MAX_ROOT_PORTS #define USB_EXTERNAL_HUB_MAX_PORTS 31u #define USB_ROOT_PORT_ENUM_RETRIES 3u #define USB_XHCI_CONTROL_TIMEOUT_US 1000000u #define USB_XHCI_ENUM_CONTROL_TIMEOUT_US 120000u #define USB_HUB_CHANGE_BITMAP_BYTES 8u #pragma pack(push, 1) typedef struct XHCI_TRB { uint32_t ParameterLo; uint32_t ParameterHi; uint32_t Status; uint32_t Control; } XHCI_TRB; typedef struct XHCI_ERST_ENTRY { uint64_t RingSegmentBase; uint32_t RingSegmentSize; uint32_t Reserved; } XHCI_ERST_ENTRY; typedef struct USB_SETUP_PACKET { uint8_t bmRequestType; uint8_t bRequest; uint16_t wValue; uint16_t wIndex; uint16_t wLength; } USB_SETUP_PACKET; typedef struct USB_DEVICE_DESCRIPTOR { uint8_t bLength; uint8_t bDescriptorType; uint16_t bcdUSB; uint8_t bDeviceClass; uint8_t bDeviceSubClass; uint8_t bDeviceProtocol; uint8_t bMaxPacketSize0; uint16_t idVendor; uint16_t idProduct; uint16_t bcdDevice; uint8_t iManufacturer; uint8_t iProduct; uint8_t iSerialNumber; uint8_t bNumConfigurations; } USB_DEVICE_DESCRIPTOR; typedef struct USB_CONFIGURATION_DESCRIPTOR { uint8_t bLength; uint8_t bDescriptorType; uint16_t wTotalLength; uint8_t bNumInterfaces; uint8_t bConfigurationValue; uint8_t iConfiguration; uint8_t bmAttributes; uint8_t bMaxPower; } USB_CONFIGURATION_DESCRIPTOR; typedef struct USB_INTERFACE_DESCRIPTOR { uint8_t bLength; uint8_t bDescriptorType; uint8_t bInterfaceNumber; uint8_t bAlternateSetting; uint8_t bNumEndpoints; uint8_t bInterfaceClass; uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; uint8_t iInterface; } USB_INTERFACE_DESCRIPTOR; typedef struct USB_ENDPOINT_DESCRIPTOR { uint8_t bLength; uint8_t bDescriptorType; uint8_t bEndpointAddress; uint8_t bmAttributes; uint16_t wMaxPacketSize; uint8_t bInterval; } USB_ENDPOINT_DESCRIPTOR; typedef struct USB_HUB_DESCRIPTOR { uint8_t bLength; uint8_t bDescriptorType; uint8_t bNbrPorts; uint16_t wHubCharacteristics; uint8_t bPwrOn2PwrGood; uint8_t bHubContrCurrent; uint8_t DeviceRemovable[1]; } USB_HUB_DESCRIPTOR; typedef struct USB_HUB_PORT_STATUS { uint16_t Status; uint16_t Change; } USB_HUB_PORT_STATUS; typedef struct USB_MASS_CBW { uint32_t Signature; uint32_t Tag; uint32_t DataTransferLength; uint8_t Flags; uint8_t Lun; uint8_t CommandBlockLength; uint8_t CommandBlock[16]; } USB_MASS_CBW; typedef struct USB_MASS_CSW { uint32_t Signature; uint32_t Tag; uint32_t DataResidue; uint8_t Status; } USB_MASS_CSW; #pragma pack(pop) typedef struct USB_TRACKED_INTERFACE { bool Present; USB_INTERFACE_DESCRIPTOR Descriptor; uint8_t EndpointCount; USB_ENDPOINT_DESCRIPTOR Endpoints[USB_MAX_TRACKED_ENDPOINTS]; } USB_TRACKED_INTERFACE; typedef enum USB_BAR_KIND { UsbBarNone, UsbBarIo, UsbBarMmio } USB_BAR_KIND; typedef struct USB_BAR { USB_BAR_KIND Kind; uint64_t Base; uint8_t Index; } USB_BAR; typedef enum USB_DEVICE_STATE { UsbDeviceAttached = 0, UsbDevicePowered, UsbDeviceDefault, UsbDeviceAddressed, UsbDeviceConfigured, UsbDeviceSuspended, UsbDeviceSurpriseRemoved, UsbDeviceRemoved, } USB_DEVICE_STATE; typedef struct USB_PORT_PATH { uint8_t RootPort; uint8_t Depth; uint32_t RouteString; uint8_t ParentHubSlot; uint8_t ParentHubPort; bool BehindHub; } USB_PORT_PATH; typedef enum USB_PIPE_TYPE { UsbPipeControl = 0, UsbPipeBulk, UsbPipeInterrupt, UsbPipeIsochronous, } USB_PIPE_TYPE; typedef enum USB_TRANSFER_DIRECTION { UsbTransferNoData = 0, UsbTransferOut, UsbTransferIn, } USB_TRANSFER_DIRECTION; typedef enum USB_URB_FUNCTION { UrbFunctionControlTransfer = 0, UrbFunctionBulkTransfer, UrbFunctionInterruptTransfer, UrbFunctionSelectConfiguration, UrbFunctionSelectInterface, UrbFunctionResetPipe, UrbFunctionAbortPipe, } USB_URB_FUNCTION; typedef struct USB_HCD USB_HCD; typedef struct USB_DEVICE USB_DEVICE; typedef struct USB_PIPE USB_PIPE; typedef struct USB_URB USB_URB; typedef struct XHCI_DEVICE XHCI_DEVICE; typedef void (*USB_URB_COMPLETION)(USB_URB* urb, void* context); typedef struct USB_HCD_OPERATIONS { KSTATUS (*SubmitUrb)(USB_HCD* hcd, USB_URB* urb); KSTATUS (*CancelUrb)(USB_HCD* hcd, USB_URB* urb); KSTATUS (*ResetRootPort)(USB_HCD* hcd, uint8_t port, uint8_t* outSpeed); KSTATUS (*ClearRootPortChanges)(USB_HCD* hcd, uint8_t port); void* (*AllocateDma)(USB_HCD* hcd, size_t pages, PHYSICAL_ADDRESS* outPhys); } USB_HCD_OPERATIONS; struct USB_HCD { const USB_HCD_OPERATIONS* Operations; void* ControllerContext; DRIVER_OBJECT* DriverObject; DEVICE_OBJECT* ControllerPdo; DEVICE_OBJECT* RootHubPdo; void* RootHubContext; uint8_t ControllerIndex; uint8_t MaxRootPorts; }; struct USB_DEVICE { OBJECT Header; USB_HCD* Hcd; DEVICE_OBJECT* Pdo; void* HcdDeviceContext; USB_DEVICE_STATE State; USB_PORT_PATH Path; uint8_t Address; uint8_t SlotId; uint8_t Speed; uint16_t MaxPacketSize0; uint16_t VendorId; uint16_t ProductId; uint16_t BcdUsb; uint16_t BcdDevice; uint8_t DeviceClass; uint8_t DeviceSubclass; uint8_t DeviceProtocol; uint8_t ConfigurationValue; IO_REMOVE_LOCK RemoveLock; bool RemoveLockReady; }; struct USB_PIPE { OBJECT Header; USB_DEVICE* Device; USB_PIPE_TYPE Type; uint8_t EndpointAddress; uint8_t EndpointId; uint16_t MaxPacketSize; uint8_t Interval; bool Open; bool Halted; void* HcdPipeContext; }; struct USB_URB { LIST_ENTRY Link; USB_URB_FUNCTION Function; USB_TRANSFER_DIRECTION Direction; USB_DEVICE* Device; USB_PIPE* Pipe; USB_SETUP_PACKET Setup; void* Buffer; PHYSICAL_ADDRESS BufferPhys; uint32_t Length; uint32_t ActualLength; KSTATUS Status; IRP* Irp; USB_URB_COMPLETION Complete; void* CompleteContext; bool Pending; bool Cancelled; }; typedef enum USB_PDO_KIND { UsbPdoController = 1, UsbPdoDevice = 2, UsbPdoInterface = 3, UsbPdoRootHub = 4, } USB_PDO_KIND; typedef struct USB_PDO_EXTENSION { USB_PDO_KIND Kind; USB_HCD* Hcd; USB_DEVICE* Device; uint8_t InterfaceIndex; USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; uint8_t EndpointCount; USB_ENDPOINT_DESCRIPTOR Endpoints[USB_MAX_TRACKED_ENDPOINTS]; } USB_PDO_EXTENSION; typedef enum USB_HUB_KIND { UsbHubKindRoot = 1, UsbHubKindExternal = 2, } USB_HUB_KIND; typedef enum USB_HUB_PORT_STATE { UsbHubPortDisconnected = 0, UsbHubPortPowered, UsbHubPortConnectedDebounce, UsbHubPortResetting, UsbHubPortEnabled, UsbHubPortEnumerating, UsbHubPortChildPresent, UsbHubPortFailedConnected, UsbHubPortRemoving, } USB_HUB_PORT_STATE; typedef struct USB_HUB_EXTENSION { DEVICE_OBJECT* Self; DEVICE_OBJECT* LowerDevice; DEVICE_OBJECT* HubPdo; USB_HUB_KIND Kind; USB_HCD* Hcd; USB_DEVICE* Device; IO_REMOVE_LOCK RemoveLock; bool RemoveLockReady; bool Started; bool SurpriseRemoved; bool Removed; uint8_t PortCount; uint8_t RootPortSlot[USB_ROOT_HUB_MAX_PORTS + 1u]; uint8_t RootPortFailCount[USB_ROOT_HUB_MAX_PORTS + 1u]; USB_HUB_PORT_STATE RootPortState[USB_ROOT_HUB_MAX_PORTS + 1u]; uint8_t ChildSlot[USB_EXTERNAL_HUB_MAX_PORTS + 1u]; USB_HUB_PORT_STATE ChildPortState[USB_EXTERNAL_HUB_MAX_PORTS + 1u]; uint32_t PendingRootPorts[8]; uint32_t PendingHubPorts[1]; SPINLOCK PendingLock; SEMAPHORE* WorkerSemaphore; THREAD* WorkerThread; bool WorkerRunning; bool InitialScanPending; bool InitialScanComplete; bool InitialScanInProgress; uint8_t InterfaceNumber; uint8_t InterruptEndpointAddress; uint16_t InterruptMaxPacket; uint8_t InterruptInterval; USB_PIPE* InterruptPipe; uint8_t* ChangeBitmap; PHYSICAL_ADDRESS ChangeBitmapPhys; USB_URB ChangeUrb; bool ChangeUrbPending; uint8_t PowerOnToPowerGoodMs; } USB_HUB_EXTENSION; typedef struct USB_COMPOSITE_EXTENSION { DEVICE_OBJECT* Self; DEVICE_OBJECT* LowerDevice; DEVICE_OBJECT* DevicePdo; USB_DEVICE* Device; bool Started; bool InterfacesCreated; } USB_COMPOSITE_EXTENSION; typedef struct USB_HID_EXTENSION { DEVICE_OBJECT* Self; DEVICE_OBJECT* LowerDevice; DEVICE_OBJECT* InterfacePdo; USB_DEVICE* Device; IO_REMOVE_LOCK RemoveLock; bool RemoveLockReady; bool Started; bool SurpriseRemoved; bool Removed; bool Keyboard; bool Mouse; uint8_t InterfaceNumber; uint8_t Protocol; uint8_t EndpointAddress; uint16_t MaxPacketSize; uint8_t Interval; USB_PIPE* InterruptPipe; uint8_t* ReportBuffer; PHYSICAL_ADDRESS ReportBufferPhys; uint16_t ReportLength; USB_URB InterruptUrb; bool InterruptPending; uint8_t LastModifiers; uint8_t LastKeys[6]; uint8_t LastButtons; uint32_t InputDeviceId; } USB_HID_EXTENSION; typedef enum USB_STORAGE_EXTENSION_KIND { UsbStorageExtensionInterface = 0x55534946u, UsbStorageExtensionDisk = 0x5553444Bu, } USB_STORAGE_EXTENSION_KIND; typedef struct USB_STORAGE_EXTENSION USB_STORAGE_EXTENSION; typedef struct USB_STORAGE_DISK_EXTENSION USB_STORAGE_DISK_EXTENSION; struct USB_STORAGE_EXTENSION { USB_STORAGE_EXTENSION_KIND Kind; DEVICE_OBJECT* Self; DEVICE_OBJECT* LowerDevice; DEVICE_OBJECT* InterfacePdo; DEVICE_OBJECT* DiskDevice; USB_DEVICE* Device; XHCI_DEVICE* XhciDevice; USB_PIPE* BulkInPipe; USB_PIPE* BulkOutPipe; IO_REMOVE_LOCK RemoveLock; bool RemoveLockReady; bool Started; bool SurpriseRemoved; bool Removed; uint8_t InterfaceNumber; uint8_t BulkInAddress; uint8_t BulkOutAddress; uint16_t BulkInMaxPacket; uint16_t BulkOutMaxPacket; uint32_t Tag; uint32_t BlockSize; uint64_t BlockCount; volatile long IoBusy; }; struct USB_STORAGE_DISK_EXTENSION { USB_STORAGE_EXTENSION_KIND Kind; USB_STORAGE_EXTENSION* Storage; }; typedef struct XHCI_PIPE_CONTEXT { XHCI_TRB* Ring; PHYSICAL_ADDRESS RingPhys; uint32_t Enqueue; uint8_t Cycle; uint8_t EndpointId; USB_PIPE_TYPE Type; bool Configured; bool ActiveTransfer; uint64_t ActiveTrbPhys; USB_URB* ActiveUrb; } XHCI_PIPE_CONTEXT; typedef struct XHCI_DEVICE { bool Allocated; bool Addressed; uint8_t SlotId; uint8_t Port; uint8_t Speed; uint16_t MaxPacketSize0; uint16_t VendorId; uint16_t ProductId; uint16_t BcdUsb; uint16_t BcdDevice; uint8_t DeviceClass; uint8_t DeviceSubclass; uint8_t DeviceProtocol; uint8_t ConfigurationValue; bool Configured; USB_DEVICE* UsbDevice; DEVICE_OBJECT* UsbPdo; DEVICE_OBJECT* ParentDeviceObject; USB_PORT_PATH Path; USB_PIPE* EndpointPipes[32]; uint8_t InterfaceCount; USB_TRACKED_INTERFACE Interfaces[USB_MAX_TRACKED_INTERFACES]; bool HidCandidate; bool HidActive; bool HidKeyboard; bool HidMouse; bool HidArmed; uint8_t HidInterface; uint8_t HidProtocol; uint8_t HidEndpointAddress; uint8_t HidEndpointId; uint8_t HidInterval; uint16_t HidMaxPacket; uint16_t HidReportLength; uint32_t HidEnqueue; uint8_t HidCycle; uint8_t HidLastModifiers; uint8_t HidLastKeys[6]; uint8_t HidLastButtons; uint64_t HidLastTrbPhys; bool MassCandidate; bool MassActive; uint8_t MassInterface; uint8_t MassBulkInAddress; uint8_t MassBulkOutAddress; uint8_t MassBulkInEndpointId; uint8_t MassBulkOutEndpointId; uint16_t MassBulkInMaxPacket; uint16_t MassBulkOutMaxPacket; uint32_t MassInEnqueue; uint8_t MassInCycle; uint32_t MassOutEnqueue; uint8_t MassOutCycle; uint32_t MassTag; uint32_t MassBlockSize; uint64_t MassBlockCount; DEVICE_OBJECT* MassDeviceObject; IO_REMOVE_LOCK MassRemoveLock; bool MassRemoveLockReady; bool MassSurpriseRemoved; bool MassRemoved; volatile long MassIoBusy; PHYSICAL_ADDRESS InputContextPhys; PHYSICAL_ADDRESS DeviceContextPhys; PHYSICAL_ADDRESS Ep0RingPhys; PHYSICAL_ADDRESS HidRingPhys; PHYSICAL_ADDRESS MassInRingPhys; PHYSICAL_ADDRESS MassOutRingPhys; PHYSICAL_ADDRESS DescriptorPhys; PHYSICAL_ADDRESS HidBufferPhys; PHYSICAL_ADDRESS MassBufferPhys; uint8_t* InputContext; uint8_t* DeviceContext; XHCI_TRB* Ep0Ring; XHCI_TRB* HidRing; XHCI_TRB* MassInRing; XHCI_TRB* MassOutRing; uint8_t* DescriptorBuffer; uint8_t* HidBuffer; uint8_t* MassBuffer; uint32_t Ep0Enqueue; uint8_t Ep0Cycle; } XHCI_DEVICE; typedef struct XHCI_COMMAND_RESULT { uint32_t CompletionCode; uint8_t SlotId; } XHCI_COMMAND_RESULT; typedef struct XHCI_TRANSFER_RESULT { uint32_t CompletionCode; uint8_t SlotId; uint8_t EndpointId; uint32_t Residue; } XHCI_TRANSFER_RESULT; typedef struct XHCI_WAIT_TARGET { struct XHCI_WAIT_TARGET* Next; uint64_t CommandPhys; uint64_t TransferPhys; uint8_t TransferSlotId; uint8_t TransferEndpointId; volatile bool CommandMatched; volatile bool TransferMatched; volatile bool Registered; XHCI_COMMAND_RESULT Command; XHCI_TRANSFER_RESULT Transfer; } XHCI_WAIT_TARGET; typedef struct XHCI_CONTROLLER { const HAL_API* Hal; uint8_t Bus; uint8_t Dev; uint8_t Fn; uint8_t Irq; bool UsingMsi; uint64_t MmioPhys; uint32_t MmioBytes; volatile uint8_t* Mmio; volatile uint8_t* Cap; volatile uint8_t* Op; volatile uint8_t* Runtime; volatile uint8_t* Doorbells; uint8_t CapLength; uint16_t Version; uint32_t Hcs1; uint32_t Hcs2; uint32_t Hcc1; uint32_t DbOff; uint32_t RtsOff; uint8_t MaxSlots; uint16_t MaxIntrs; uint8_t MaxPorts; uint16_t ScratchpadCount; uint8_t PortProtocolMajor[XHCI_MAX_ROOT_PORTS + 1u]; uint8_t PortProtocolMinor[XHCI_MAX_ROOT_PORTS + 1u]; PHYSICAL_ADDRESS DcbaaPhys; PHYSICAL_ADDRESS ScratchpadArrayPhys; PHYSICAL_ADDRESS ScratchpadPhys[XHCI_MAX_SCRATCHPADS]; PHYSICAL_ADDRESS CommandRingPhys; PHYSICAL_ADDRESS EventRingPhys; PHYSICAL_ADDRESS ErstPhys; uint64_t* Dcbaa; uint64_t* ScratchpadArray; XHCI_TRB* CommandRing; XHCI_TRB* EventRing; XHCI_ERST_ENTRY* Erst; uint32_t CommandEnqueue; uint8_t CommandCycle; uint32_t EventDequeue; uint8_t EventCycle; uint8_t ContextBytes; XHCI_DEVICE Devices[XHCI_MAX_TRACKED_SLOTS + 1u]; uint32_t HidDeviceCount; KDPC EventDpc; volatile bool InterruptsEnabled; volatile uint32_t InterruptCount; volatile uint32_t EventDpcCount; SPINLOCK EventLock; SPINLOCK WaitLock; SPINLOCK CommandLock; XHCI_WAIT_TARGET* WaiterList; volatile bool Running; USB_HCD Hcd; } XHCI_CONTROLLER; extern XHCI_CONTROLLER gXhci; extern bool gHaveXhci; extern DRIVER_OBJECT gUsbStorageDriver; extern DRIVER_OBJECT gUsbBusDriver; extern DRIVER_OBJECT gUsbCompositeDriver; extern DRIVER_OBJECT gUsbHidDriver; extern DRIVER_OBJECT gUsbHubDriver; KSTATUS UsbInitializeBusModel(void); KSTATUS UsbInitializeCompositeDriver(void); KSTATUS UsbInitializeHidDriver(void); KSTATUS UsbInitializeStorageDriver(void); KSTATUS UsbInitializeHubDriver(void); KSTATUS UsbCompositeAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject); KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp); void UsbInitializeHcd(USB_HCD* hcd, const USB_HCD_OPERATIONS* ops, void* controllerContext, uint8_t controllerIndex, uint8_t maxRootPorts); KSTATUS UsbCreateControllerPdo(USB_HCD* hcd, uint16_t vendor, uint16_t device); KSTATUS UsbCreateRootHubPdo(USB_HCD* hcd); KSTATUS UsbRemoveDeviceObjectChildren(DEVICE_OBJECT* parent, bool surprise); KSTATUS UsbRemovePdoSubtree(DEVICE_OBJECT* pdo, bool surprise); KSTATUS UsbCreateDevicePdo(USB_HCD* hcd, XHCI_DEVICE* xhciDev, DEVICE_OBJECT* parent); KSTATUS UsbCreateInterfacePdos(USB_HCD* hcd, XHCI_DEVICE* xhciDev, DEVICE_OBJECT* parent); KSTATUS UsbCreatePipe(USB_DEVICE* dev, USB_PIPE_TYPE type, uint8_t endpointAddress, uint16_t maxPacketSize, uint8_t interval, USB_PIPE** outPipe); void UsbReferenceDevice(USB_DEVICE* dev); void UsbDereferenceDevice(USB_DEVICE* dev); void UsbReferencePipe(USB_PIPE* pipe); void UsbDereferencePipe(USB_PIPE* pipe); KSTATUS UsbSubmitUrbSync(DEVICE_OBJECT* target, USB_URB* urb); KSTATUS UsbSubmitUrbAsync(DEVICE_OBJECT* target, USB_URB* urb); KSTATUS UsbCancelUrb(USB_URB* urb); void* UsbAllocateDmaBuffer(USB_DEVICE* dev, size_t pages, PHYSICAL_ADDRESS* outPhys); KSTATUS UsbDispatchPdoPnp(DEVICE_OBJECT* device, IRP* irp); KSTATUS UsbDispatchInternalDeviceControl(DEVICE_OBJECT* device, IRP* irp); uint32_t UsbAlignUp32(uint32_t value, uint32_t align); void XhciBarrier(void); uint8_t XhciRead8(volatile uint8_t* base, uint32_t reg); uint16_t XhciRead16(volatile uint8_t* base, uint32_t reg); uint32_t XhciRead32(volatile uint8_t* base, uint32_t reg); void XhciWrite32(volatile uint8_t* base, uint32_t reg, uint32_t value); uint64_t XhciRead64(volatile uint8_t* base, uint32_t reg); void XhciWrite64(volatile uint8_t* base, uint32_t reg, uint64_t value); void UsbDelayUs(const HAL_API* hal, uint32_t us); bool UsbWaitSet32(const HAL_API* hal, volatile uint8_t* base, uint32_t reg, uint32_t mask, uint32_t timeoutUs); bool UsbWaitClear32(const HAL_API* hal, volatile uint8_t* base, uint32_t reg, uint32_t mask, uint32_t timeoutUs); bool UsbReadBar(const HAL_API* hal, uint8_t bus, uint8_t dev, uint8_t fn, uint8_t index, USB_BAR* out); KSTATUS UsbMapMmio(const HAL_API* hal, uint64_t physBase, uint32_t bytes, volatile uint8_t** outMmio); void* UsbDmaAllocPages(XHCI_CONTROLLER* xhci, size_t pages, PHYSICAL_ADDRESS* outPhys); uint16_t XhciScratchpadCount(uint32_t hcs2); uint32_t XhciTrbType(const XHCI_TRB* trb); uint32_t XhciCompletionCode(const XHCI_TRB* trb); uint8_t XhciEventSlotId(const XHCI_TRB* trb); uint8_t XhciEventEndpointId(const XHCI_TRB* trb); uint32_t XhciTransferResidue(const XHCI_TRB* trb); uint32_t* XhciInputControlContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); uint32_t* XhciInputSlotContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); uint32_t* XhciInputEndpointContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, uint8_t endpointId); uint32_t XhciEpMaxPacket(uint8_t speed); uint64_t UsbSetupPacketToU64(const USB_SETUP_PACKET* setup); const char* XhciPortSpeedName(uint32_t speed); void XhciParseSupportedProtocols(XHCI_CONTROLLER* xhci); uint8_t XhciPortProtocolMajor(XHCI_CONTROLLER* xhci, uint8_t port, uint32_t portsc); const char* UsbEndpointTypeName(uint8_t type); const char* UsbDirectionName(uint8_t endpointAddress); const char* UsbInterfaceClassName(uint8_t klass, uint8_t subclass, uint8_t proto); void XhciLogPortStatus(XHCI_CONTROLLER* xhci); void XhciPowerRootPorts(XHCI_CONTROLLER* xhci); void XhciAckInterrupter0(XHCI_CONTROLLER* xhci); void XhciUpdateErdp(XHCI_CONTROLLER* xhci); bool XhciDrainEventRing(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target); bool XhciDrainEventRingLocked(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target); bool XhciWaitTargetComplete(const XHCI_WAIT_TARGET* target); void XhciRegisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target); void XhciUnregisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target); KSTATUS XhciWaitForArmedTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs); KSTATUS XhciWaitForTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs); void XhciEventDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2); void XhciIsr(void); KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci); KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci); KSTATUS XhciAllocateScratchpads(XHCI_CONTROLLER* xhci); KSTATUS XhciAllocateRuntimeMemory(XHCI_CONTROLLER* xhci); KSTATUS XhciProgramRuntime(XHCI_CONTROLLER* xhci); uint64_t XhciCommandTrbPhys(XHCI_CONTROLLER* xhci, uint32_t index); KSTATUS XhciSubmitCommand(XHCI_CONTROLLER* xhci, uint64_t parameter, uint32_t status, uint32_t controlWithoutCycle, XHCI_COMMAND_RESULT* outResult); KSTATUS XhciSubmitNoopCommand(XHCI_CONTROLLER* xhci); KSTATUS XhciEnableSlot(XHCI_CONTROLLER* xhci, uint8_t* outSlotId); KSTATUS XhciAddressDevice(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); KSTATUS XhciStart(XHCI_CONTROLLER* xhci); void XhciEnableInterrupts(XHCI_CONTROLLER* xhci); uint32_t XhciPortReg(uint8_t port); void XhciClearPortChanges(XHCI_CONTROLLER* xhci, uint8_t port); KSTATUS XhciResetPort(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSpeed); KSTATUS XhciDisableSlot(XHCI_CONTROLLER* xhci, uint8_t slotId); KSTATUS XhciAllocateDeviceMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); void XhciBuildDefaultControlContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); uint64_t XhciEp0TrbPhys(XHCI_DEVICE* dev, uint32_t index); KSTATUS XhciEp0AppendTrb(XHCI_DEVICE* dev, uint64_t parameter, uint32_t status, uint32_t controlWithoutCycle, uint64_t* outPhys); KSTATUS XhciControlInTimeout(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, const USB_SETUP_PACKET* setup, void* buffer, PHYSICAL_ADDRESS bufferPhys, uint16_t length, uint32_t timeoutUs); KSTATUS XhciControlIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, const USB_SETUP_PACKET* setup, void* buffer, PHYSICAL_ADDRESS bufferPhys, uint16_t length); KSTATUS XhciControlNoData(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, const USB_SETUP_PACKET* setup); KSTATUS XhciGetDeviceDescriptorTimeout(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_DEVICE_DESCRIPTOR* outDesc, uint32_t timeoutUs); KSTATUS XhciGetDeviceDescriptor(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_DEVICE_DESCRIPTOR* outDesc); KSTATUS XhciGetConfigurationDescriptor(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, uint8_t configurationIndex, USB_CONFIGURATION_DESCRIPTOR* outConfig, uint16_t* outTotalLength); uint8_t XhciEndpointIdFromAddress(uint8_t endpointAddress); uint8_t XhciInterruptInterval(uint8_t speed, uint8_t usbInterval); KSTATUS XhciRingAppend(XHCI_TRB* ring, PHYSICAL_ADDRESS ringPhys, uint32_t trbCount, uint32_t* enqueue, uint8_t* cycle, uint64_t parameter, uint32_t status, uint32_t controlWithoutCycle, uint64_t* outPhys); bool XhciHidKeyInReport(const uint8_t* keys, uint8_t key); INPUT_KEY XhciHidModifierKey(uint8_t bit); void XhciSubmitHidKey(INPUT_KEY key, bool pressed); void XhciProcessBootKeyboardReport(XHCI_DEVICE* dev, const uint8_t* report, uint16_t len); void XhciProcessBootMouseReport(XHCI_DEVICE* dev, const uint8_t* report, uint16_t len); KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); void XhciArmAllHid(XHCI_CONTROLLER* xhci); void XhciHandleAsyncTransferEvent(XHCI_CONTROLLER* xhci, uint64_t trbPhys, uint32_t completionCode, uint8_t slotId, uint8_t endpointId, uint32_t residue); KSTATUS XhciStartHidInterrupts(XHCI_CONTROLLER* xhci); KSTATUS XhciSetHidBootProtocol(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); KSTATUS XhciAllocateHidMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); KSTATUS XhciConfigureHidEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); const IO_PUBLISHED_USB_ENDPOINT* UsbFindEndpoint(const IO_PUBLISHED_DEVICE* pub, uint8_t endpointType, bool wantIn); bool UsbHidMatch(const IO_PUBLISHED_DEVICE* pub, void* context); KSTATUS UsbHidBind(IO_PUBLISHED_DEVICE* pub, void* context); KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject); KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp); void XhciInitialiseTransferRing(XHCI_TRB* ring, PHYSICAL_ADDRESS ringPhys, uint32_t trbCount, uint8_t cycle); KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_PIPE* pipe); KSTATUS XhciBulkTransfer(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, uint8_t endpointId, XHCI_TRB* ring, PHYSICAL_ADDRESS ringPhys, uint32_t* enqueue, uint8_t* cycle, PHYSICAL_ADDRESS bufferPhys, uint32_t length, uint32_t* outActual); KSTATUS UsbStorageBulkIn(USB_STORAGE_EXTENSION* storage, PHYSICAL_ADDRESS phys, uint32_t length, uint32_t* outActual); KSTATUS UsbStorageBulkOut(USB_STORAGE_EXTENSION* storage, PHYSICAL_ADDRESS phys, uint32_t length, uint32_t* outActual); KSTATUS UsbStorageBotCommand(USB_STORAGE_EXTENSION* storage, const uint8_t* cdb, uint8_t cdbLen, void* data, PHYSICAL_ADDRESS dataPhys, uint32_t dataLength, bool dataIn); uint32_t UsbBe32(const uint8_t* p); void UsbStoreBe32(uint8_t* p, uint32_t v); void UsbStoreBe16(uint8_t* p, uint16_t v); KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage); KSTATUS UsbStorageRequestSense(USB_STORAGE_EXTENSION* storage); KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage); KSTATUS UsbStorageReadCapacity(USB_STORAGE_EXTENSION* storage); KSTATUS UsbStorageReadWriteSectors(USB_STORAGE_EXTENSION* storage, bool write, uint64_t lba, uint32_t sectors, void* buffer); void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage); void UsbStorageReleaseIo(USB_STORAGE_EXTENSION* storage); KSTATUS UsbStorageDispatchReadWrite(DEVICE_OBJECT* device, IRP* irp); KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp); KSTATUS UsbStorageAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject); KSTATUS XhciAllocateMassStorageMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); KSTATUS XhciConfigureMassStorageEndpoints(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev); uint8_t UsbFindFreeDiskIndex(void); KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage); bool UsbStorageMatch(const IO_PUBLISHED_DEVICE* pub, void* context); KSTATUS UsbStorageBind(IO_PUBLISHED_DEVICE* pub, void* context); KSTATUS XhciSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, uint8_t configurationValue); void XhciLogConfigurationTree(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, const USB_CONFIGURATION_DESCRIPTOR* config, uint16_t totalLength); KSTATUS XhciDiscoverAndSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, const USB_DEVICE_DESCRIPTOR* devDesc); KSTATUS XhciEnumeratePortEx(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSlotId); KSTATUS XhciEnumerateHubPortEx(XHCI_CONTROLLER* xhci, USB_HUB_EXTENSION* hub, uint8_t hubPort, uint8_t speed, uint8_t* outSlotId); KSTATUS XhciEnumeratePort(XHCI_CONTROLLER* xhci, uint8_t port); void XhciEnumerateRootPorts(XHCI_CONTROLLER* xhci); KSTATUS UsbHubScheduleRootScan(USB_HCD* hcd); void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port); void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port); extern const USB_HCD_OPERATIONS gXhciHcdOperations; KSTATUS XhciInitialise(const HAL_API* hal, uint8_t bus, uint8_t dev, uint8_t fn, uint16_t vendor, uint16_t device);