From b1745f5aa423411cb6cafd9e0f2d88965928be90 Mon Sep 17 00:00:00 2001 From: Marek G Date: Sat, 7 Dec 2024 00:28:38 +0100 Subject: [PATCH] Add send_output_report --- src/ffi.rs | 5 +++++ src/hidapi.rs | 18 ++++++++++++++++++ src/lib.rs | 18 ++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/ffi.rs b/src/ffi.rs index 7840ddf..f2aecb9 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -63,6 +63,11 @@ extern "C" { data: *mut c_uchar, length: size_t, ) -> c_int; + pub fn hid_send_output_report( + device: *mut HidDevice, + data: *const c_uchar, + length: size_t, + ) -> c_int; pub fn hid_close(device: *mut HidDevice); pub fn hid_get_manufacturer_string( device: *mut HidDevice, diff --git a/src/hidapi.rs b/src/hidapi.rs index 701574e..983eaa4 100644 --- a/src/hidapi.rs +++ b/src/hidapi.rs @@ -251,6 +251,24 @@ impl HidDeviceBackendBase for HidDevice { self.check_size(res) } + fn send_output_report(&self, data: &[u8]) -> HidResult<()> { + if data.is_empty() { + return Err(HidError::InvalidZeroSizeData); + } + let res = unsafe { + ffi::hid_send_output_report(self._hid_device, data.as_ptr(), data.len() as size_t) + }; + let res = self.check_size(res)?; + if res != data.len() { + Err(HidError::IncompleteSendError { + sent: res, + all: data.len(), + }) + } else { + Ok(()) + } + } + fn set_blocking_mode(&self, blocking: bool) -> HidResult<()> { let res = unsafe { ffi::hid_set_nonblocking(self._hid_device, if blocking { 0i32 } else { 1i32 }) diff --git a/src/lib.rs b/src/lib.rs index 21ce7b8..e85ede4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -476,6 +476,7 @@ trait HidDeviceBackendBase { fn read_timeout(&self, buf: &mut [u8], timeout: i32) -> HidResult; fn send_feature_report(&self, data: &[u8]) -> HidResult<()>; fn get_feature_report(&self, buf: &mut [u8]) -> HidResult; + fn send_output_report(&self, data: &[u8]) -> HidResult<()>; fn set_blocking_mode(&self, blocking: bool) -> HidResult<()>; fn get_device_info(&self) -> HidResult; fn get_manufacturer_string(&self) -> HidResult>; @@ -594,6 +595,23 @@ impl HidDevice { self.inner.get_feature_report(buf) } + // Send a Output report to the device. + // + // Output reports are sent over the Control endpoint as a Set_Report + // transfer. The first byte of data[] must contain the Report ID. + // For devices which only support a single report, this must be set + // to 0x0. The remaining bytes contain the report data. Since the + // Report ID is mandatory, calls to hid_send_output_report() will + // always contain one more byte than the report contains. For example, + // if a hid report is 16 bytes long, 17 bytes must be passed to + // hid_send_output_report(): the Report ID (or 0x0, for devices + // which do not use numbered reports), followed by the report + // data (16 bytes). In this example, the length passed in + // would be 17. + pub fn send_output_report(&self, data: &[u8]) -> HidResult<()> { + self.inner.send_output_report(data) + } + /// Set the device handle to be in blocking or in non-blocking mode. In /// non-blocking mode calls to `read()` will return immediately with an empty /// slice if there is no data to be read. In blocking mode, `read()` will