#[cfg(all(unix, feature = "libusb"))]
use crate::server::usb::descriptors::{build_hid_mouse_report_descriptor, MouseReport};
#[cfg(all(unix, feature = "libusb"))]
use std::collections::VecDeque;
#[cfg(all(unix, feature = "libusb"))]
use tracing::{debug, trace, warn};
#[cfg(all(unix, feature = "libusb"))]
mod hid_descriptor_type {
pub const HID: u8 = 0x21;
pub const REPORT: u8 = 0x22;
}
#[cfg(all(unix, feature = "libusb"))]
#[derive(Debug)]
pub struct UsbHidMouseHandler {
report_descriptor: Vec<u8>,
pending_reports: VecDeque<[u8; 4]>,
}
#[cfg(all(unix, feature = "libusb"))]
impl Default for UsbHidMouseHandler {
fn default() -> Self {
Self::new()
}
}
#[cfg(all(unix, feature = "libusb"))]
impl UsbHidMouseHandler {
pub fn new() -> Self {
Self {
report_descriptor: build_hid_mouse_report_descriptor(),
pending_reports: VecDeque::new(),
}
}
pub fn endpoints() -> Vec<usbip::UsbEndpoint> {
vec![usbip::UsbEndpoint {
address: 0x81, attributes: 0x03, max_packet_size: 4, interval: 10, }]
}
pub fn queue(&mut self, report: MouseReport) {
trace!(
"USB mouse queue report: buttons={:#04x} x={} y={} wheel={}",
report.buttons,
report.x,
report.y,
report.wheel
);
self.pending_reports.push_back(report.to_bytes());
}
pub fn queue_with_release(&mut self, report: MouseReport) {
let held = report.buttons != 0;
self.queue(report);
if held {
self.queue(MouseReport::new());
}
}
#[allow(dead_code)]
pub fn pending_len(&self) -> usize {
self.pending_reports.len()
}
}
#[cfg(all(unix, feature = "libusb"))]
impl usbip::UsbInterfaceHandler for UsbHidMouseHandler {
fn handle_urb(
&mut self,
_interface: &usbip::UsbInterface,
ep: usbip::UsbEndpoint,
_transfer_buffer_length: u32,
setup: usbip::SetupPacket,
_req: &[u8],
) -> std::result::Result<Vec<u8>, std::io::Error> {
if ep.is_ep0() {
match (setup.request_type, setup.request) {
(0b1000_0001, 0x06) => {
let desc_type = (setup.value >> 8) as u8;
if desc_type == hid_descriptor_type::REPORT {
debug!(
"USB mouse GET_DESCRIPTOR(Report): {} bytes",
self.report_descriptor.len()
);
Ok(self.report_descriptor.clone())
} else {
warn!("USB mouse: unsupported descriptor type {:#04x}", desc_type);
Ok(vec![])
}
}
(0b0010_0001, 0x0A) | (0b0010_0001, 0x0B) => Ok(vec![]),
(0b1010_0001, 0x01) => Ok(self
.pending_reports
.front()
.map(|r| r.to_vec())
.unwrap_or_else(|| vec![0u8; 4])),
_ => {
debug!(
"USB mouse: unhandled control request type={:#04x} request={:#04x}",
setup.request_type, setup.request
);
Ok(vec![])
}
}
} else if let usbip::Direction::In = ep.direction() {
Ok(self
.pending_reports
.pop_front()
.map(|r| r.to_vec())
.unwrap_or_default())
} else {
Ok(vec![])
}
}
fn get_class_specific_descriptor(&self) -> Vec<u8> {
let len = self.report_descriptor.len();
vec![
0x09, hid_descriptor_type::HID, 0x11,
0x01, 0x00, 0x01, hid_descriptor_type::REPORT, len as u8,
(len >> 8) as u8, ]
}
fn as_any(&mut self) -> &mut dyn std::any::Any {
self
}
}