Skip to content
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

Add HidIo protocol, USB HidIo implementation, and UefiHidDxe Rust input driver [Rebase & FF] #324

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
11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@

# Add packages that generate binaries here
members = [
"MsCorePkg/HelloWorldRustDxe",
"HidPkg/Crates/AbsolutePointer",
"HidPkg/Crates/HidIo",
"HidPkg/UefiHidDxe",
"MsCorePkg/HelloWorldRustDxe"
]

# Add packages that generate libraries here
[workspace.dependencies]
RustAdvancedLoggerDxe = {path = "AdvLoggerPkg/Crates/RustAdvancedLoggerDxe"}
RustBootServicesAllocatorDxe = {path = "MsCorePkg/Crates/RustBootServicesAllocatorDxe"}
HidIo = {path = "HidPkg/Crates/HidIo"}
AbsolutePointer = {path = "HidPkg/Crates/AbsolutePointer"}

hidparser = {git = "https://github.com/microsoft/mu_rust_hid.git", branch = "main"}

r-efi = "4.0.0"
rustversion = "1.0.14"
spin = "0.9.8"
memoffset = "0.9.0"
13 changes: 13 additions & 0 deletions HidPkg/Crates/AbsolutePointer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "AbsolutePointer"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
name = "absolute_pointer"
path = "src/lib.rs"

[dependencies]
r-efi = {workspace=true}
114 changes: 114 additions & 0 deletions HidPkg/Crates/AbsolutePointer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//!
//! ## Summary
//! This module defines the Absolute Pointer protocol.
//!
//! Refer to UEFI spec version 2.10 section 12.7.
//!
//! ## License
//! Copyright (c) Microsoft Corporation. All rights reserved.
//! SPDX-License-Identifier: BSD-2-Clause-Patent
//!
//!
#![no_std]

pub mod protocol {
use r_efi::efi::{Event, Guid, Status};

/// Absolute pointer interface GUID: 8D59D32B-C655-4AE9-9B15-F25904992A43
pub const PROTOCOL_GUID: Guid =
Guid::from_fields(0x8D59D32B, 0xC655, 0x4AE9, 0x9B, 0x15, &[0xF2, 0x59, 0x04, 0x99, 0x2A, 0x43]);

/// This function resets the pointer device hardware. As part of initialization process, the firmware/device will make
/// a quick but reasonable attempt to verify that the device is functioning. If the ExtendedVerification flag is TRUE
/// the firmware may take an extended amount of time to verify the device is operating on reset. Otherwise the reset
/// operation is to occur as quickly as possible. The hardware verification process is not defined by this
/// specification and is left up to the platform firmware or driver to implement.
///
/// # Arguments
/// * `this` - A pointer to the AbsolutePointer Instance
/// * `extended_verification` - indicates whether extended reset is requested.
///
/// # Return Values
/// * `Status::SUCCESS` - The device was reset
/// * `Status::DEVICE_ERROR` - The device is not functioning correctly and could not be reset.
///
pub type AbsolutePointerReset = extern "efiapi" fn(this: *const Protocol, extended_verification: bool) -> Status;

/// This function retrieves the current state of a pointer device. This includes information on the active state
/// associated with the pointer device and the current position of the axes associated with the pointer device.
/// If the state of the pointer device has not changed since the last call to GetState(), then EFI_NOT_READY is
/// returned. If the state of the pointer device has changed since the last call to GetState(), then the state
/// information is placed in State, and efi::Status::SUCCESS is returned. If a device error occurs while attempting to
/// retrieve the state information, then efi::Status::DEVICE_ERROR is returned.
///
/// # Arguments
/// * `this` - A pointer to the AbsolutePointer Instance
/// * `state` - A pointer to the state information on the pointer device.
///
/// # Return Values
/// * `Status::SUCCESS` - The state of the pointer device was returned in state.
/// * `Status::NOT_READY` - The state of the pointer device has not changed since the last call to this function.
/// * `Status::DEVICE_ERROR` - A device error occurred while attempting to retrieve the pointer device current state.
///
pub type AbsolutePointerGetState =
extern "efiapi" fn(this: *const Protocol, state: *mut AbsolutePointerState) -> Status;

/// Describes the current state of the pointer.
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct AbsolutePointerState {
/// The unsigned position of the activation on the x-axis. If the absolute_min_x and the absolute_max_x fields of
/// the AbsolutePointerMode structure are both 0, then this pointer device does not support an x-axis, and this
/// field must be ignored.
pub current_x: u64,
/// The unsigned position of the activation on the y-axis. If the absolute_min_y and the absolute_max_y fields of
/// the AbsolutePointerMode structure are both 0, then this pointer device does not support an y-axis, and this
/// field must be ignored.
pub current_y: u64,
/// The unsigned position of the activation on the z-axis. If the absolute_min_z and the absolute_max_z fields of
/// the AbsolutePointerMode structure are both 0, then this pointer device does not support an z-axis, and this
/// field must be ignored.
pub current_z: u64,
/// Bits are set to 1 in this field to indicate that device buttons are active.
pub active_buttons: u32,
}

/// Describes the mode of the pointer.
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct AbsolutePointerMode {
pub absolute_min_x: u64,
/// The Absolute Minimum of the device on the x-axis
pub absolute_min_y: u64,
/// The Absolute Minimum of the device on the y-axis.
pub absolute_min_z: u64,
/// The Absolute Minimum of the device on the z-axis.
/// The Absolute Maximum of the device on the x-axis. If 0, and absolute_min_x is 0, then x-axis is unsupported.
pub absolute_max_x: u64,
/// The Absolute Maximum of the device on the y-axis. If 0, and absolute_min_y is 0, then y-axis is unsupported.
pub absolute_max_y: u64,
/// The Absolute Maximum of the device on the z-axis. If 0, and absolute_min_z is 0, then z-axis is unsupported.
pub absolute_max_z: u64,
/// Supported device attributes.
pub attributes: u32,
}

/// If set in [`AbsolutePointerMode::attributes`], indicates this device supports an alternate button input.
pub const SUPPORTS_ALT_ACTIVE: u32 = 0x00000001;
/// If set in [`AbsolutePointerMode::attributes`], indicates this device returns pressure data in current_z.
pub const SUPPORTS_PRESSURE_AS_Z: u32 = 0x00000002;

/// The EFI_ABSOLUTE_POINTER_PROTOCOL provides a set of services for a pointer device that can be used as an input
/// device from an application written to this specification. The services include the ability to: reset the pointer
/// device, retrieve the state of the pointer device, and retrieve the capabilities of the pointer device. The service
/// also provides certain data items describing the device.
#[derive(Debug)]
#[repr(C)]
pub struct Protocol {
pub reset: AbsolutePointerReset,
pub get_state: AbsolutePointerGetState,
/// Event to use with WaitForEvent() to wait for input from the pointer device.
pub wait_for_input: Event,
pub mode: *mut AbsolutePointerMode,
}
}
13 changes: 13 additions & 0 deletions HidPkg/Crates/HidIo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "HidIo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
name = "hid_io"
path = "src/lib.rs"

[dependencies]
r-efi = {workspace=true}
153 changes: 153 additions & 0 deletions HidPkg/Crates/HidIo/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
//! ## Summary
//! This protocol provides access to HID devices.
//!
//! ## License
//! Copyright (c) Microsoft Corporation. All rights reserved.
//! SPDX-License-Identifier: BSD-2-Clause-Patent
//!
#![no_std]

pub mod protocol {
use core::ffi::c_void;

use r_efi::efi::{Guid, Status};

/// HidIo interface GUID: 3EA93936-6BF4-49D6-AA50-D9F5B9AD8CFF
pub const GUID: Guid =
Guid::from_fields(0x3ea93936, 0x6bf4, 0x49d6, 0xaa, 0x50, &[0xd9, 0xf5, 0xb9, 0xad, 0x8c, 0xff]);

#[repr(C)]
pub enum HidReportType {
InputReport = 1,
OutputReport = 2,
Feature = 3,
}

/// Retrieve the HID Report Descriptor from the device.
///
/// # Arguments
///
/// * `this` - A pointer to the HidIo Instance
/// * `report_descriptor_size` - On input, the size of the buffer allocated to hold the descriptor. On output, the
/// actual size of the descriptor. May be set to zero to query the required size for the
/// descriptor.
/// * `report_descriptor_buffer` - A pointer to the buffer to hold the descriptor. May be NULL if ReportDescriptorSize
/// is zero.
/// # Return values
/// * `Status::SUCCESS` - Report descriptor successfully returned.
/// * `Status::BUFFER_TOO_SMALL` - The provided buffer is not large enough to hold the descriptor.
/// * `Status::INVALID_PARAMETER` - Invalid input parameters.
/// * `Status::NOT_FOUND` - The device does not have a report descriptor.
/// * Other - Unexpected error reading descriptor.
///
pub type HidIoGetReportDescriptor = extern "efiapi" fn(
this: *const Protocol,
report_descriptor_size: *mut usize,
report_descriptor_buffer: *mut c_void,
) -> Status;

/// Retrieves a single report from the device.
///
/// # Arguments
///
/// * `this` - A pointer to the HidIo Instance
/// * `report_id` - Specifies which report to return if the device supports multiple input reports. Set to zero if
/// ReportId is not present.
/// * `report_type` - Indicates the type of report type to retrieve. 1-Input, 3-Feature.
/// * `report_buffer_size` - Indicates the size of the provided buffer to receive the report.
/// * `report_buffer` - Pointer to the buffer to receive the report.
///
/// # Return values
/// * `Status::SUCCESS` - Report successfully returned.
/// * `Status::OUT_OF_RESOURCES` - The provided buffer is not large enough to hold the report.
/// * `Status::INVALID_PARAMETER` - Invalid input parameters.
/// * Other - Unexpected error reading report.
///
pub type HidIoGetReport = extern "efiapi" fn(
this: *const Protocol,
report_id: u8,
report_type: HidReportType,
report_buffer_size: usize,
report_buffer: *mut c_void,
) -> Status;

/// Sends a single report to the device.
///
/// # Arguments
///
/// * `this` - A pointer to the HidIo Instance
/// * `report_id` - Specifies which report to send if the device supports multiple input reports. Set to zero if
/// ReportId is not present.
/// * `report_type` - Indicates the type of report type to retrieve. 2-Output, 3-Feature.
/// * `report_buffer_size` - Indicates the size of the provided buffer holding the report to send.
/// * `report_buffer` - Pointer to the buffer holding the report to send.
///
/// # Return values
/// * `Status::SUCCESS` - Report successfully transmitted.
/// * `Status::INVALID_PARAMETER` - Invalid input parameters.
/// * Other - Unexpected error transmitting report.
///
pub type HidIoSetReport = extern "efiapi" fn(
this: *const Protocol,
report_id: u8,
report_type: HidReportType,
report_buffer_size: usize,
report_buffer: *mut c_void,
) -> Status;

/// Report received callback function.
///
/// # Arguments
///
/// * `report_buffer_size` - Indicates the size of the provided buffer holding the received report.
/// * `report_buffer` - Pointer to the buffer holding the report.
/// * `context` - Context provided when the callback was registered.
///
pub type HidIoReportCallback =
extern "efiapi" fn(report_buffer_size: u16, report_buffer: *mut c_void, context: *mut c_void);

/// Registers a callback function to receive asynchronous input reports from the device. The device driver will do any
/// necessary initialization to configure the device to send reports.
///
/// # Arguments
///
/// * `this` - A pointer to the HidIo Instance
/// * `callback` - Callback function to handle reports as they are received.
/// * `context` - Context that will be provided to the callback function.
///
/// # Return values
/// * `Status::SUCCESS` - Callback successfully registered.
/// * `Status::INVALID_PARAMETER` - Invalid input parameters.
/// * `Status::ALREADY_STARTED` - Callback function is already registered.
/// * Other - Unexpected error registering callback or initiating report generation from device.
///
pub type HidIoRegisterReportCallback =
extern "efiapi" fn(this: *const Protocol, callback: HidIoReportCallback, context: *mut c_void) -> Status;

/// Unregisters a previously registered callback function. The device driver will do any necessary initialization to
/// configure the device to stop sending reports.
///
/// # Arguments
///
/// * `this` - A pointer to the HidIo Instance
/// * `callback` - Callback function to unregister.
///
/// # Return values
/// * `Status::SUCCESS` - Callback successfully unregistered.
/// * `Status::INVALID_PARAMETER` - Invalid input parameters.
/// * `Status::NOT_STARTED` - Callback function was not previously registered.
/// * Other - Unexpected error unregistering report or disabling report generation from device.
///
pub type HidIoUnregisterReportCallback =
extern "efiapi" fn(this: *const Protocol, callback: HidIoReportCallback) -> Status;

/// The HID_IO protocol provides a set of services for interacting with a HID device.
#[repr(C)]
pub struct Protocol {
pub get_report_descriptor: HidIoGetReportDescriptor,
pub get_report: HidIoGetReport,
pub set_report: HidIoSetReport,
pub register_report_callback: HidIoRegisterReportCallback,
pub unregister_report_callback: HidIoUnregisterReportCallback,
}
}
4 changes: 4 additions & 0 deletions HidPkg/HidPkg.dec
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#
gHidPointerProtocolGuid = { 0x80b5ee6e, 0xcbd8, 0x43ae, { 0xb6, 0xac, 0x10, 0x91, 0x7b, 0x25, 0x35, 0xb7 }}

## HID IO Protocol GUID
# {3EA93936-6BF4-49D6-AA50-D9F5B9AD8CFF}
gHidIoProtocolGuid = {0x3ea93936, 0x6bf4, 0x49d6, { 0xaa, 0x50, 0xd9, 0xf5, 0xb9, 0xad, 0x8c, 0xff}}

[Guids]
gHidPkgTokenSpaceGuid = {0x347d3cd6, 0xdf7d, 0x4397, {0xa3, 0x7a, 0x4c, 0x0f, 0x46, 0xdb, 0xdb, 0xff}}

Expand Down
2 changes: 2 additions & 0 deletions HidPkg/HidPkg.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
HidPkg/HidMouseAbsolutePointerDxe/HidMouseAbsolutePointerDxe.inf
HidPkg/UsbKbHidDxe/UsbKbHidDxe.inf
HidPkg/UsbMouseHidDxe/UsbMouseHidDxe.inf
HidPkg/UsbHidDxe/UsbHidDxe.inf
HidPkg/UefiHidDxe/UefiHidDxe.inf

[BuildOptions]
#force deprecated interfaces off
Expand Down
Loading