1mod field;
2
3pub use field::FieldInfo;
4use num_enum::IntoPrimitive;
5use num_enum::TryFromPrimitive;
6
7use std::fmt::Display;
8
9use nix::ioctl_none;
10use nix::ioctl_read;
11use nix::ioctl_read_buf;
12use nix::ioctl_readwrite;
13use nix::ioctl_write_ptr;
14
15const HID_STRING_SIZE: usize = 256;
16pub const HID_MAX_MULTI_USAGES: usize = 1024;
17
18#[repr(C)]
19pub struct Event {
20 hid: u32,
21 value: i32,
22}
23
24#[derive(Default)]
25#[repr(C)]
26pub struct Devinfo {
27 pub bustype: u32,
28 pub busnum: u32,
29 pub devnum: u32,
30 pub ifnum: u32,
31 pub vendor: i16,
32 pub product: i16,
33 pub version: i16,
34 pub num_applications: u32,
35}
36
37impl Display for Devinfo {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 write!(f, "{{ busnum: {:#X}, bustype: {:#X}, devnum: {:#X}, ifnum: {:#X}, num_applications: {:#X}, product: {:#X}, vendor: {:#X}, version: {:#X} }}", self.busnum, self.bustype, self.devnum, self.ifnum, self.num_applications, self.product, self.vendor, self.version)
40 }
41}
42
43#[repr(C)]
44pub struct StringDescriptor {
45 pub index: i32,
46 pub value: [char; HID_STRING_SIZE],
47}
48
49#[derive(Default)]
50#[repr(C)]
51pub struct ReportInfo {
52 pub report_type: u32,
53 pub report_id: u32,
54 pub num_fields: u32,
55}
56
57pub enum ReportIds {
58 Short = 0x10,
59 Long = 0x11,
60 VeryLong = 0x12,
61}
62
63impl Display for ReportInfo {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 write!(
66 f,
67 "{{ num_fields: {}, report_id: {:#X}, report_type: {:#X} }}",
68 self.num_fields, self.report_id, self.report_type
69 )
70 }
71}
72
73#[derive(Default)]
74#[repr(C)]
75pub struct UsageRef {
76 pub report_type: u32,
77 pub report_id: u32,
78 pub field_index: u32,
79 pub usage_index: u32,
80 pub usage_code: u32,
81 pub value: i32,
82}
83
84impl Display for UsageRef {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 write!(f, "{{ field_index: {:#X}, report_id: {:#X}, report_type: {:#X}, usage_code: {:#X}, usage_index: {:#X}, value: {:#X} }}",
87 self.field_index, self.report_id, self.report_type, self.usage_code, self.usage_index, self.value)
88 }
89}
90
91#[repr(C)]
94pub struct UsageRefMulti {
95 pub uref: UsageRef,
96 pub num_values: u32,
97 pub values: [i32; HID_MAX_MULTI_USAGES],
98}
99
100impl Default for UsageRefMulti {
101 fn default() -> Self {
102 Self {
103 uref: UsageRef::default(),
104 num_values: 0,
105 values: [0; HID_MAX_MULTI_USAGES],
106 }
107 }
108}
109
110impl Display for UsageRefMulti {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 write!(
113 f,
114 "{{ num_values: {}, uref: {}, values:",
115 self.num_values, self.uref,
116 )?;
117 let values = &self.values;
118 let last_index = values.iter().enumerate().rev().fold(None, |acc, (i, v)| {
120 if acc.is_some() {
121 return acc;
122 }
123 if *v == 0x0 {
124 None
125 } else {
126 Some(i)
127 }
128 });
129 last_index.map_or(Ok(()), |index| {
130 let s = values[0..=index]
132 .as_ref()
133 .iter()
134 .map(|v| format!("{:#0x}", *v))
135 .collect::<Vec<String>>()
136 .join(", ");
137 write!(f, " {}", s)
138 })?;
139 f.write_str(" }")
140 }
141}
142
143
144
145#[repr(C)]
146pub struct CollectionInfo {
147 pub index: u32,
148 pub _type: u32,
149 pub usage: u32,
150 pub level: u32,
151}
152
153ioctl_read!(HIDIOCGVERSION, 'H', 0x01, i32);
154pub unsafe fn HIDIOCAPPLICATION(fd: nix::libc::c_int, index: u32) -> nix::Result<nix::libc::c_int> {
155 nix::convert_ioctl_res!(nix::libc::ioctl(
156 fd,
157 nix::request_code_none!('H', 0x02) as nix::sys::ioctl::ioctl_num_type,
158 index
159 ))
160}
161ioctl_read!(HIDIOCGDEVINFO, 'H', 0x03, Devinfo);
162ioctl_read!(HIDIOCGSTRING, 'H', 0x04, StringDescriptor);
163ioctl_none!(HIDIOCINITREPORT, 'H', 0x05);
164ioctl_read_buf!(HIDIOCGNAME, 'H', 0x06, u8);
165ioctl_write_ptr!(HIDIOCGREPORT, 'H', 0x07, ReportInfo);
166ioctl_write_ptr!(HIDIOCSREPORT, 'H', 0x08, ReportInfo);
167ioctl_readwrite!(HIDIOCGREPORTINFO, 'H', 0x09, ReportInfo);
168ioctl_readwrite!(HIDIOCGFIELDINFO, 'H', 0x0A, FieldInfo);
169ioctl_readwrite!(HIDIOCGUSAGE, 'H', 0x0B, UsageRef);
170ioctl_write_ptr!(HIDIOCSUSAGE, 'H', 0x0C, UsageRef);
171ioctl_readwrite!(HIDIOCGUCODE, 'H', 0x0D, UsageRef);
172
173ioctl_read!(HIDIOCGFLAG, 'H', 0x0E, i32);
174ioctl_write_ptr!(HIDIOCSFLAG, 'H', 0x0F, HIDIOCSFLAGFlag);
175ioctl_write_ptr!(HIDIOCGCOLLECTIONINDEX, 'H', 0x10, UsageRef);
176ioctl_readwrite!(HIDIOCGCOLLECTIONINFO, 'H', 0x11, CollectionInfo);
177ioctl_read_buf!(HIDIOCGPHYS, 'H', 0x12, u8);
178
179ioctl_readwrite!(HIDIOCGUSAGES, 'H', 0x13, UsageRefMulti);
181ioctl_write_ptr!(HIDIOCSUSAGES, 'H', 0x14, UsageRefMulti);
182
183#[derive(IntoPrimitive)]
184#[repr(u8)]
185pub enum HIDIOCSFLAGFlag {
187 UREF = 0x1,
188 REPORT = 0x2,
189 ALL = 0x3,
190}
191
192