Skip to content

uefi-raw: Add EFI_USB2_HC_PROTOCOL bindings #1629

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

Merged
merged 2 commits into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions uefi-raw/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Added `AtaPassThruProtocol`.
- Added `DevicePathUtilitiesProtocol`.
- Added `UsbIoProtocol`.
- Added `Usb2HostControllerProtocol`.


# uefi-raw - 0.10.0 (2025-02-07)
Expand Down
218 changes: 218 additions & 0 deletions uefi-raw/src/protocol/usb/host_controller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

use core::ffi;

use bitflags::bitflags;

use crate::{guid, Boolean, Guid, Status};

use super::{AsyncUsbTransferCallback, DataDirection, DeviceRequest, UsbTransferStatus};

newtype_enum! {
pub enum Speed: u8 => {
FULL = 0,
LOW = 1,
HIGH = 2,
SUPER = 3,
}
}

bitflags! {
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ResetAttributes: u16 {
/// Send a global reset signal to the USB bus.
const RESET_GLOBAL = 0x0001;
/// Reset the USB host controller hardware.
///
/// No reset signal will be sent to the USB bus.
const RESET_HOST = 0x0002;
/// Send a global reset signal to the USB bus.
///
/// Even if a debug port has been enabled, this still resets the host controller.
const RESET_GLOBAL_WITH_DEBUG = 0x0004;
/// Reset the USB host controller hardware.
///
/// Even if a debug port has been enabled, this still resets the host controller.
const RESET_HOST_WITH_DEBUG = 0x0008;
}
}

newtype_enum! {
pub enum HostControllerState: i32 => {
HALT = 0,
OPERATIONAL = 1,
SUSPEND = 2,
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct TransactionTranslator {
pub hub_address: u8,
pub port_number: u8,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct UsbPortStatus {
pub port_status: PortStatus,
pub port_change_status: PortChangeStatus,
}

bitflags! {
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct PortStatus: u16 {
const CONNECTION = 0x0001;
const ENABLE = 0x0002;
const SUSPEND = 0x0004;
const OVER_CURRENT = 0x0008;
const RESET = 0x0010;
const POWER = 0x0100;
const LOW_SPEED = 0x0200;
const HIGH_SPEED = 0x0400;
const SUPER_SPEED = 0x0800;
const OWNER = 0x2000;
}
}

bitflags! {
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct PortChangeStatus: u16 {
const CONNECTION = 0x0001;
const ENABLE = 0x0002;
const SUSPEND = 0x0004;
const OVER_CURRENT = 0x0008;
const RESET = 0x0010;
}
}

newtype_enum! {
pub enum PortFeature: i32 => {
ENABLE = 1,
SUSPEND = 2,
RESET = 4,
POWER = 8,
OWNER = 13,
CONNECT_CHANGE = 16,
ENABLE_CHANGE = 17,
SUSPEND_CHANGE = 18,
OVER_CURRENT_CHARGE = 19,
RESET_CHANGE = 20,
}
}

#[derive(Debug)]
#[repr(C)]
pub struct Usb2HostControllerProtocol {
pub get_capability: unsafe extern "efiapi" fn(
this: *const Self,
max_speed: *mut Speed,
port_number: *mut u8,
is_64_bit_capable: *mut u8,
) -> Status,
pub reset: unsafe extern "efiapi" fn(this: *mut Self, attributes: ResetAttributes) -> Status,
pub get_state:
unsafe extern "efiapi" fn(this: *mut Self, state: *mut HostControllerState) -> Status,
pub set_state: unsafe extern "efiapi" fn(this: *mut Self, state: HostControllerState) -> Status,
pub control_transfer: unsafe extern "efiapi" fn(
this: *mut Self,
device_address: u8,
device_speed: Speed,
maximum_packet_length: usize,
request: *const DeviceRequest,
transfer_direction: DataDirection,
data: *mut ffi::c_void,
data_length: *mut usize,
timeout: usize,
translator: *const TransactionTranslator,
transfer_result: *mut UsbTransferStatus,
) -> Status,
pub bulk_transfer: unsafe extern "efiapi" fn(
this: *mut Self,
device_address: u8,
endpoint_address: u8,
device_speed: Speed,
maximum_packet_length: usize,
data_buffers_number: u8,
data: *const *const ffi::c_void,
data_length: *mut usize,
data_toggle: *mut u8,
timeout: usize,
translator: *const TransactionTranslator,
transfer_result: *mut UsbTransferStatus,
) -> Status,
pub async_interrupt_transfer: unsafe extern "efiapi" fn(
this: *mut Self,
device_address: u8,
endpoint_address: u8,
device_speed: Speed,
maximum_packet_length: usize,
is_new_transfer: Boolean,
data_toggle: *mut u8,
polling_interval: usize,
data_length: usize,
translator: *const TransactionTranslator,
callback_function: AsyncUsbTransferCallback,
context: *mut ffi::c_void,
) -> Status,
pub sync_interrupt_transfer: unsafe extern "efiapi" fn(
this: *mut Self,
device_address: u8,
endpoint_address: u8,
device_speed: Speed,
maximum_packet_length: usize,
data: *mut ffi::c_void,
data_length: *mut usize,
data_toggle: *mut u8,
timeout: usize,
translator: *const TransactionTranslator,
transfer_result: *mut UsbTransferStatus,
) -> Status,
pub isochronous_transfer: unsafe extern "efiapi" fn(
this: *mut Self,
device_address: u8,
endpoint_address: u8,
device_speed: Speed,
maximum_packet_length: usize,
data_buffers_number: u8,
data: *const *const ffi::c_void,
data_length: usize,
translator: *const TransactionTranslator,
transfer_result: *mut UsbTransferStatus,
) -> Status,
pub async_isochronous_transfer: unsafe extern "efiapi" fn(
this: *mut Self,
device_address: u8,
endpoint_address: u8,
device_speed: Speed,
maximum_packet_length: usize,
data_buffers_number: u8,
data: *const *const ffi::c_void,
data_length: usize,
translator: *const TransactionTranslator,
isochronous_callback: AsyncUsbTransferCallback,
context: *mut ffi::c_void,
) -> Status,
pub get_root_hub_port_status: unsafe extern "efiapi" fn(
this: *mut Self,
port_number: u8,
port_status: *mut UsbPortStatus,
) -> Status,
pub set_root_hub_port_feature: unsafe extern "efiapi" fn(
this: *mut Self,
port_number: u8,
port_feature: PortFeature,
) -> Status,
pub clear_root_hub_port_feature:
unsafe extern "efiapi" fn(this: *mut Self, port_number: u8, feature: PortFeature) -> Status,

pub major_revision: u16,
pub minor_revision: u16,
}

impl Usb2HostControllerProtocol {
pub const GUID: Guid = guid!("3e745226-9818-45b6-a2ac-d7cd0e8ba2bc");
}
89 changes: 4 additions & 85 deletions uefi-raw/src/protocol/usb/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,91 +4,10 @@ use core::ffi;

use crate::{guid, Boolean, Char16, Guid, Status};

newtype_enum! {
pub enum DataDirection: i32 => {
DATA_IN = 0,
DATA_OUT = 1,
NO_DATA = 2,
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct DeviceRequest {
pub request_type: u8,
pub request: u8,
pub value: u16,
pub index: u16,
pub length: u16,
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[repr(transparent)]
pub struct UsbTransferStatus(pub u32);

pub type AsyncUsbTransferCallback = unsafe extern "efiapi" fn(
data: *mut ffi::c_void,
data_length: usize,
context: *mut ffi::c_void,
status: UsbTransferStatus,
) -> Status;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct DeviceDescriptor {
pub length: u8,
pub descriptor_type: u8,
pub bcd_usb: u16,
pub device_class: u8,
pub device_subclass: u8,
pub device_protocol: u8,
pub max_packet_size: u8,
pub id_vendor: u16,
pub id_product: u16,
pub bcd_device: u16,
pub str_manufacturer: u8,
pub str_product: u8,
pub str_serial_number: u8,
pub num_configurations: u8,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct ConfigDescriptor {
pub length: u8,
pub descriptor_type: u8,
pub total_length: u16,
pub num_interfaces: u8,
pub configuration_value: u8,
pub configuration: u8,
pub attributes: u8,
pub max_power: u8,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct InterfaceDescriptor {
pub length: u8,
pub descriptor_type: u8,
pub interface_number: u8,
pub alternate_setting: u8,
pub num_endpoints: u8,
pub interface_class: u8,
pub interface_subclass: u8,
pub interface_protocol: u8,
pub interface: u8,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct EndpointDescriptor {
pub length: u8,
pub descriptor_type: u8,
pub endpoint_address: u8,
pub attributes: u8,
pub max_packet_size: u16,
pub interval: u8,
}
use super::{
AsyncUsbTransferCallback, ConfigDescriptor, DataDirection, DeviceDescriptor, DeviceRequest,
EndpointDescriptor, InterfaceDescriptor, UsbTransferStatus,
};

#[derive(Debug)]
#[repr(C)]
Expand Down
Loading