1use embassy_usb_driver::host::{PipeError, UsbHostAllocator, UsbPipe, pipe};
6use embassy_usb_driver::{Direction as UsbDirection, EndpointAddress, EndpointInfo, EndpointType};
7
8pub use super::hid_report::{ReportDescriptor, ReportField};
9use crate::control::SetupPacket;
10use crate::descriptor::ConfigurationDescriptor;
11use crate::handler::EnumerationInfo;
12
13const USB_CLASS_HID: u8 = 0x03;
15const TRANSFER_INTERRUPT: u8 = 0x03;
17
18const GET_REPORT: u8 = 0x01;
20const SET_IDLE: u8 = 0x0A;
22const SET_PROTOCOL: u8 = 0x0B;
24
25pub const PROTOCOL_BOOT: u8 = 0;
27pub const PROTOCOL_REPORT: u8 = 1;
29
30#[derive(Clone, Debug, Default, PartialEq, Eq)]
37#[cfg_attr(feature = "defmt", derive(defmt::Format))]
38pub struct KeyboardReport {
39 pub modifiers: u8,
44 pub keycodes: [u8; 6],
47}
48
49impl KeyboardReport {
50 pub fn parse(buf: &[u8]) -> Option<Self> {
53 if buf.len() < 8 {
54 return None;
55 }
56 Some(Self {
57 modifiers: buf[0],
58 keycodes: [buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]],
60 })
61 }
62
63 pub fn is_pressed(&self, keycode: u8) -> bool {
65 keycode != 0 && self.keycodes.contains(&keycode)
66 }
67
68 pub fn ctrl(&self) -> bool {
70 self.modifiers & 0x11 != 0
71 }
72 pub fn shift(&self) -> bool {
74 self.modifiers & 0x22 != 0
75 }
76 pub fn alt(&self) -> bool {
78 self.modifiers & 0x44 != 0
79 }
80 pub fn gui(&self) -> bool {
82 self.modifiers & 0x88 != 0
83 }
84}
85
86pub type MouseButtons = u8;
90
91#[derive(Clone, Debug, Default, PartialEq, Eq)]
95#[cfg_attr(feature = "defmt", derive(defmt::Format))]
96pub struct MouseReport {
97 pub buttons: MouseButtons,
99 pub x: i8,
101 pub y: i8,
103 pub wheel: i8,
105}
106
107impl MouseReport {
108 pub const BUTTON_LEFT: MouseButtons = 1 << 0;
110 pub const BUTTON_RIGHT: MouseButtons = 1 << 1;
112 pub const BUTTON_MIDDLE: MouseButtons = 1 << 2;
114
115 pub fn parse(buf: &[u8]) -> Option<Self> {
118 if buf.len() < 3 {
119 return None;
120 }
121 Some(Self {
122 buttons: buf[0],
123 x: buf[1] as i8,
124 y: buf[2] as i8,
125 wheel: if buf.len() >= 4 { buf[3] as i8 } else { 0 },
126 })
127 }
128
129 pub fn left(&self) -> bool {
131 self.buttons & Self::BUTTON_LEFT != 0
132 }
133 pub fn right(&self) -> bool {
135 self.buttons & Self::BUTTON_RIGHT != 0
136 }
137 pub fn middle(&self) -> bool {
139 self.buttons & Self::BUTTON_MIDDLE != 0
140 }
141}
142
143const DESC_HID: u8 = 0x21;
145
146#[derive(Clone, Debug)]
148#[cfg_attr(feature = "defmt", derive(defmt::Format))]
149pub struct HidInfo {
150 pub interface_number: u8,
152 pub interrupt_in_ep: u8,
154 pub interrupt_in_mps: u16,
156 pub report_descriptor_len: u16,
159}
160
161pub fn find_hid(config_desc: &[u8]) -> Option<HidInfo> {
163 let cfg = ConfigurationDescriptor::try_from_slice(config_desc).ok()?;
164
165 for iface in cfg.iter_interface() {
166 if iface.interface_class != USB_CLASS_HID {
167 continue;
168 }
169
170 let report_desc_len = iface
174 .iter_descriptors()
175 .find_map(|(_, data)| {
176 if data.len() >= 7 && data[1] == DESC_HID {
177 Some(u16::from_le_bytes([data[5], data[6]]))
178 } else {
179 None
180 }
181 })
182 .unwrap_or(0);
183
184 let ep = iface
185 .iter_endpoints()
186 .find(|ep| ep.transfer_type() == TRANSFER_INTERRUPT && ep.is_in())?;
187
188 return Some(HidInfo {
189 interface_number: iface.interface_number,
190 interrupt_in_ep: ep.endpoint_address,
191 interrupt_in_mps: ep.max_packet_size,
192 report_descriptor_len: report_desc_len,
193 });
194 }
195
196 None
197}
198
199#[derive(Debug)]
201#[cfg_attr(feature = "defmt", derive(defmt::Format))]
202pub enum HidError {
203 Transfer(PipeError),
205 NoInterface,
207 NoPipe,
209}
210
211impl From<PipeError> for HidError {
212 fn from(e: PipeError) -> Self {
213 Self::Transfer(e)
214 }
215}
216
217impl core::fmt::Display for HidError {
218 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
219 match self {
220 Self::Transfer(_e) => write!(f, "Transfer error"),
221 Self::NoInterface => write!(f, "No HID interface found"),
222 Self::NoPipe => write!(f, "No free pipe"),
223 }
224 }
225}
226
227impl core::error::Error for HidError {}
228
229pub struct HidHost<'d, A: UsbHostAllocator<'d>> {
233 ctrl_ch: A::Pipe<pipe::Control, pipe::InOut>,
234 in_ch: A::Pipe<pipe::Interrupt, pipe::In>,
235 interface: u8,
236 report_descriptor_len: u16,
237 _phantom: core::marker::PhantomData<&'d ()>,
238}
239
240impl<'d, A: UsbHostAllocator<'d>> HidHost<'d, A> {
241 pub fn new(alloc: &A, config_desc: &[u8], enum_info: &EnumerationInfo) -> Result<Self, HidError> {
246 let info = find_hid(config_desc).ok_or(HidError::NoInterface)?;
247
248 let ctrl_ep_info = EndpointInfo {
249 addr: EndpointAddress::from_parts(0, UsbDirection::In),
250 ep_type: EndpointType::Control,
251 max_packet_size: enum_info.device_desc.max_packet_size0 as u16,
252 interval_ms: 0,
253 };
254
255 let in_ep_info = EndpointInfo {
256 addr: EndpointAddress::from_parts((info.interrupt_in_ep & 0x0F) as usize, UsbDirection::In),
257 ep_type: EndpointType::Interrupt,
258 max_packet_size: info.interrupt_in_mps,
259 interval_ms: 0,
260 };
261
262 let device_address = enum_info.device_address;
263 let split = enum_info.split();
264
265 let ctrl_ch = alloc
266 .alloc_pipe::<pipe::Control, pipe::InOut>(device_address, &ctrl_ep_info, split)
267 .map_err(|_| HidError::NoPipe)?;
268 let in_ch = alloc
269 .alloc_pipe::<pipe::Interrupt, pipe::In>(device_address, &in_ep_info, split)
270 .map_err(|_| HidError::NoPipe)?;
271
272 Ok(Self {
273 ctrl_ch,
274 in_ch,
275 interface: info.interface_number,
276 report_descriptor_len: info.report_descriptor_len,
277 _phantom: core::marker::PhantomData,
278 })
279 }
280
281 pub async fn fetch_report_descriptor<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8], HidError> {
295 let len = (self.report_descriptor_len as usize).min(buf.len()) as u16;
296 let setup = SetupPacket::get_hid_report_descriptor(self.interface, len);
297 let n = self
298 .ctrl_ch
299 .control_in(&setup.to_bytes(), &mut buf[..len as usize])
300 .await?;
301 Ok(&buf[..n])
302 }
303
304 pub async fn set_idle(&mut self, report_id: u8, idle_duration: u8) -> Result<(), HidError> {
311 let value = (idle_duration as u16) << 8 | report_id as u16;
312 let setup = SetupPacket::class_interface_out(SET_IDLE, value, self.interface as u16, 0);
313 match self.ctrl_ch.control_out(&setup.to_bytes(), &[]).await {
314 Ok(_) => Ok(()),
315 Err(PipeError::Stall) => Ok(()),
316 Err(e) => Err(HidError::Transfer(e)),
317 }
318 }
319
320 pub async fn set_protocol(&mut self, protocol: u8) -> Result<(), HidError> {
322 let setup = SetupPacket::class_interface_out(SET_PROTOCOL, protocol as u16, self.interface as u16, 0);
323 self.ctrl_ch.control_out(&setup.to_bytes(), &[]).await?;
324 Ok(())
325 }
326
327 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, HidError> {
331 let n = self.in_ch.request_in(buf).await?;
332 Ok(n)
333 }
334
335 pub async fn read_keyboard(&mut self) -> Result<Option<KeyboardReport>, HidError> {
340 let mut buf = [0u8; 8];
341 self.in_ch.request_in(&mut buf).await?;
342 Ok(KeyboardReport::parse(&buf))
343 }
344
345 pub async fn read_mouse(&mut self) -> Result<Option<MouseReport>, HidError> {
350 let mut buf = [0u8; 4];
351 let n = self.in_ch.request_in(&mut buf).await?;
353 Ok(MouseReport::parse(&buf[..n]))
354 }
355
356 pub async fn get_report(&mut self, report_type: u8, report_id: u8, buf: &mut [u8]) -> Result<usize, HidError> {
363 let value = (report_type as u16) << 8 | report_id as u16;
364 let setup = SetupPacket::class_interface_in(GET_REPORT, value, self.interface as u16, buf.len() as u16);
365 let n = self.ctrl_ch.control_in(&setup.to_bytes(), buf).await?;
366 Ok(n)
367 }
368}