1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//! Contain interfaces filters.

use std::fmt::{Display, Formatter};

use hidapi::DeviceInfo;
#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};

/// Product is of the Vulcan 100.
const VULCAN_100_PRODUCT_ID: u16 = 12_410;
/// Product is of the Vulcan 120.
const VULCAN_120_PRODUCT_ID: u16 = 12_440;
/// Defaut usage page for the read device.
/// The reason the usage page is 10 is unkown and may change for diffrent device.
const USAGE_PAGE_READ_DEVICE: u16 = 10;
/// Defaut interface number of the read device.
const READ_INTERFACE_NUMBER: i32 = 1_i32;
/// Defaut interface number of the control device.
const CONTROL_INTERFACE_NUMBER: i32 = 1_i32;
/// Defaut interface number of the led device.
const LED_INTERFACE_NUMBER: i32 = 3_i32;

/// Basic HID interface filter with a product id and an interface number.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct HidInterfaceFilter {
    /// Product number
    product_id: u16,
    /// interface of communication
    interface_number: i32,
    /// Optionally an usage page
    usage_page: Option<u16>,
}

impl HidInterfaceFilter {
    /// Create a new [`HidInterfaceFilter`]
    pub const fn new(product_id: u16, interface_number: i32) -> Self {
        Self {
            product_id,
            interface_number,
            usage_page: None,
        }
    }

    /// Create a new filter with an usage page
    pub const fn new_with_usage_page(
        product_id: u16,
        interface_number: i32,
        usage_page: u16,
    ) -> Self {
        Self {
            product_id,
            interface_number,
            usage_page: Some(usage_page),
        }
    }

    /// Get the product id.
    pub const fn product_id(&self) -> u16 {
        self.product_id
    }

    /// Get the product id as a mut ref.
    pub fn product_id_mut(&mut self) -> &mut u16 {
        &mut self.product_id
    }

    /// Get the interface numer.
    pub const fn interface_number(&self) -> i32 {
        self.interface_number
    }

    /// Get the interface numer as a mut reference.
    pub fn interface_number_mut(&mut self) -> &mut i32 {
        &mut self.interface_number
    }

    /// Get the usage page
    pub const fn usage_page(&self) -> Option<u16> {
        self.usage_page
    }

    /// Get a mut reference to the usage page
    pub fn usage_page_mut(&mut self) -> &mut Option<u16> {
        &mut self.usage_page
    }

    /// returns whether or not a device match the filter
    pub fn match_filter(&self, device: &DeviceInfo) -> bool {
        let match_usage = if let Some(val) = self.usage_page() {
            val == device.usage_page()
        } else {
            true
        };
        match_usage
            && self.product_id() == device.product_id()
            && self.interface_number() == device.interface_number()
    }
}

impl Display for HidInterfaceFilter {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        // TODO improve
        write!(
            f,
            "product id: {}, interface number: {}",
            self.product_id(),
            self.interface_number()
        )?;
        if let Some(page) = self.usage_page {
            return write!(f, ", usage page {}", page);
        }
        Ok(())
    }
}

/// liste the filter for the differents devices used by [`super::KeyboardApi`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct KeyboardIntrefacesFilter {
    /// The read device filter
    read_interface: HidInterfaceFilter,
    /// The control device filter
    control_interface: HidInterfaceFilter,
    /// The led device filter
    led_interface: HidInterfaceFilter,
}

impl KeyboardIntrefacesFilter {
    /// Get the read interface.
    pub const fn read_interface(&self) -> &HidInterfaceFilter {
        &self.read_interface
    }

    /// Get the read interface as a mutable reference.
    pub fn read_interface_mut(&mut self) -> &mut HidInterfaceFilter {
        &mut self.read_interface
    }

    /// Get the control interface.
    pub const fn control_interface(&self) -> &HidInterfaceFilter {
        &self.control_interface
    }

    /// Get the control interface as a mutable reference.
    pub fn control_interface_mut(&mut self) -> &mut HidInterfaceFilter {
        &mut self.control_interface
    }

    /// Get the led interface.
    pub const fn led_interface(&self) -> &HidInterfaceFilter {
        &self.led_interface
    }

    /// Get the led interface as a mutable reference.
    pub fn led_interface_mut(&mut self) -> &mut HidInterfaceFilter {
        &mut self.led_interface
    }

    /// Default vulcan 100 info.
    pub const fn vulcan_100() -> Self {
        let product_id = VULCAN_100_PRODUCT_ID;
        Self {
            read_interface: HidInterfaceFilter::new_with_usage_page(
                product_id,
                READ_INTERFACE_NUMBER,
                USAGE_PAGE_READ_DEVICE,
            ),
            control_interface: HidInterfaceFilter::new(product_id, CONTROL_INTERFACE_NUMBER),
            led_interface: HidInterfaceFilter::new(product_id, LED_INTERFACE_NUMBER),
        }
    }

    /// Default vulcan 120 info.
    pub const fn vulcan_120() -> Self {
        let product_id = VULCAN_120_PRODUCT_ID;
        Self {
            read_interface: HidInterfaceFilter::new_with_usage_page(
                product_id,
                READ_INTERFACE_NUMBER,
                USAGE_PAGE_READ_DEVICE,
            ),
            control_interface: HidInterfaceFilter::new(product_id, CONTROL_INTERFACE_NUMBER),
            led_interface: HidInterfaceFilter::new(product_id, LED_INTERFACE_NUMBER),
        }
    }

    /// Array containg the default models.
    pub const DEFAULT_MODEL: [Self; 2] = [Self::vulcan_100(), Self::vulcan_120()];
}

impl Display for KeyboardIntrefacesFilter {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "read_interface: {}, control_interface: {}, led_interface: {}",
            self.read_interface(),
            self.control_interface(),
            self.led_interface()
        )
    }
}

impl Default for KeyboardIntrefacesFilter {
    fn default() -> Self {
        Self::vulcan_120()
    }
}