-
Notifications
You must be signed in to change notification settings - Fork 48
[REBASE & FF]Add USB and HID protocol definitions to SDK. #1498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,6 +121,7 @@ words: | |
| - mtrrs | ||
| - nestedfv | ||
| - nocapture | ||
| - noerror | ||
| - nologo | ||
| - nomem | ||
| - noopt | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| //! USB IO protocol FFI types and descriptor structures. | ||
| //! | ||
| //! Defines the `EFI_USB_IO_PROTOCOL` interface and associated USB descriptor | ||
| //! types needed to interact with USB devices. | ||
| //! | ||
| //! The underlying protocol is defined in the UEFI Specification version 2.11, | ||
| //! Chapter 17.2.4 (USB I/O Protocol). | ||
| //! | ||
| //! ## License | ||
| //! | ||
| //! Copyright (c) Microsoft Corporation. | ||
| //! | ||
| //! SPDX-License-Identifier: Apache-2.0 | ||
| //! | ||
| pub mod types; | ||
|
|
||
| use core::ffi::c_void; | ||
|
|
||
| use r_efi::efi; | ||
|
|
||
| use self::types::{ | ||
| EfiUsbConfigDescriptor, EfiUsbDataDirection, EfiUsbDeviceDescriptor, EfiUsbDeviceRequest, EfiUsbEndpointDescriptor, | ||
| EfiUsbInterfaceDescriptor, | ||
| }; | ||
|
|
||
| /// USB IO protocol GUID: 2B2F68D6-0CD2-44CF-8E8B-BBA20B1B5B75 | ||
| pub const USB_IO_PROTOCOL_GUID: crate::BinaryGuid = | ||
| crate::BinaryGuid::from_string("2B2F68D6-0CD2-44CF-8E8B-BBA20B1B5B75"); | ||
|
|
||
| /// Callback for async USB transfers (interrupt and isochronous). | ||
| pub type EfiAsyncUsbTransferCallback = | ||
| unsafe extern "efiapi" fn(data: *mut c_void, data_length: usize, context: *mut c_void, status: u32) -> efi::Status; | ||
|
|
||
| /// The EFI_USB_IO_PROTOCOL FFI interface. | ||
| /// | ||
| /// Provides services to manage and communicate with USB devices. | ||
| #[repr(C)] | ||
| pub struct EfiUsbIoProtocol { | ||
| /// Manages a USB device with a control transfer pipe. A control transfer is | ||
| /// typically used to perform device initialization and configuration. | ||
| pub usb_control_transfer: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| request: *const EfiUsbDeviceRequest, | ||
| direction: EfiUsbDataDirection, | ||
| timeout: u32, | ||
| data: *mut c_void, | ||
| data_length: usize, | ||
| status: *mut u32, | ||
| ) -> efi::Status, | ||
| /// Manages a USB device with the bulk transfer pipe. Bulk Transfers are | ||
| /// typically used to transfer large amounts of data to/from USB devices. | ||
| pub usb_bulk_transfer: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| device_endpoint: u8, | ||
| data: *mut c_void, | ||
| data_length: *mut usize, | ||
| timeout: usize, | ||
| status: *mut u32, | ||
| ) -> efi::Status, | ||
| /// Manages a USB device with an asynchronous interrupt transfer pipe. | ||
| /// Typically used to query a device's status at a fixed rate. For example, | ||
| /// keyboard, mouse, and hub devices use this type of transfer to query | ||
| /// their interrupt endpoints at a fixed rate. | ||
| pub usb_async_interrupt_transfer: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| device_endpoint: u8, | ||
| is_new_transfer: efi::Boolean, | ||
| polling_interval: usize, | ||
| data_length: usize, | ||
| callback: Option<EfiAsyncUsbTransferCallback>, | ||
| context: *mut c_void, | ||
| ) -> efi::Status, | ||
| /// Manages a USB device with a synchronous interrupt transfer pipe. Unlike | ||
| /// `usb_async_interrupt_transfer`, this executes only once. Once it returns, | ||
| /// regardless of status, the interrupt request is deleted. | ||
| pub usb_sync_interrupt_transfer: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| device_endpoint: u8, | ||
| data: *mut c_void, | ||
| data_length: *mut usize, | ||
| timeout: usize, | ||
| status: *mut u32, | ||
| ) -> efi::Status, | ||
| /// Manages a USB device with an isochronous transfer pipe. Isochronous | ||
| /// transfers are typically used to transfer streaming data. | ||
| pub usb_isochronous_transfer: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| device_endpoint: u8, | ||
| data: *mut c_void, | ||
| data_length: usize, | ||
| status: *mut u32, | ||
| ) -> efi::Status, | ||
| /// Manages a USB device with an asynchronous isochronous transfer pipe. | ||
| /// A nonblocking USB isochronous transfer. | ||
| pub usb_async_isochronous_transfer: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| device_endpoint: u8, | ||
| data: *mut c_void, | ||
| data_length: usize, | ||
| isochronous_callback: EfiAsyncUsbTransferCallback, | ||
| context: *mut c_void, | ||
| ) -> efi::Status, | ||
| /// Retrieves the USB Device Descriptor. | ||
| pub usb_get_device_descriptor: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| device_descriptor: *mut EfiUsbDeviceDescriptor, | ||
| ) -> efi::Status, | ||
| /// Retrieves the USB Device Configuration Descriptor. | ||
| pub usb_get_config_descriptor: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| config_descriptor: *mut EfiUsbConfigDescriptor, | ||
| ) -> efi::Status, | ||
| /// Retrieves the Interface Descriptor for a USB Device Controller. | ||
| pub usb_get_interface_descriptor: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| interface_descriptor: *mut EfiUsbInterfaceDescriptor, | ||
| ) -> efi::Status, | ||
| /// Retrieves an Endpoint Descriptor within a USB Controller. | ||
| pub usb_get_endpoint_descriptor: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| endpoint_index: u8, | ||
| endpoint_descriptor: *mut EfiUsbEndpointDescriptor, | ||
| ) -> efi::Status, | ||
| /// Retrieves a Unicode string stored in a USB Device. | ||
| pub usb_get_string_descriptor: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| lang_id: u16, | ||
| string_id: u8, | ||
| string: *mut *mut u16, | ||
| ) -> efi::Status, | ||
| /// Retrieves all the language ID codes that the USB device supports. | ||
| pub usb_get_supported_languages: unsafe extern "efiapi" fn( | ||
| this: *const EfiUsbIoProtocol, | ||
| lang_id_table: *mut *mut u16, | ||
| table_size: *mut u16, | ||
| ) -> efi::Status, | ||
|
|
||
| /// Resets and reconfigures the USB controller. | ||
| pub usb_port_reset: unsafe extern "efiapi" fn(this: *const EfiUsbIoProtocol) -> efi::Status, | ||
| } | ||
|
|
||
| // SAFETY: EfiUsbIoProtocol is a C-compatible struct whose layout matches the USB IO GUID interface. | ||
| unsafe impl crate::uefi_protocol::ProtocolInterface for EfiUsbIoProtocol { | ||
| const PROTOCOL_GUID: crate::BinaryGuid = USB_IO_PROTOCOL_GUID; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| //! USB descriptor structures, types, and constants. | ||
| //! | ||
| //! ## License | ||
| //! | ||
| //! Copyright (c) Microsoft Corporation. | ||
| //! | ||
| //! SPDX-License-Identifier: Apache-2.0 | ||
| //! | ||
|
|
||
| /// Direction of USB data transfer. | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| #[repr(C)] | ||
| pub enum EfiUsbDataDirection { | ||
| /// Data flows from device to host. | ||
| DataIn = 0, | ||
| /// Data flows from host to device. | ||
| DataOut = 1, | ||
| /// No data phase. | ||
| NoData = 2, | ||
| } | ||
|
|
||
| /// USB device request structure (SETUP packet). | ||
| #[derive(Debug, Clone, Copy)] | ||
| #[repr(C)] | ||
| pub struct EfiUsbDeviceRequest { | ||
| /// Identifies the characteristics of the specific request. | ||
| pub request_type: u8, | ||
| /// Specifies the particular request. | ||
| pub request: u8, | ||
| /// Request-specific parameter. | ||
| pub value: u16, | ||
| /// Request-specific index. | ||
| pub index: u16, | ||
| /// Number of bytes to transfer if there is a data stage. | ||
| pub length: u16, | ||
| } | ||
|
|
||
| /// USB descriptor type for configuration. | ||
| pub const USB_DESC_TYPE_CONFIG: u8 = 2; | ||
| /// USB descriptor type for interface. | ||
| pub const USB_DESC_TYPE_INTERFACE: u8 = 4; | ||
|
|
||
| /// USB endpoint transfer type mask. | ||
| pub const USB_ENDPOINT_XFER_TYPE_MASK: u8 = 0x03; | ||
| /// USB endpoint type: interrupt. | ||
| pub const USB_ENDPOINT_INTERRUPT: u8 = 0x03; | ||
| /// USB endpoint direction: IN. | ||
| pub const USB_ENDPOINT_DIR_IN: u8 = 0x80; | ||
|
|
||
| /// No USB error. | ||
| pub const EFI_USB_NOERROR: u32 = 0x00; | ||
| /// USB transfer was not executed. | ||
| pub const EFI_USB_ERR_NOTEXECUTE: u32 = 0x01; | ||
| /// USB stall error (endpoint halted). | ||
| pub const EFI_USB_ERR_STALL: u32 = 0x02; | ||
| /// USB data buffer error. | ||
| pub const EFI_USB_ERR_BUFFER: u32 = 0x04; | ||
| /// USB babble error (device sent more data than expected). | ||
| pub const EFI_USB_ERR_BABBLE: u32 = 0x08; | ||
| /// USB NAK error (device not ready). | ||
| pub const EFI_USB_ERR_NAK: u32 = 0x10; | ||
| /// USB CRC error. | ||
| pub const EFI_USB_ERR_CRC: u32 = 0x20; | ||
| /// USB timeout error. | ||
| pub const EFI_USB_ERR_TIMEOUT: u32 = 0x40; | ||
| /// USB bit stuffing error. | ||
| pub const EFI_USB_ERR_BITSTUFF: u32 = 0x80; | ||
| /// USB system error. | ||
| pub const EFI_USB_ERR_SYSTEM: u32 = 0x100; | ||
|
|
||
| /// USB device descriptor. | ||
| #[derive(Debug, Clone, Copy, Default)] | ||
| #[repr(C)] | ||
| pub struct EfiUsbDeviceDescriptor { | ||
| /// Size of this descriptor in bytes. | ||
| pub length: u8, | ||
| /// Descriptor type (USB_DESC_TYPE_DEVICE). | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. initially excluded because they weren't needed for the implementation; but agree they should be added to fully define the protocol |
||
| pub descriptor_type: u8, | ||
| /// USB specification release number in BCD. | ||
| pub bcd_usb: u16, | ||
| /// Class code (assigned by the USB-IF). | ||
| pub device_class: u8, | ||
| /// Subclass code (assigned by the USB-IF). | ||
| pub device_sub_class: u8, | ||
| /// Protocol code (assigned by the USB-IF). | ||
| pub device_protocol: u8, | ||
| /// Maximum packet size for endpoint zero. | ||
| pub max_packet_size0: u8, | ||
| /// Vendor ID (assigned by the USB-IF). | ||
| pub id_vendor: u16, | ||
| /// Product ID (assigned by the manufacturer). | ||
| pub id_product: u16, | ||
| /// Device release number in BCD. | ||
| pub bcd_device: u16, | ||
| /// Index of string descriptor describing manufacturer. | ||
| pub str_manufacturer: u8, | ||
| /// Index of string descriptor describing product. | ||
| pub str_product: u8, | ||
| /// Index of string descriptor describing device serial number. | ||
| pub str_serial_number: u8, | ||
| /// Number of possible configurations. | ||
| pub num_configurations: u8, | ||
| } | ||
|
|
||
| /// USB interface descriptor. | ||
| #[derive(Debug, Clone, Copy, Default)] | ||
| #[repr(C)] | ||
| pub struct EfiUsbInterfaceDescriptor { | ||
| /// Size of this descriptor in bytes. | ||
| pub length: u8, | ||
| /// Descriptor type (interface). | ||
| pub descriptor_type: u8, | ||
| /// Number of this interface. | ||
| pub interface_number: u8, | ||
| /// Value used to select this alternate setting. | ||
| pub alternate_setting: u8, | ||
| /// Number of endpoints used by this interface. | ||
| pub num_endpoints: u8, | ||
| /// Class code assigned by the USB-IF. | ||
| pub interface_class: u8, | ||
| /// Sub-class code assigned by the USB-IF. | ||
| pub interface_sub_class: u8, | ||
| /// Protocol code assigned by the USB-IF. | ||
| pub interface_protocol: u8, | ||
| /// Index of string descriptor describing this interface. | ||
| pub interface: u8, | ||
| } | ||
|
|
||
| /// USB endpoint descriptor. | ||
| #[derive(Debug, Clone, Copy, Default)] | ||
| #[repr(C)] | ||
| pub struct EfiUsbEndpointDescriptor { | ||
| /// Size of this descriptor in bytes. | ||
| pub length: u8, | ||
| /// Descriptor type (endpoint). | ||
| pub descriptor_type: u8, | ||
| /// The address of the endpoint on the USB device. | ||
| pub endpoint_address: u8, | ||
| /// Endpoint attributes (transfer type, sync type, usage type). | ||
| pub attributes: u8, | ||
| /// Maximum packet size this endpoint is capable of sending or receiving. | ||
| pub max_packet_size: u16, | ||
| /// Interval for polling endpoint for data transfers. | ||
| pub interval: u8, | ||
| } | ||
|
|
||
| /// USB configuration descriptor. | ||
| #[derive(Debug, Clone, Copy, Default)] | ||
| #[repr(C)] | ||
| pub struct EfiUsbConfigDescriptor { | ||
| /// Size of this descriptor in bytes. | ||
| pub length: u8, | ||
| /// Descriptor type (configuration). | ||
| pub descriptor_type: u8, | ||
| /// Total length of data returned for this configuration. | ||
| pub total_length: u16, | ||
| /// Number of interfaces supported by this configuration. | ||
| pub num_interfaces: u8, | ||
| /// Value to use as an argument to SetConfiguration to select this configuration. | ||
| pub configuration_value: u8, | ||
| /// Index of string descriptor describing this configuration. | ||
| pub configuration: u8, | ||
| /// Configuration attributes (self-powered, remote wakeup, etc.). | ||
| pub attributes: u8, | ||
| /// Maximum power consumption in 2mA units. | ||
| pub max_power: u8, | ||
| } | ||
|
|
||
| /// Common header for USB descriptors. | ||
| #[derive(Debug, Clone, Copy)] | ||
| #[repr(C, packed)] | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this structure (
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. copilot added it and it was an oversight on my part not to make it consistent with the others. In this case, it should not be needed as packed will result in the same as natural alignment for this struct. |
||
| pub struct UsbDescHead { | ||
| /// Size of this descriptor in bytes. | ||
| pub len: u8, | ||
| /// Descriptor type identifier. | ||
| pub desc_type: u8, | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| //! Vendor-specific UEFI protocol definitions. | ||
| //! | ||
| //! Protocols in this module are not part of the UEFI or PI specifications but | ||
| //! follow the UEFI protocol model. They are defined by platform vendors. | ||
| //! | ||
| //! ## License | ||
| //! | ||
| //! Copyright (c) Microsoft Corporation. | ||
| //! | ||
| //! SPDX-License-Identifier: Apache-2.0 | ||
| //! | ||
|
|
||
| pub mod hid_io; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the way this is defined in the UEFI Specification, I don't think we can consider it
*consthere.