This repository has been archived on 2026-08-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
donglora/vendor/usbd-hid-macros/src/packer.rs
T
swaitsandClaude Opus 4.6 3102fc747a feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support:
- Splash screen on boot (1.5s) with project name, version, board
- Dashboard showing radio state, config, counters, RSSI/SNR
- RSSI history sparkline (64-sample ring buffer, 2px-wide bars)
- DisplayOn/DisplayOff host commands routed via dedicated channel
- Pure render functions against generic DrawTarget (no hardware coupling)
- Display on/off control bypasses radio task entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:42:54 -06:00

115 lines
3.7 KiB
Rust

extern crate usbd_hid_descriptors;
use usbd_hid_descriptors::*;
use alloc::vec::Vec;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{parse, Ident, Index, Result};
use crate::item::*;
use crate::spec::*;
use core::iter::Extend;
pub fn uses_report_ids(spec: &Spec) -> bool {
match spec {
Spec::MainItem(_) => false,
Spec::Collection(c) => {
for s in c.fields.values() {
if uses_report_ids(s) {
return true;
}
}
c.report_id.is_some()
}
}
}
fn make_unary_serialize_invocation(bits: usize, ident: Ident, signed: bool) -> TokenStream {
match (bits, signed) {
(8, false) => quote!({ s.serialize_element(&(self.#ident as u8))?; }),
(16, false) => quote!({ s.serialize_element(&(self.#ident as u16))?; }),
(32, false) => quote!({ s.serialize_element(&(self.#ident as u32))?; }),
(8, true) => quote!({ s.serialize_element(&(self.#ident as i8))?; }),
(16, true) => quote!({ s.serialize_element(&(self.#ident as i16))?; }),
(32, true) => quote!({ s.serialize_element(&(self.#ident as i32))?; }),
_ => quote!(),
}
}
pub fn gen_serializer(fields: Vec<ReportUnaryField>, typ: MainItemKind) -> Result<TokenStream> {
let mut elems = Vec::new();
for field in fields {
if field.descriptor_item.kind != typ {
continue;
}
let signed = field.descriptor_item.logical_minimum < 0;
let rc = match field.descriptor_item.report_size {
1 => {
if field.descriptor_item.report_count == 1 {
elems.push(make_unary_serialize_invocation(
field.bit_width,
field.ident.clone(),
signed,
));
} else {
let ident = field.ident.clone();
elems.push(quote!({ s.serialize_element(&self.#ident)?; }));
}
Ok(())
}
8 => {
// u8 / i8
if field.descriptor_item.report_count == 1 {
elems.push(make_unary_serialize_invocation(
8,
field.ident.clone(),
signed,
));
} else if field.descriptor_item.report_count <= 32 {
let ident = field.ident.clone();
elems.push(quote!({ s.serialize_element(&self.#ident)?; }));
} else {
// XXX - don't attempt to serialize arrays larger than 32
// (not supported by serde, yet)
}
Ok(())
}
16 | 32 => {
// u16 / i16 / u32 / i32
if field.descriptor_item.report_count == 1 {
elems.push(make_unary_serialize_invocation(
field.descriptor_item.report_size as usize,
field.ident.clone(),
signed,
));
Ok(())
} else {
Err(parse::Error::new(
field.ident.span(),
"Arrays of 16/32bit fields not supported",
))
}
}
_ => Err(parse::Error::new(
field.ident.span(),
"Unsupported report size for serialization",
)),
};
rc?;
}
let mut out = TokenStream::new();
let idx = Index::from(elems.len());
out.extend(elems);
Ok(quote!({
let mut s = serializer.serialize_tuple(#idx)?;
#out
s.end()
}))
}