1use core::ffi::c_char;
2use std::fmt;
3
4use bitflags::bitflags;
5use cue_sdk_sys as ffi;
6
7#[derive(Clone, Copy, PartialEq, Eq, Hash)]
16pub struct DeviceId(pub(crate) ffi::CorsairDeviceId);
17
18impl DeviceId {
19 pub(crate) fn as_ptr(&self) -> *const c_char {
21 self.0.as_ptr()
22 }
23
24 pub(crate) fn from_ffi(raw: ffi::CorsairDeviceId) -> Self {
26 Self(raw)
27 }
28}
29
30impl fmt::Debug for DeviceId {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 write!(f, "DeviceId(\"{}\")", self)
33 }
34}
35
36impl fmt::Display for DeviceId {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 let bytes = self.0.map(|c| c as u8);
39 let len = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
40 let s = std::str::from_utf8(&bytes[..len]).unwrap_or("<invalid utf8>");
41 f.write_str(s)
42 }
43}
44
45bitflags! {
50 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
52 pub struct DeviceType: u32 {
53 const UNKNOWN = ffi::CorsairDeviceType_CDT_Unknown;
54 const KEYBOARD = ffi::CorsairDeviceType_CDT_Keyboard;
55 const MOUSE = ffi::CorsairDeviceType_CDT_Mouse;
56 const MOUSEMAT = ffi::CorsairDeviceType_CDT_Mousemat;
57 const HEADSET = ffi::CorsairDeviceType_CDT_Headset;
58 const HEADSET_STAND = ffi::CorsairDeviceType_CDT_HeadsetStand;
59 const FAN_LED_CONTROLLER = ffi::CorsairDeviceType_CDT_FanLedController;
60 const LED_CONTROLLER = ffi::CorsairDeviceType_CDT_LedController;
61 const MEMORY_MODULE = ffi::CorsairDeviceType_CDT_MemoryModule;
62 const COOLER = ffi::CorsairDeviceType_CDT_Cooler;
63 const MOTHERBOARD = ffi::CorsairDeviceType_CDT_Motherboard;
64 const GRAPHICS_CARD = ffi::CorsairDeviceType_CDT_GraphicsCard;
65 const TOUCHBAR = ffi::CorsairDeviceType_CDT_Touchbar;
66 const GAME_CONTROLLER = ffi::CorsairDeviceType_CDT_GameController;
67 const ALL = ffi::CorsairDeviceType_CDT_All;
68 }
69}
70
71#[derive(Debug, Clone)]
77pub struct DeviceInfo {
78 pub device_type: DeviceType,
80 pub id: DeviceId,
82 pub serial: String,
84 pub model: String,
86 pub led_count: i32,
88 pub channel_count: i32,
90}
91
92impl DeviceInfo {
93 pub(crate) fn from_ffi(raw: &ffi::CorsairDeviceInfo) -> Self {
95 Self {
96 device_type: DeviceType::from_bits_truncate(raw.type_),
97 id: DeviceId::from_ffi(raw.id),
98 serial: c_char_array_to_string(&raw.serial),
99 model: c_char_array_to_string(&raw.model),
100 led_count: raw.ledCount,
101 channel_count: raw.channelCount,
102 }
103 }
104}
105
106fn c_char_array_to_string(arr: &[c_char]) -> String {
109 let bytes: Vec<u8> = arr
110 .iter()
111 .map(|&c| c as u8)
112 .take_while(|&b| b != 0)
113 .collect();
114 String::from_utf8_lossy(&bytes).into_owned()
115}