Skip to content
Open
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: 9 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
resolver = "3"
members = ["placeholder"]
members = ["uefi_hid", "usb_hid"]

[workspace.package]
version = "0.0.1"
Expand All @@ -11,7 +11,14 @@ description = "Patina components"
repository = "https://github.com/OpenDevicePartnership/patina-components"

[workspace.dependencies]
patina = { version = "21"}
hidparser = { version = "1" }
log = { version = "0.4", default-features = false }
mockall = { version = "0.13.0" }
num_enum = { version = "0.7", default-features = false }
# git path is a temporary placeholder until the appropriate protocol branches are checked in upstream.
patina = { git = "https://github.com/joschock/patina", branch = "usb_hid_protocol_defs" }
r-efi = { version = "5.0.0", default-features = false }
scroll = { version = "0.13", default-features = false, features = ["derive"] }

[workspace.lints.clippy]
undocumented_unsafe_blocks = "warn"
15 changes: 15 additions & 0 deletions cspell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,23 @@ caseSensitive: false
allowCompoundWords: true
words:
- "Depex"
- "Deque"
- "descs"
- "EDKII"
- "efiapi"
- "gread"
- "guids"
- "gwrite"
- "lctrl"
- "lshift"
- "mdbook"
- "NOERROR"
- "numlock"
- "numpad"
- "Pread"
- "pwrite"
- "sysreg"
- "unshifted"
- "Unregisters"
- "unsignaled"
- "withf"
12 changes: 0 additions & 12 deletions placeholder/Cargo.toml

This file was deleted.

8 changes: 0 additions & 8 deletions placeholder/src/lib.rs

This file was deleted.

28 changes: 28 additions & 0 deletions uefi_hid/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "uefi_hid"
description = "UEFI HID (Human Interface Device) support as a Patina component."
version.workspace = true
license.workspace = true
edition.workspace = true
rust-version.workspace = true
repository.workspace = true
publish = false

[lints]
workspace = true

[features]
default = ["ctrl-alt-del"]
ctrl-alt-del = []

[dependencies]
hidparser = { workspace = true }
log = { workspace = true }
num_enum = { workspace = true }
patina = { workspace = true }
r-efi = { workspace = true }
scroll = { workspace = true }

[dev-dependencies]
mockall = { workspace = true }
patina = { workspace = true, features = ["mockall"] }
98 changes: 98 additions & 0 deletions uefi_hid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<!-- Copyright (c) Microsoft Corporation. SPDX-License-Identifier: Apache-2.0 -->
# UEFI HID

## Overview

This Patina component provides Human Interface Device (HID) support for UEFI. It consumes the
[HidIo](https://github.com/microsoft/mu_plus/blob/release/202502/HidPkg/Include/Protocol/HidIo.h) protocol and
produces standard UEFI input protocols for keyboard and pointer HID devices:

- **SimpleTextInput** (`EFI_SIMPLE_TEXT_INPUT_PROTOCOL`)
- **SimpleTextInputEx** (`EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL`)
- **AbsolutePointer** (`EFI_ABSOLUTE_POINTER_PROTOCOL`)

## Architecture

The component installs a UEFI Driver Binding that manages HID device instances. When the driver is
started on a controller that exposes the HidIo protocol, it:

1. Opens the HidIo protocol on the controller.
2. Parses the HID report descriptor to identify keyboard and pointer usages.
3. Creates the appropriate input protocol handlers (keyboard and/or pointer).
4. Installs the corresponding UEFI input protocols on the controller handle:
- **SimpleTextInput** and **SimpleTextInputEx** for keyboard devices.
- **AbsolutePointer** for pointer and touch devices.
5. Registers a report callback to receive asynchronous HID input reports.

### Report Processing

Incoming HID reports are buffered through a `ReportQueue` rather than being processed inline from the
HidIo producer's callback. This ensures all report processing occurs at a consistent `TPL_CALLBACK`
regardless of the producer's calling TPL:

1. **Report callback** (any TPL): pushes raw HID report bytes onto a queue and signals a `TPL_CALLBACK` event.
2. **Event handler** (`TPL_CALLBACK`): dequeues all pending reports and dispatches them to receivers.

## Modules

| Module | Description |
|---|---|
| `hid` | Driver binding implementation that manages HID instances on controllers. |
| `hid_io` | HidIo protocol FFI bindings, report queue, and receiver traits (`HidIo`, `HidReportReceiver`). |
| `keyboard` | Keyboard HID handler — translates HID key reports into UEFI keystrokes using HII keyboard layouts, and produces SimpleTextInput / SimpleTextInputEx protocol interfaces. |
| `pointer` | Pointer HID handler — translates HID pointer/touch reports into absolute pointer state and produces the AbsolutePointer protocol interface. |

## Features

| Feature | Default | Description |
|---|---|---|
| `ctrl-alt-del` | ✅ | Enables Ctrl+Alt+Delete to trigger a system reset via UEFI Runtime Services. |

## Dependencies

Key crate dependencies (see `Cargo.toml` for the full list):

- [`hidparser`](https://crates.io/crates/hidparser) — HID report descriptor parsing.
- [`patina`](https://crates.io/crates/patina) — Patina component SDK (boot services, driver binding, protocol interfaces).
- [`r-efi`](https://crates.io/crates/r-efi) — Rust UEFI type definitions.

## Platform Integration

To include `uefi_hid` in a Patina binary, add the crate as a dependency and register the component
in the platform's `ComponentInfo` implementation.

1. Add the dependency to the binary crate's `Cargo.toml`:

```toml
[dependencies]
uefi_hid = { version = "20" }
```

2. Register the component in the `components` function:

```rust
impl ComponentInfo for MyPlatform {
fn components(mut add: Add<Component>) {
// ...other components...
add.component(uefi_hid::UefiHidComponent);
}
}
```

The driver binding will automatically attach to any controller that exposes the HidIo protocol. A
HidIo producer (e.g. a USB HID driver) must be present in the platform firmware for this component
to be functional.

The `ctrl-alt-del` feature is enabled by default. To disable it:

```toml
uefi_hid = { path = "../components/uefi_hid", default-features = false }
```

## Testing

Unit tests use `mockall` and `patina`'s mock boot services:

```sh
cargo test -p uefi_hid
```
Loading
Loading