Skip to content

Commit ce6183b

Browse files
authored
Merge pull request #163 from ruabmbua/getinputreport
Add get_input_report (currently not supported on windows native backend)
2 parents 11474cd + a51ba9b commit ce6183b

File tree

6 files changed

+58
-14
lines changed

6 files changed

+58
-14
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ target
22
Cargo.lock
33
.idea/
44
hidapi-rs.iml
5+
.helix/
6+
.vscode/

src/ffi.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ extern "C" {
6868
data: *const c_uchar,
6969
length: size_t,
7070
) -> c_int;
71+
pub fn hid_get_input_report(
72+
device: *mut HidDevice,
73+
data: *mut c_uchar,
74+
length: size_t,
75+
) -> c_int;
7176
pub fn hid_close(device: *mut HidDevice);
7277
pub fn hid_get_manufacturer_string(
7378
device: *mut HidDevice,

src/hidapi.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,16 @@ impl HidDeviceBackendBase for HidDevice {
269269
}
270270
}
271271

272+
fn get_input_report(&self, data: &mut [u8]) -> HidResult<usize> {
273+
if data.is_empty() {
274+
return Err(HidError::InvalidZeroSizeData);
275+
}
276+
let res = unsafe {
277+
ffi::hid_get_input_report(self._hid_device, data.as_mut_ptr(), data.len() as size_t)
278+
};
279+
self.check_size(res)
280+
}
281+
272282
fn set_blocking_mode(&self, blocking: bool) -> HidResult<()> {
273283
let res = unsafe {
274284
ffi::hid_set_nonblocking(self._hid_device, if blocking { 0i32 } else { 1i32 })

src/lib.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,8 @@ trait HidDeviceBackendBase {
477477
fn send_feature_report(&self, data: &[u8]) -> HidResult<()>;
478478
fn get_feature_report(&self, buf: &mut [u8]) -> HidResult<usize>;
479479
fn send_output_report(&self, data: &[u8]) -> HidResult<()>;
480+
#[cfg(any(hidapi, target_os = "linux"))]
481+
fn get_input_report(&self, data: &mut [u8]) -> HidResult<usize>;
480482
fn set_blocking_mode(&self, blocking: bool) -> HidResult<()>;
481483
fn get_device_info(&self) -> HidResult<DeviceInfo>;
482484
fn get_manufacturer_string(&self) -> HidResult<Option<String>>;
@@ -595,23 +597,36 @@ impl HidDevice {
595597
self.inner.get_feature_report(buf)
596598
}
597599

598-
// Send a Output report to the device.
599-
//
600-
// Output reports are sent over the Control endpoint as a Set_Report
601-
// transfer. The first byte of data[] must contain the Report ID.
602-
// For devices which only support a single report, this must be set
603-
// to 0x0. The remaining bytes contain the report data. Since the
604-
// Report ID is mandatory, calls to hid_send_output_report() will
605-
// always contain one more byte than the report contains. For example,
606-
// if a hid report is 16 bytes long, 17 bytes must be passed to
607-
// hid_send_output_report(): the Report ID (or 0x0, for devices
608-
// which do not use numbered reports), followed by the report
609-
// data (16 bytes). In this example, the length passed in
610-
// would be 17.
600+
/// Send a Output report to the device.
601+
///
602+
/// Output reports are sent over the Control endpoint as a Set_Report
603+
/// transfer. The first byte of data[] must contain the Report ID.
604+
/// For devices which only support a single report, this must be set
605+
/// to 0x0. The remaining bytes contain the report data. Since the
606+
/// Report ID is mandatory, calls to hid_send_output_report() will
607+
/// always contain one more byte than the report contains. For example,
608+
/// if a hid report is 16 bytes long, 17 bytes must be passed to
609+
/// hid_send_output_report(): the Report ID (or 0x0, for devices
610+
/// which do not use numbered reports), followed by the report
611+
/// data (16 bytes). In this example, the length passed in
612+
/// would be 17.
611613
pub fn send_output_report(&self, data: &[u8]) -> HidResult<()> {
612614
self.inner.send_output_report(data)
613615
}
614616

617+
/// Get a input report from a HID device
618+
///
619+
/// Set the first byte of data to the report id of the report to be read.
620+
/// Set the first byte to zero if your device does not use numbered reports.
621+
/// After calling the function, the first byte will still contain the same report id.
622+
///
623+
/// If successful, returns the number of bytes read plus one for the report ID (which is still
624+
/// in the first byte).
625+
#[cfg(any(hidapi, target_os = "linux"))]
626+
pub fn get_input_report(&self, data: &mut [u8]) -> HidResult<usize> {
627+
self.inner.get_input_report(data)
628+
}
629+
615630
/// Set the device handle to be in blocking or in non-blocking mode. In
616631
/// non-blocking mode calls to `read()` will return immediately with an empty
617632
/// slice if there is no data to be read. In blocking mode, `read()` will

src/linux_native.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ use nix::{
2323

2424
use super::{BusType, DeviceInfo, HidDeviceBackendBase, HidError, HidResult, WcharString};
2525
use ioctl::{
26-
hidraw_ioc_get_feature, hidraw_ioc_grdescsize, hidraw_ioc_set_feature, hidraw_ioc_set_output,
26+
hidraw_ioc_get_feature, hidraw_ioc_get_input, hidraw_ioc_grdescsize, hidraw_ioc_set_feature,
27+
hidraw_ioc_set_output,
2728
};
2829

2930
// Bus values from linux/input.h
@@ -578,6 +579,15 @@ impl HidDeviceBackendBase for HidDevice {
578579
Ok(())
579580
}
580581

582+
fn get_input_report(&self, data: &mut [u8]) -> HidResult<usize> {
583+
match unsafe { hidraw_ioc_get_input(self.fd.as_raw_fd(), data) } {
584+
Ok(n) => Ok(n as usize),
585+
Err(e) => Err(HidError::HidApiError {
586+
message: format!("ioctl (GINPUT): {e}"),
587+
}),
588+
}
589+
}
590+
581591
fn set_blocking_mode(&self, blocking: bool) -> HidResult<()> {
582592
self.blocking.set(blocking);
583593
Ok(())

src/linux_native/ioctl.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const HIDRAW_IOC_GRDESCSIZE: u8 = 0x01;
88
const HIDRAW_SET_FEATURE: u8 = 0x06;
99
const HIDRAW_GET_FEATURE: u8 = 0x07;
1010
const HIDRAW_SET_OUTPUT: u8 = 0x0b;
11+
const HIDRAW_GET_INPUT: u8 = 0x0a;
1112

1213
ioctl_read!(
1314
hidraw_ioc_grdescsize,
@@ -34,3 +35,4 @@ ioctl_write_buf!(
3435
HIDRAW_SET_OUTPUT,
3536
u8
3637
);
38+
ioctl_read_buf!(hidraw_ioc_get_input, HIDRAW_IOC_MAGIC, HIDRAW_GET_INPUT, u8);

0 commit comments

Comments
 (0)