use core::cmp::min;
use usb_device::Result;
use usb_device::bus::{InterfaceNumber, StringIndex, UsbBus, UsbBusAllocator};
use usb_device::class::{ControlIn, ControlOut, UsbClass};
use usb_device::control;
use usb_device::control::{Recipient, RequestType};
use usb_device::descriptor::DescriptorWriter;
use usb_device::endpoint::{EndpointAddress, EndpointIn, EndpointOut};
use usb_device::UsbError;
//use cortex_m_semihosting::hprintln;
pub const USB_CLASS_HID: u8 = 0x03;
const REPORT_DESCRIPTOR: &[u8] = &[
0x06, 0xD0, 0xF1, // Usage Page (Reserved 0xF1D0)
0x09, 0x01, // Usage (0x01)
0xA1, 0x01, // Collection (Application)
0x09, 0x20, // Usage (0x20)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x40, // Report Count (64)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x21, // Usage (0x21)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x40, // Report Count (64)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
];
pub struct HidClass<'a, B: UsbBus> {
intf: InterfaceNumber,
read_ep: EndpointOut<'a, B>,
write_ep: EndpointIn<'a, B>,
buf: [u8; 65],
len: usize,
}
impl<B: UsbBus> HidClass<'_, B> {
pub fn new(alloc: &UsbBusAllocator<B>) -> HidClass<'_, B> {
HidClass {
intf: alloc.interface(),
read_ep: alloc.interrupt(8, 10),
write_ep: alloc.interrupt(8, 10),
buf: [0; 65],
len: 0,
}
}
pub fn write(&mut self, data: &[u8]) -> Result<usize> {
match self.write_ep.write(data) {
Ok(count) => Ok(count),
Err(UsbError::WouldBlock) => Ok(0),
e => e,
}
}
pub fn read(&mut self, data: &mut [u8]) -> Result<usize> {
// Terrible buffering implementation for brevity's sake
if self.len == 0 {
self.len = match self.read_ep.read(&mut self.buf) {
Ok(0) | Err(UsbError::WouldBlock) => return Ok(0),
Ok(count) => count,
e => return e,
};
}
let count = min(data.len(), self.len);
&data[..count].copy_from_slice(&self.buf[0..count]);
self.buf.rotate_left(count);
self.len -= count;
Ok(count)
}
}
impl<B: UsbBus> UsbClass<B> for HidClass<'_, B> {
fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
writer.interface(
self.intf,
3, //USB_CLASS_HID,
0,
0)?;
let descriptor_len = REPORT_DESCRIPTOR.len();
//hprintln!("report len: {}", descriptor_len).unwrap();
let descriptor_len = (descriptor_len as u16).to_le_bytes();
writer.write(
0x21,
&[0x10, 0x01, 0x21, 0x01, 0x22, descriptor_len[0], descriptor_len[1]]
)?;
writer.endpoint(&self.write_ep)?;
writer.endpoint(&self.read_ep)?;
//hprintln!("get_configuration_descriptors!").unwrap();
Ok(())
}
fn endpoint_in_complete(&mut self, _addr: EndpointAddress) {
//hprintln!("endpoint_in_complete!").unwrap();
}
fn control_in(&mut self, xfer: ControlIn<B>) {
let req = xfer.request();
match (req.request_type, req.recipient) {
(RequestType::Standard, Recipient::Interface) => {
//hprintln!("control_in!").unwrap();
if req.request == control::Request::GET_DESCRIPTOR {
let (dtype, index) = req.descriptor_type_index();
if dtype == 0x22 && index == 0 {
let descriptor = REPORT_DESCRIPTOR;
xfer.accept_with(descriptor).ok();
}
}
}
_ => {}
}
}
}
hid.rs:
main.rs:
this will result in
c0000011- "xact error".if add
device_class(0xff)toUsbDeviceBuilder, it will be detected by Windows. but i want to use hidapi, so how to configure hid-class?