wooting_analog_plugin_dev/
lib.rs

1extern crate ffi_support;
2pub extern crate wooting_analog_common;
3
4use ffi_support::FfiStr;
5use std::collections::HashMap;
6use std::hash::Hasher;
7use std::os::raw::{c_float, c_ushort};
8use wooting_analog_common::*;
9
10pub static ANALOG_SDK_PLUGIN_VERSION: &str = env!("CARGO_PKG_VERSION");
11
12/// The core Plugin trait which needs to be implemented for an Analog Plugin to function
13pub trait Plugin {
14    /// Get a name describing the `Plugin`.
15    fn name(&mut self) -> SDKResult<&'static str>;
16
17    /// Initialise the plugin with the given function for device events. Returns an int indicating the number of connected devices
18    fn initialise(
19        &mut self,
20        callback: Box<dyn Fn(DeviceEventType, &DeviceInfo) + Send>,
21    ) -> SDKResult<u32>;
22
23    /// A function fired to check if the plugin is currently initialised
24    fn is_initialised(&mut self) -> bool;
25
26    /// This function is fired by the SDK to collect up all Device Info structs. The memory for the struct should be retained and only dropped
27    /// when the device is disconnected or the plugin is unloaded. This ensures that the Device Info is not garbled when it's being accessed by the client.
28    ///
29    /// # Notes
30    ///
31    /// Although, the client should be copying any data they want to use for a prolonged time as there is no lifetime guarantee on the data.
32    fn device_info(&mut self) -> SDKResult<Vec<DeviceInfo>>;
33
34    /// A callback fired immediately before the plugin is unloaded. Use this if
35    /// you need to do any cleanup.
36    fn unload(&mut self) {}
37
38    /// Function called to get the analog value for a particular HID key `code` from the device with ID `device`.
39    /// If `device` is 0 then no specific device is specified and the value should be read from all devices and combined
40    fn read_analog(&mut self, code: u16, device: DeviceID) -> SDKResult<f32>;
41
42    /// Function called to get the full analog read buffer for a particular device with ID `device`. `max_length` is the maximum amount
43    /// of keys that can be accepted, any more beyond this will be ignored by the SDK.
44    /// If `device` is 0 then no specific device is specified and the data should be read from all devices and combined
45    fn read_full_buffer(
46        &mut self,
47        max_length: usize,
48        device: DeviceID,
49    ) -> SDKResult<HashMap<c_ushort, c_float>>;
50}
51
52/// Declare a plugin type and its constructor.
53///
54/// # Notes
55///
56/// This works by automatically generating an `extern "C"` function with a
57/// pre-defined signature and symbol name. Therefore you will only be able to
58/// declare one plugin per library.
59#[macro_export]
60macro_rules! declare_plugin {
61    ($plugin_type:ty, $constructor:path) => {
62        #[no_mangle]
63        pub extern "C" fn _plugin_create() -> *mut $crate::Plugin {
64            // make sure the constructor is the correct type.
65            let constructor: fn() -> $plugin_type = $constructor;
66
67            let object = constructor();
68            let boxed: Box<$crate::Plugin> = Box::new(object);
69            Box::into_raw(boxed)
70        }
71
72        #[no_mangle]
73        pub extern "C" fn plugin_version() -> &'static str {
74            ANALOG_SDK_PLUGIN_VERSION
75        }
76    };
77}
78
79pub fn generate_device_id(serial_number: &str, vendor_id: u16, product_id: u16) -> DeviceID {
80    use std::collections::hash_map::DefaultHasher;
81    let mut s = DefaultHasher::new();
82    s.write_u16(vendor_id);
83    s.write_u16(product_id);
84    s.write(serial_number.as_bytes());
85    s.finish()
86}
87
88mod ffi {
89    use super::*;
90
91    #[no_mangle]
92    pub extern "C" fn generate_device_id(
93        serial_number: FfiStr,
94        vendor_id: u16,
95        product_id: u16,
96    ) -> DeviceID {
97        let serial = {
98            if let Some(str) = serial_number.into_opt_string() {
99                str
100            } else {
101                return 0;
102            }
103        };
104        super::generate_device_id(&serial, vendor_id, product_id)
105    }
106}