xencelabs_quick_keys/
lib.rs

1#![allow(dead_code)]
2extern crate hidapi;
3
4use hidapi::{HidApi, HidDevice};
5
6mod error;
7mod msgs;
8
9pub use error::QKError;
10pub use msgs::{ButtonState, Event, ScreenOrientation, WheelDirection, ScreenBrightness, WheelSpeed};
11use msgs::*;
12
13/// Connection method (cable, wireless, or automatic...)
14#[derive(Debug, PartialEq, Clone, Copy, Default)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub enum ConnectionMode {
17    #[default]
18    Wired,
19    Wireless,  // NOTE: Not implemented yet
20    Auto,
21}
22
23pub type QKResult<T> = Result<T, QKError>;
24
25
26/// Use to send and receive commands from a particular Quick Keys device.
27pub struct QKDevice {
28    device: HidDevice,
29}
30
31impl QKDevice {
32    /// Search and connect to a Quick Keys device using a HidApi instance.
33    pub fn open(hidapi: HidApi, mode: ConnectionMode) -> QKResult<Self> {
34        let this = hidapi
35            .device_list()
36            .find(|&dev| {
37                dev.vendor_id() == 0x28BD
38                    && ((dev.product_id() == 0x5202 && mode != ConnectionMode::Wireless)
39                        || (dev.product_id() == 0x5204 && mode != ConnectionMode::Wired))
40                    && dev.usage() == 1
41                    && dev.usage_page() == 0xff0a
42            })
43            .map(|dev| match dev.open_device(&hidapi) {
44                Ok(d) => Ok(QKDevice { device: d }),
45                Err(_) => Err(QKError::QKConnectionError),
46            })
47            .or_else(|| Some(Err(QKError::QKDeviceNotFound)))
48            .unwrap()?;
49        this.device.write(&msg_subscribe_to_key_events())?;
50        this.device.write(&msg_subscribe_to_battery())?;
51        Ok(this)
52    }
53
54    //
55    // Output Api
56    //
57
58    /// Rotate the screen to the given angle.
59    pub fn set_screen_orientation(&self, orientation: ScreenOrientation) -> QKResult<()> {
60        self.device.write(&msg_rotate_screen(orientation))?;
61        Ok(())
62    }
63
64    /// Set screen brightness to the given level.
65    pub fn set_screen_brightness(&self, level: ScreenBrightness) -> QKResult<()> {
66        self.device.write(&msg_set_screen_brightness(level))?;
67        Ok(())
68    }
69
70
71    /// Set the wheel speed to the given value.
72    pub fn set_wheel_speed(&self, speed: WheelSpeed) -> QKResult<()> {
73        self.device.write(&msg_set_wheel_speed(speed))?;
74        Ok(())
75    }
76
77    /// Switch off the device after the given amount of minutes (after connection is lost).
78    pub fn set_sleep_timeout(&self, minutes: u8) -> QKResult<()> {
79        self.device.write(&msg_set_sleep_timeout(minutes))?;
80        Ok(())
81    }
82
83    /// Set the color of the LED ring of the wheel to the given RGB value.
84    pub fn set_ring_color(&self, red: u8, green: u8, blue: u8) -> QKResult<()> {
85        self.device.write(&msg_set_wheel_color(red, green, blue))?;
86        Ok(())
87    }
88
89    /// Set the text label for the given key (0-7).  (max 8 characters, ATM).
90    pub fn set_key_text(&self, key: u8, text: &str) -> QKResult<()> {
91        self.device.write(&msg_set_key_text(key, text))?;
92        Ok(())
93    }
94
95
96    /// Show a text overlay for a fix amount of time (max 32 characters).
97    pub fn show_overlay_text(&self, text: &str, seconds: u8) -> QKResult<()> {
98        for chunk in &msgs_show_overlay_text(seconds, text) {
99            self.device.write(chunk)?;
100        }
101        Ok(())
102    }
103
104    //
105    // Input Api
106    //
107
108    /// Set the blocking mode (see hidapi for details).
109    pub fn set_blocking_mode(&self, blocking: bool) -> QKResult<()> {
110        self.device.set_blocking_mode(blocking).map_err(QKError::QKHidError)
111    }
112
113    /// Read the next Event.  By default in blocks (unless set_blocking_mode(false)).
114    pub fn read(&self) -> QKResult<Event> {
115        let mut buf = [0u8; 10];
116        self.device.read(&mut buf[..])?;
117        Ok(process_input(&buf))
118    }
119
120
121    /// Try to read the next Event in the next number of milliseconds. 
122    pub fn read_timeout(&self, timeout: i32) -> QKResult<Event> {
123        let mut buf = [0u8; 10];
124        match self.device.read_timeout(&mut buf[..], timeout) {
125            Ok(_) => Ok(process_input(&buf)),
126            Err(e) => Err(QKError::QKHidError(e)),
127        }
128    }
129}