Compare commits
8 Commits
386aecb58f
...
f8ee319fbe
| Author | SHA1 | Date | |
|---|---|---|---|
| f8ee319fbe | |||
|
30f8cda48e
|
|||
| 6d944dfef3 | |||
| 333c92c3e0 | |||
| bd5b8f4e85 | |||
| 937b3312eb | |||
| 4bca6857b4 | |||
| c65fd1d218 |
1
.rustfmt.toml
Normal file
1
.rustfmt.toml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
style_edition = "2024"
|
||||||
145
Cargo.lock
generated
145
Cargo.lock
generated
@@ -36,7 +36,10 @@ dependencies = [
|
|||||||
"embassy-sync",
|
"embassy-sync",
|
||||||
"embassy-time",
|
"embassy-time",
|
||||||
"embassy-usb",
|
"embassy-usb",
|
||||||
|
"embedded-alloc",
|
||||||
|
"futures-util",
|
||||||
"panic-probe",
|
"panic-probe",
|
||||||
|
"portable-atomic",
|
||||||
"usbd-hid",
|
"usbd-hid",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -76,6 +79,12 @@ dependencies = [
|
|||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-set"
|
name = "bit-set"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -173,6 +182,12 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-default"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cordyceps"
|
name = "cordyceps"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
@@ -212,7 +227,7 @@ checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -276,7 +291,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim",
|
"strsim",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -287,7 +302,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -324,7 +339,7 @@ dependencies = [
|
|||||||
"defmt-parser",
|
"defmt-parser",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -411,7 +426,7 @@ dependencies = [
|
|||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -587,6 +602,18 @@ dependencies = [
|
|||||||
"embedded-io-async 0.7.0",
|
"embedded-io-async 0.7.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "embedded-alloc"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2db634e07f552215f7a3572dc0a4d29760c637fcea5a8c18d2cc291f782c216c"
|
||||||
|
dependencies = [
|
||||||
|
"const-default",
|
||||||
|
"critical-section",
|
||||||
|
"linked_list_allocator",
|
||||||
|
"rlsf",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-hal"
|
name = "embedded-hal"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
@@ -720,9 +747,12 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.32"
|
version = "0.3.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7"
|
||||||
|
dependencies = [
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
@@ -730,6 +760,26 @@ version = "0.3.32"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
|
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"portable-atomic",
|
||||||
|
"portable-atomic-util",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generator"
|
name = "generator"
|
||||||
version = "0.8.9"
|
version = "0.8.9"
|
||||||
@@ -888,6 +938,12 @@ version = "0.2.186"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked_list_allocator"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b23ac50abb8261cb38c6e2a7192d3302e0836dac1628f6a93b82b4fad185897"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litrs"
|
name = "litrs"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@@ -994,7 +1050,7 @@ checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1118,14 +1174,26 @@ dependencies = [
|
|||||||
"proc-macro-error2",
|
"proc-macro-error2",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic"
|
name = "portable-atomic"
|
||||||
version = "1.13.1"
|
version = "1.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic-util"
|
||||||
|
version = "0.2.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618"
|
||||||
|
dependencies = [
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "precomputed-hash"
|
name = "precomputed-hash"
|
||||||
@@ -1152,7 +1220,7 @@ dependencies = [
|
|||||||
"proc-macro-error-attr2",
|
"proc-macro-error-attr2",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1238,6 +1306,19 @@ version = "0.8.53"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4"
|
checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rlsf"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"const-default",
|
||||||
|
"libc",
|
||||||
|
"rustversion",
|
||||||
|
"svgbobdoc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rp-pac"
|
name = "rp-pac"
|
||||||
version = "7.0.0"
|
version = "7.0.0"
|
||||||
@@ -1334,7 +1415,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1374,6 +1455,12 @@ version = "1.0.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
|
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.15.2"
|
version = "1.15.2"
|
||||||
@@ -1432,6 +1519,30 @@ version = "0.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "svgbobdoc"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.118"
|
version = "2.0.118"
|
||||||
@@ -1478,7 +1589,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1509,7 +1620,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1618,7 +1729,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"serde",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
"usbd-hid-descriptors",
|
"usbd-hid-descriptors",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1715,5 +1826,5 @@ checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.118",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -13,5 +13,8 @@ embassy-rp = { version = "0.10.0", features = ["chrono", "defmt", "rp2040", "rt"
|
|||||||
embassy-sync = { version = "0.8.0", features = ["defmt"] }
|
embassy-sync = { version = "0.8.0", features = ["defmt"] }
|
||||||
embassy-time = "0.5.1"
|
embassy-time = "0.5.1"
|
||||||
embassy-usb = { version = "0.6.0", features = ["defmt"] }
|
embassy-usb = { version = "0.6.0", features = ["defmt"] }
|
||||||
|
embedded-alloc = "0.7.0"
|
||||||
|
futures-util = { version = "0.3.33", default-features = false, features = ["alloc", "portable-atomic-alloc"] }
|
||||||
panic-probe = { version = "1.0.0", features = ["defmt"] }
|
panic-probe = { version = "1.0.0", features = ["defmt"] }
|
||||||
|
portable-atomic = { version = "1.14.0", default-features = false, features = ["critical-section"] }
|
||||||
usbd-hid = { version = "0.10.0", features = ["defmt"] }
|
usbd-hid = { version = "0.10.0", features = ["defmt"] }
|
||||||
|
|||||||
19
prek.toml
Normal file
19
prek.toml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[[repos]]
|
||||||
|
repo = "local"
|
||||||
|
hooks = [
|
||||||
|
{
|
||||||
|
id = "cargo-fmt",
|
||||||
|
name = "cargo-fmt",
|
||||||
|
language = "system",
|
||||||
|
entry = "cargo fmt --",
|
||||||
|
types = ["rust"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id = "cargo-clippy",
|
||||||
|
name = "cargo-clippy",
|
||||||
|
language = "system",
|
||||||
|
entry = "cargo clippy -- -Dwarnings",
|
||||||
|
types = ["rust"],
|
||||||
|
pass_filenames = false,
|
||||||
|
},
|
||||||
|
]
|
||||||
108
src/keyboard.rs
108
src/keyboard.rs
@@ -1,83 +1,14 @@
|
|||||||
use core::sync::atomic::Ordering;
|
use crate::usb::KeyboardEvent;
|
||||||
|
|
||||||
use defmt::*;
|
|
||||||
use embassy_rp::gpio::Input;
|
use embassy_rp::gpio::Input;
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
|
use embassy_sync::blocking_mutex::raw::RawMutex;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_sync::channel::Sender;
|
||||||
use embassy_usb::{
|
use futures_util::stream::{FuturesUnordered, StreamExt};
|
||||||
class::hid::{HidProtocolMode, HidWriter},
|
|
||||||
driver::Driver,
|
|
||||||
};
|
|
||||||
use usbd_hid::descriptor::KeyboardReport;
|
|
||||||
|
|
||||||
use crate::HID_PROTOCOL_MODE;
|
|
||||||
|
|
||||||
const WRITE_N: usize = 8;
|
|
||||||
|
|
||||||
pub struct Key<'a> {
|
pub struct Key<'a> {
|
||||||
button: Input<'a>,
|
button: Input<'a>,
|
||||||
value: char,
|
value: char,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Key<'_> {
|
|
||||||
pub async fn process<'d, D: Driver<'d>>(
|
|
||||||
&mut self,
|
|
||||||
mut writer: Mutex<CriticalSectionRawMutex, HidWriter<'d, D, WRITE_N>>,
|
|
||||||
) {
|
|
||||||
loop {
|
|
||||||
self.button.wait_for_high().await;
|
|
||||||
info!("Button {} pressed", self.value);
|
|
||||||
|
|
||||||
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
|
|
||||||
match writer.get_mut().write(&[0, 0, 4, 0, 0, 0, 0, 0]).await {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(e) => warn!("Failed to send boot report: {:?}", e),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// Create a report with the A key pressed. (no shift modifier)
|
|
||||||
let report = KeyboardReport {
|
|
||||||
keycodes: [4, 0, 0, 0, 0, 0],
|
|
||||||
leds: 0,
|
|
||||||
modifier: 0,
|
|
||||||
reserved: 0,
|
|
||||||
};
|
|
||||||
// Send the report.
|
|
||||||
match writer.get_mut().write_serialize(&report).await {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(e) => warn!("Failed to send report: {:?}", e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debounce
|
|
||||||
Timer::after(Duration::from_millis(50)).await;
|
|
||||||
|
|
||||||
self.button.wait_for_low().await;
|
|
||||||
info!("Button {} unpressed", self.value);
|
|
||||||
|
|
||||||
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8 {
|
|
||||||
match writer.get_mut().write(&[0, 0, 0, 0, 0, 0, 0, 0]).await {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(e) => warn!("Failed to send boot report: {:?}", e),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
let report = KeyboardReport {
|
|
||||||
keycodes: [0, 0, 0, 0, 0, 0],
|
|
||||||
leds: 0,
|
|
||||||
modifier: 0,
|
|
||||||
reserved: 0,
|
|
||||||
};
|
|
||||||
match writer.get_mut().write_serialize(&report).await {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(e) => warn!("Failed to send report: {:?}", e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debounce
|
|
||||||
Timer::after(Duration::from_millis(50)).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Key<'_> {
|
impl Key<'_> {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub async fn set_value(mut self, value: char) {
|
pub async fn set_value(mut self, value: char) {
|
||||||
@@ -85,8 +16,7 @@ impl Key<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Keyboard<'d, D: Driver<'d>, const KEY_N: usize> {
|
pub struct Keyboard<'d, const KEY_N: usize> {
|
||||||
writer: Mutex<CriticalSectionRawMutex, HidWriter<'d, D, WRITE_N>>,
|
|
||||||
keys: [Option<Key<'d>>; KEY_N],
|
keys: [Option<Key<'d>>; KEY_N],
|
||||||
num_keys: usize,
|
num_keys: usize,
|
||||||
}
|
}
|
||||||
@@ -95,10 +25,9 @@ pub enum KeyboardError {
|
|||||||
MaxKeys,
|
MaxKeys,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, D: Driver<'d>, const KEY_N: usize> Keyboard<'d, D, KEY_N> {
|
impl<'d, const KEY_N: usize> Keyboard<'d, KEY_N> {
|
||||||
pub fn new(writer: HidWriter<'d, D, WRITE_N>) -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
writer: Mutex::new(writer),
|
|
||||||
keys: [const { None }; KEY_N],
|
keys: [const { None }; KEY_N],
|
||||||
num_keys: 0,
|
num_keys: 0,
|
||||||
}
|
}
|
||||||
@@ -116,8 +45,25 @@ impl<'d, D: Driver<'d>, const KEY_N: usize> Keyboard<'d, D, KEY_N> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn process(mut self) {
|
pub async fn process<'ch, M, const N: usize>(mut self, sender: Sender<'ch, M, KeyboardEvent, N>)
|
||||||
// TODO: Make this a loop that is concatinated together
|
where
|
||||||
self.keys[0].as_mut().unwrap().process(self.writer).await;
|
M: RawMutex,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
self.keys
|
||||||
|
.iter_mut()
|
||||||
|
.filter_map(|opt| opt.as_mut().map(|s| s.button.wait_for_any_edge()))
|
||||||
|
.collect::<FuturesUnordered<_>>()
|
||||||
|
.next()
|
||||||
|
.await;
|
||||||
|
for key in self.keys.iter_mut().filter_map(|opt| opt.as_mut()) {
|
||||||
|
sender
|
||||||
|
.send(KeyboardEvent {
|
||||||
|
key: key.value,
|
||||||
|
action: key.button.get_level().into(),
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
165
src/main.rs
165
src/main.rs
@@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
mod heartbeat;
|
mod heartbeat;
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
|
mod usb;
|
||||||
|
|
||||||
use crate::heartbeat::heartbeat;
|
use crate::heartbeat::heartbeat;
|
||||||
use crate::keyboard::Keyboard;
|
use crate::keyboard::Keyboard;
|
||||||
use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::join::join;
|
use embassy_futures::join::join;
|
||||||
@@ -14,12 +14,9 @@ use embassy_rp::bind_interrupts;
|
|||||||
use embassy_rp::gpio::{Input, Level, Output, Pull};
|
use embassy_rp::gpio::{Input, Level, Output, Pull};
|
||||||
use embassy_rp::peripherals::USB;
|
use embassy_rp::peripherals::USB;
|
||||||
use embassy_rp::usb::{Driver, InterruptHandler};
|
use embassy_rp::usb::{Driver, InterruptHandler};
|
||||||
use embassy_usb::class::hid::{
|
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||||
HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
|
use embassy_sync::channel::Channel;
|
||||||
};
|
use embedded_alloc::LlffHeap as Heap;
|
||||||
use embassy_usb::control::OutResponse;
|
|
||||||
use embassy_usb::{Builder, Config, Handler};
|
|
||||||
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
|
|
||||||
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
@@ -27,59 +24,27 @@ bind_interrupts!(struct Irqs {
|
|||||||
USBCTRL_IRQ => InterruptHandler<USB>;
|
USBCTRL_IRQ => InterruptHandler<USB>;
|
||||||
});
|
});
|
||||||
|
|
||||||
static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
|
#[global_allocator]
|
||||||
|
static HEAP: Heap = Heap::empty();
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
|
static mut HEAP_MEM: [u8; 4096] = [0; 4096];
|
||||||
|
unsafe {
|
||||||
|
HEAP.init(
|
||||||
|
core::ptr::addr_of!(HEAP_MEM) as usize,
|
||||||
|
core::mem::size_of::<[u8; 4096]>(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let keyboard_events: Channel<ThreadModeRawMutex, usb::KeyboardEvent, 64> = Channel::new();
|
||||||
|
|
||||||
let p = embassy_rp::init(Default::default());
|
let p = embassy_rp::init(Default::default());
|
||||||
|
|
||||||
// Create the driver, from the HAL.
|
// Create the driver, from the HAL.
|
||||||
let driver = Driver::new(p.USB, Irqs);
|
let driver = Driver::new(p.USB, Irqs);
|
||||||
|
let mut usb_buf = usb::UsbKeyboardBuf::new();
|
||||||
// Create embassy-usb Config
|
let usbkey = usb::UsbKeyboard::create_usb(&mut usb_buf, driver);
|
||||||
let mut config = Config::new(0xc0de, 0xcafe);
|
|
||||||
config.manufacturer = Some("Nicholas Mello");
|
|
||||||
config.product = Some("Pi Pico Arcade Keyboard");
|
|
||||||
config.serial_number = Some("00000001");
|
|
||||||
config.max_power = 100;
|
|
||||||
config.max_packet_size_0 = 64;
|
|
||||||
config.composite_with_iads = false;
|
|
||||||
config.device_class = 0;
|
|
||||||
config.device_sub_class = 0;
|
|
||||||
config.device_protocol = 0;
|
|
||||||
|
|
||||||
// Create embassy-usb DeviceBuilder using the driver and config.
|
|
||||||
// It needs some buffers for building the descriptors.
|
|
||||||
let mut config_descriptor = [0; 256];
|
|
||||||
let mut bos_descriptor = [0; 256];
|
|
||||||
// You can also add a Microsoft OS descriptor.
|
|
||||||
let mut msos_descriptor = [0; 256];
|
|
||||||
let mut control_buf = [0; 64];
|
|
||||||
let mut request_handler = MyRequestHandler {};
|
|
||||||
let mut device_handler = MyDeviceHandler::new();
|
|
||||||
|
|
||||||
let mut state = State::new();
|
|
||||||
|
|
||||||
let mut builder = Builder::new(
|
|
||||||
driver,
|
|
||||||
config,
|
|
||||||
&mut config_descriptor,
|
|
||||||
&mut bos_descriptor,
|
|
||||||
&mut msos_descriptor,
|
|
||||||
&mut control_buf,
|
|
||||||
);
|
|
||||||
|
|
||||||
builder.handler(&mut device_handler);
|
|
||||||
|
|
||||||
// Create classes on the builder.
|
|
||||||
let config = embassy_usb::class::hid::Config {
|
|
||||||
report_descriptor: KeyboardReport::desc(),
|
|
||||||
request_handler: None,
|
|
||||||
poll_ms: 60,
|
|
||||||
max_packet_size: 64,
|
|
||||||
hid_subclass: HidSubclass::Boot,
|
|
||||||
hid_boot_protocol: HidBootProtocol::Keyboard,
|
|
||||||
};
|
|
||||||
let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
|
|
||||||
|
|
||||||
// Set up the signal pin that will be used to trigger the keyboard.
|
// Set up the signal pin that will be used to trigger the keyboard.
|
||||||
let mut signal_pin = Input::new(p.PIN_16, Pull::None);
|
let mut signal_pin = Input::new(p.PIN_16, Pull::None);
|
||||||
@@ -87,9 +52,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
// Enable the schmitt trigger to slightly debounce.
|
// Enable the schmitt trigger to slightly debounce.
|
||||||
signal_pin.set_schmitt(true);
|
signal_pin.set_schmitt(true);
|
||||||
|
|
||||||
let (reader, writer) = hid.split();
|
let mut keyboard = Keyboard::<1>::new();
|
||||||
|
|
||||||
let mut keyboard = Keyboard::<_, 1>::new(writer);
|
|
||||||
match keyboard.add_key(signal_pin, 'a') {
|
match keyboard.add_key(signal_pin, 'a') {
|
||||||
Ok(()) => info!("Key 'a' registered"),
|
Ok(()) => info!("Key 'a' registered"),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@@ -97,95 +60,11 @@ async fn main(_spawner: Spawner) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let out_fut = async {
|
|
||||||
reader.run(false, &mut request_handler).await;
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut usb = builder.build();
|
|
||||||
let led = Output::new(p.PIN_25, Level::Low);
|
let led = Output::new(p.PIN_25, Level::Low);
|
||||||
|
|
||||||
join(
|
join(
|
||||||
join(usb.run(), heartbeat(led)),
|
join(usbkey.run(keyboard_events.receiver()), heartbeat(led)),
|
||||||
join(keyboard.process(), out_fut),
|
keyboard.process(keyboard_events.sender()),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MyRequestHandler {}
|
|
||||||
|
|
||||||
impl RequestHandler for MyRequestHandler {
|
|
||||||
fn get_report(&mut self, id: ReportId, _buf: &mut [u8]) -> Option<usize> {
|
|
||||||
info!("Get report for {:?}", id);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_report(&mut self, id: ReportId, data: &[u8]) -> OutResponse {
|
|
||||||
info!("Set report for {:?}: {=[u8]}", id, data);
|
|
||||||
OutResponse::Accepted
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_protocol(&self) -> HidProtocolMode {
|
|
||||||
let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
|
|
||||||
info!("The current HID protocol mode is: {}", protocol);
|
|
||||||
protocol
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
|
|
||||||
info!("Switching to HID protocol mode: {}", protocol);
|
|
||||||
HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
|
|
||||||
OutResponse::Accepted
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
|
|
||||||
info!("Set idle rate for {:?} to {:?}", id, dur);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_idle_ms(&mut self, id: Option<ReportId>) -> Option<u32> {
|
|
||||||
info!("Get idle rate for {:?}", id);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MyDeviceHandler {
|
|
||||||
configured: AtomicBool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MyDeviceHandler {
|
|
||||||
fn new() -> Self {
|
|
||||||
MyDeviceHandler {
|
|
||||||
configured: AtomicBool::new(false),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Handler for MyDeviceHandler {
|
|
||||||
fn enabled(&mut self, enabled: bool) {
|
|
||||||
self.configured.store(false, Ordering::Relaxed);
|
|
||||||
if enabled {
|
|
||||||
info!("Device enabled");
|
|
||||||
} else {
|
|
||||||
info!("Device disabled");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reset(&mut self) {
|
|
||||||
self.configured.store(false, Ordering::Relaxed);
|
|
||||||
info!("Bus reset, the Vbus current limit is 100mA");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn addressed(&mut self, addr: u8) {
|
|
||||||
self.configured.store(false, Ordering::Relaxed);
|
|
||||||
info!("USB address set to: {}", addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn configured(&mut self, configured: bool) {
|
|
||||||
self.configured.store(configured, Ordering::Relaxed);
|
|
||||||
if configured {
|
|
||||||
info!(
|
|
||||||
"Device configured, it may now draw up to the configured current limit from Vbus."
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
info!("Device is no longer configured, the Vbus current limit is 100mA.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
288
src/usb.rs
Normal file
288
src/usb.rs
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
use core::cell::OnceCell;
|
||||||
|
use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_futures::join::join;
|
||||||
|
use embassy_rp::gpio::Level;
|
||||||
|
use embassy_rp::peripherals::USB;
|
||||||
|
use embassy_rp::usb::Driver;
|
||||||
|
use embassy_sync::blocking_mutex::raw::RawMutex;
|
||||||
|
use embassy_sync::channel::Receiver;
|
||||||
|
use embassy_usb::UsbDevice;
|
||||||
|
use embassy_usb::class::hid::{
|
||||||
|
HidBootProtocol, HidProtocolMode, HidReader, HidReaderWriter, HidSubclass, HidWriter, ReportId,
|
||||||
|
RequestHandler, State,
|
||||||
|
};
|
||||||
|
use embassy_usb::control::OutResponse;
|
||||||
|
use embassy_usb::{Builder, Config, Handler};
|
||||||
|
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
|
||||||
|
|
||||||
|
pub static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum KeyboardAction {
|
||||||
|
Press,
|
||||||
|
Depress,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Level> for KeyboardAction {
|
||||||
|
fn from(value: Level) -> Self {
|
||||||
|
match value {
|
||||||
|
Level::Low => KeyboardAction::Depress,
|
||||||
|
Level::High => KeyboardAction::Press,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct KeyboardEvent {
|
||||||
|
pub key: char,
|
||||||
|
pub action: KeyboardAction,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UsbKeyboardBuf<'d> {
|
||||||
|
// Create embassy-usb DeviceBuilder using the driver and config.
|
||||||
|
// It needs some buffers for building the descriptors.
|
||||||
|
config_descriptor: [u8; 256],
|
||||||
|
bos_descriptor: [u8; 256],
|
||||||
|
// You can also add a Microsoft OS descriptor.
|
||||||
|
msos_descriptor: [u8; 256],
|
||||||
|
control_buf: [u8; 64],
|
||||||
|
|
||||||
|
state: OnceCell<State<'d>>,
|
||||||
|
device_handler: OnceCell<MyDeviceHandler>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> UsbKeyboardBuf<'d> {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
config_descriptor: [0; 256],
|
||||||
|
bos_descriptor: [0; 256],
|
||||||
|
msos_descriptor: [0; 256],
|
||||||
|
control_buf: [0; 64],
|
||||||
|
state: OnceCell::new(),
|
||||||
|
device_handler: OnceCell::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UsbKeyboard<'d> {
|
||||||
|
usb: UsbDevice<'d, Driver<'d, USB>>,
|
||||||
|
reader: HidReader<'d, Driver<'d, USB>, 1>,
|
||||||
|
writer: HidWriter<'d, Driver<'d, USB>, 8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> UsbKeyboard<'d> {
|
||||||
|
// HidWriter<'_, Driver<'_, USB>, 8>
|
||||||
|
pub fn create_usb(buf: &'d mut UsbKeyboardBuf<'d>, driver: Driver<'d, USB>) -> Self {
|
||||||
|
// Create embassy-usb Config
|
||||||
|
let mut config = Config::new(0xc0de, 0xcafe);
|
||||||
|
config.manufacturer = Some("Nicholas Mello");
|
||||||
|
config.product = Some("Pi Pico Arcade Keyboard");
|
||||||
|
config.serial_number = Some("00000001");
|
||||||
|
config.max_power = 100;
|
||||||
|
config.max_packet_size_0 = 64;
|
||||||
|
config.composite_with_iads = false;
|
||||||
|
config.device_class = 0;
|
||||||
|
config.device_sub_class = 0;
|
||||||
|
config.device_protocol = 0;
|
||||||
|
|
||||||
|
if buf.state.set(State::new()).is_err() {
|
||||||
|
defmt::panic!("USB State already initalized");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut builder = Builder::new(
|
||||||
|
driver,
|
||||||
|
config,
|
||||||
|
&mut buf.config_descriptor,
|
||||||
|
&mut buf.bos_descriptor,
|
||||||
|
&mut buf.msos_descriptor,
|
||||||
|
&mut buf.control_buf,
|
||||||
|
);
|
||||||
|
|
||||||
|
if buf.device_handler.set(MyDeviceHandler::new()).is_err() {
|
||||||
|
defmt::panic!("USB Device Handler already initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.handler(buf.device_handler.get_mut().unwrap());
|
||||||
|
|
||||||
|
// Create classes on the builder.
|
||||||
|
let config = embassy_usb::class::hid::Config {
|
||||||
|
report_descriptor: KeyboardReport::desc(),
|
||||||
|
request_handler: None,
|
||||||
|
poll_ms: 60,
|
||||||
|
max_packet_size: 64,
|
||||||
|
hid_subclass: HidSubclass::Boot,
|
||||||
|
hid_boot_protocol: HidBootProtocol::Keyboard,
|
||||||
|
};
|
||||||
|
let hid =
|
||||||
|
HidReaderWriter::<_, 1, 8>::new(&mut builder, buf.state.get_mut().unwrap(), config);
|
||||||
|
|
||||||
|
let (reader, writer) = hid.split();
|
||||||
|
|
||||||
|
let usb = builder.build();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
usb,
|
||||||
|
reader,
|
||||||
|
writer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run<'ch, M, const N: usize>(self, receiver: Receiver<'ch, M, KeyboardEvent, N>)
|
||||||
|
where
|
||||||
|
M: RawMutex,
|
||||||
|
{
|
||||||
|
let mut request_handler = MyRequestHandler {};
|
||||||
|
|
||||||
|
let Self {
|
||||||
|
mut usb,
|
||||||
|
reader,
|
||||||
|
mut writer,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
let reader_fut = async {
|
||||||
|
reader.run(false, &mut request_handler).await;
|
||||||
|
};
|
||||||
|
|
||||||
|
let writer_fut = async {
|
||||||
|
loop {
|
||||||
|
let event = receiver.receive().await;
|
||||||
|
|
||||||
|
match event {
|
||||||
|
KeyboardEvent {
|
||||||
|
key: 'a',
|
||||||
|
action: KeyboardAction::Press,
|
||||||
|
} => {
|
||||||
|
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8
|
||||||
|
{
|
||||||
|
match writer.write(&[0, 0, 4, 0, 0, 0, 0, 0]).await {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => warn!("Failed to send boot report: {:?}", e),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Create a report with the A key pressed. (no shift modifier)
|
||||||
|
let report = KeyboardReport {
|
||||||
|
keycodes: [4, 0, 0, 0, 0, 0],
|
||||||
|
leds: 0,
|
||||||
|
modifier: 0,
|
||||||
|
reserved: 0,
|
||||||
|
};
|
||||||
|
// Send the report.
|
||||||
|
match writer.write_serialize(&report).await {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => warn!("Failed to send report: {:?}", e),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyboardEvent {
|
||||||
|
key: 'a',
|
||||||
|
action: KeyboardAction::Depress,
|
||||||
|
} => {
|
||||||
|
if HID_PROTOCOL_MODE.load(Ordering::Relaxed) == HidProtocolMode::Boot as u8
|
||||||
|
{
|
||||||
|
match writer.write(&[0, 0, 0, 0, 0, 0, 0, 0]).await {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => warn!("Failed to send boot report: {:?}", e),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
let report = KeyboardReport {
|
||||||
|
keycodes: [0, 0, 0, 0, 0, 0],
|
||||||
|
leds: 0,
|
||||||
|
modifier: 0,
|
||||||
|
reserved: 0,
|
||||||
|
};
|
||||||
|
match writer.write_serialize(&report).await {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => warn!("Failed to send report: {:?}", e),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
defmt::panic!("Unexpected event!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
join(usb.run(), join(reader_fut, writer_fut)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyRequestHandler {}
|
||||||
|
|
||||||
|
impl RequestHandler for MyRequestHandler {
|
||||||
|
fn get_report(&mut self, id: ReportId, _buf: &mut [u8]) -> Option<usize> {
|
||||||
|
info!("Get report for {:?}", id);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_report(&mut self, id: ReportId, data: &[u8]) -> OutResponse {
|
||||||
|
info!("Set report for {:?}: {=[u8]}", id, data);
|
||||||
|
OutResponse::Accepted
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_protocol(&self) -> HidProtocolMode {
|
||||||
|
let protocol = HidProtocolMode::from(HID_PROTOCOL_MODE.load(Ordering::Relaxed));
|
||||||
|
info!("The current HID protocol mode is: {}", protocol);
|
||||||
|
protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse {
|
||||||
|
info!("Switching to HID protocol mode: {}", protocol);
|
||||||
|
HID_PROTOCOL_MODE.store(protocol as u8, Ordering::Relaxed);
|
||||||
|
OutResponse::Accepted
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_idle_ms(&mut self, id: Option<ReportId>, dur: u32) {
|
||||||
|
info!("Set idle rate for {:?} to {:?}", id, dur);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_idle_ms(&mut self, id: Option<ReportId>) -> Option<u32> {
|
||||||
|
info!("Get idle rate for {:?}", id);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyDeviceHandler {
|
||||||
|
configured: AtomicBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MyDeviceHandler {
|
||||||
|
fn new() -> Self {
|
||||||
|
MyDeviceHandler {
|
||||||
|
configured: AtomicBool::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Handler for MyDeviceHandler {
|
||||||
|
fn enabled(&mut self, enabled: bool) {
|
||||||
|
self.configured.store(false, Ordering::Relaxed);
|
||||||
|
if enabled {
|
||||||
|
info!("Device enabled");
|
||||||
|
} else {
|
||||||
|
info!("Device disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self) {
|
||||||
|
self.configured.store(false, Ordering::Relaxed);
|
||||||
|
info!("Bus reset, the Vbus current limit is 100mA");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addressed(&mut self, addr: u8) {
|
||||||
|
self.configured.store(false, Ordering::Relaxed);
|
||||||
|
info!("USB address set to: {}", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configured(&mut self, configured: bool) {
|
||||||
|
self.configured.store(configured, Ordering::Relaxed);
|
||||||
|
if configured {
|
||||||
|
info!(
|
||||||
|
"Device configured, it may now draw up to the configured current limit from Vbus."
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
info!("Device is no longer configured, the Vbus current limit is 100mA.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user