diff options
Diffstat (limited to 'embassy-usb')
| -rw-r--r-- | embassy-usb/CHANGELOG.md | 4 | ||||
| -rw-r--r-- | embassy-usb/Cargo.toml | 2 | ||||
| -rw-r--r-- | embassy-usb/src/class/hid.rs | 39 |
3 files changed, 37 insertions, 8 deletions
diff --git a/embassy-usb/CHANGELOG.md b/embassy-usb/CHANGELOG.md index 0a30bc24b..891388122 100644 --- a/embassy-usb/CHANGELOG.md +++ b/embassy-usb/CHANGELOG.md | |||
| @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 8 | <!-- next-header --> | 8 | <!-- next-header --> |
| 9 | ## Unreleased - ReleaseDate | 9 | ## Unreleased - ReleaseDate |
| 10 | 10 | ||
| 11 | ## 0.5.2 - Unreleased | ||
| 12 | |||
| 13 | - `hid`: Add USB HID Boot Protocol Mode support | ||
| 14 | |||
| 11 | ## 0.5.1 - 2025-08-26 | 15 | ## 0.5.1 - 2025-08-26 |
| 12 | 16 | ||
| 13 | ## 0.5.0 - 2025-07-16 | 17 | ## 0.5.0 - 2025-07-16 |
diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index e309eec93..fde603df0 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "embassy-usb" | 2 | name = "embassy-usb" |
| 3 | version = "0.5.1" | 3 | version = "0.5.2" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | description = "Async USB device stack for embedded devices in Rust." | 6 | description = "Async USB device stack for embedded devices in Rust." |
diff --git a/embassy-usb/src/class/hid.rs b/embassy-usb/src/class/hid.rs index 182e1f83f..8df23b384 100644 --- a/embassy-usb/src/class/hid.rs +++ b/embassy-usb/src/class/hid.rs | |||
| @@ -8,6 +8,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; | |||
| 8 | use ssmarshal::serialize; | 8 | use ssmarshal::serialize; |
| 9 | #[cfg(feature = "usbd-hid")] | 9 | #[cfg(feature = "usbd-hid")] |
| 10 | use usbd_hid::descriptor::AsInputReport; | 10 | use usbd_hid::descriptor::AsInputReport; |
| 11 | use usbd_hid::hid_class::HidProtocolMode; | ||
| 11 | 12 | ||
| 12 | use crate::control::{InResponse, OutResponse, Recipient, Request, RequestType}; | 13 | use crate::control::{InResponse, OutResponse, Recipient, Request, RequestType}; |
| 13 | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | 14 | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; |
| @@ -389,6 +390,23 @@ pub trait RequestHandler { | |||
| 389 | OutResponse::Rejected | 390 | OutResponse::Rejected |
| 390 | } | 391 | } |
| 391 | 392 | ||
| 393 | /// Gets the current hid protocol. | ||
| 394 | /// | ||
| 395 | /// Returns `Report` protocol by default. | ||
| 396 | fn get_protocol(&self) -> HidProtocolMode { | ||
| 397 | HidProtocolMode::Report | ||
| 398 | } | ||
| 399 | |||
| 400 | /// Sets the current hid protocol to `protocol`. | ||
| 401 | /// | ||
| 402 | /// Accepts only `Report` protocol by default. | ||
| 403 | fn set_protocol(&mut self, protocol: HidProtocolMode) -> OutResponse { | ||
| 404 | match protocol { | ||
| 405 | HidProtocolMode::Report => OutResponse::Accepted, | ||
| 406 | HidProtocolMode::Boot => OutResponse::Rejected, | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 392 | /// Get the idle rate for `id`. | 410 | /// Get the idle rate for `id`. |
| 393 | /// | 411 | /// |
| 394 | /// If `id` is `None`, get the idle rate for all reports. Returning `None` | 412 | /// If `id` is `None`, get the idle rate for all reports. Returning `None` |
| @@ -482,11 +500,14 @@ impl<'d> Handler for Control<'d> { | |||
| 482 | _ => Some(OutResponse::Rejected), | 500 | _ => Some(OutResponse::Rejected), |
| 483 | }, | 501 | }, |
| 484 | HID_REQ_SET_PROTOCOL => { | 502 | HID_REQ_SET_PROTOCOL => { |
| 485 | if req.value == 1 { | 503 | let hid_protocol = HidProtocolMode::from(req.value as u8); |
| 486 | Some(OutResponse::Accepted) | 504 | match (self.request_handler.as_mut(), hid_protocol) { |
| 487 | } else { | 505 | (Some(request_handler), hid_protocol) => Some(request_handler.set_protocol(hid_protocol)), |
| 488 | warn!("HID Boot Protocol is unsupported."); | 506 | (None, HidProtocolMode::Report) => Some(OutResponse::Accepted), |
| 489 | Some(OutResponse::Rejected) // UNSUPPORTED: Boot Protocol | 507 | (None, HidProtocolMode::Boot) => { |
| 508 | warn!("HID Boot Protocol is unsupported."); | ||
| 509 | Some(OutResponse::Rejected) // UNSUPPORTED: Boot Protocol | ||
| 510 | } | ||
| 490 | } | 511 | } |
| 491 | } | 512 | } |
| 492 | _ => Some(OutResponse::Rejected), | 513 | _ => Some(OutResponse::Rejected), |
| @@ -539,8 +560,12 @@ impl<'d> Handler for Control<'d> { | |||
| 539 | } | 560 | } |
| 540 | } | 561 | } |
| 541 | HID_REQ_GET_PROTOCOL => { | 562 | HID_REQ_GET_PROTOCOL => { |
| 542 | // UNSUPPORTED: Boot Protocol | 563 | if let Some(request_handler) = self.request_handler.as_mut() { |
| 543 | buf[0] = 1; | 564 | buf[0] = request_handler.get_protocol() as u8; |
| 565 | } else { | ||
| 566 | // Return `Report` protocol by default | ||
| 567 | buf[0] = HidProtocolMode::Report as u8; | ||
| 568 | } | ||
| 544 | Some(InResponse::Accepted(&buf[0..1])) | 569 | Some(InResponse::Accepted(&buf[0..1])) |
| 545 | } | 570 | } |
| 546 | _ => Some(InResponse::Rejected), | 571 | _ => Some(InResponse::Rejected), |
