Add experimental support for cloud flight wireless
This commit is contained in:
@@ -13,6 +13,7 @@ SUBSYSTEMS=="usb", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="069f", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="069f", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0995", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0995", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="02cc", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="02cc", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0e90", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
|
||||||
|
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="0d93", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0d93", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
@@ -30,3 +31,4 @@ KERNEL=="hidraw*", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="069f", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="069f", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="0995", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0995", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="02cc", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="02cc", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0e90", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ Both the CLI and tray applications are compatible with Linux, MacOS, and Windows
|
|||||||
- HyperX Cloud III S Wireless
|
- HyperX Cloud III S Wireless
|
||||||
- HyperX Cloud Stinger 2 Wireless
|
- HyperX Cloud Stinger 2 Wireless
|
||||||
- HyperX Cloud Flight S
|
- HyperX Cloud Flight S
|
||||||
|
- HyperX Cloud Flight Wireless
|
||||||
- HyperX Cloud Alpha Wireless
|
- HyperX Cloud Alpha Wireless
|
||||||
|
|
||||||
If your headset is not supported, feel free to open an issue; be sure to include the name, product ID, and vendor ID.
|
If your headset is not supported, feel free to open an issue; be sure to include the name, product ID, and vendor ID.
|
||||||
@@ -106,6 +107,7 @@ SUBSYSTEMS=="usb", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="069f", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="069f", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0995", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0995", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="02cc", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="02cc", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0e90", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="0d93", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0d93", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="018b", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="018b", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
@@ -122,6 +124,7 @@ KERNEL=="hidraw*", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="069f", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="069f", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="0995", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0995", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="02cc", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="02cc", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0e90", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
```
|
```
|
||||||
|
|
||||||
Once created, replug the wireless dongle.
|
Once created, replug the wireless dongle.
|
||||||
|
|||||||
174
src/devices/cloud_flight_wireless.rs
Normal file
174
src/devices/cloud_flight_wireless.rs
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
use crate::{
|
||||||
|
debug_println,
|
||||||
|
devices::{ChargingStatus, Device, DeviceEvent, DeviceState},
|
||||||
|
};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
const HP: u16 = 0x03F0;
|
||||||
|
pub const VENDOR_IDS: [u16; 1] = [HP];
|
||||||
|
pub const PRODUCT_IDS: [u16; 1] = [0x0e90];
|
||||||
|
|
||||||
|
const BASE_PACKET: [u8; 64] = {
|
||||||
|
let mut packet = [0; 64];
|
||||||
|
packet[0] = 33;
|
||||||
|
packet[1] = 255;
|
||||||
|
packet
|
||||||
|
};
|
||||||
|
|
||||||
|
const GET_BATTERY_CMD_ID: u8 = 5;
|
||||||
|
|
||||||
|
pub struct CloudFlightWireless {
|
||||||
|
state: DeviceState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CloudFlightWireless {
|
||||||
|
pub fn new_from_state(state: DeviceState) -> Self {
|
||||||
|
let mut state = state;
|
||||||
|
state.device_properties.connected = Some(true);
|
||||||
|
CloudFlightWireless { state }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const THRESHOLDS: [u16; 20] = [
|
||||||
|
3328, 3584, 3674, 3704, 3732, 3744, 3754, 3764, 3774, 3784, 3794, 3804, 3824, 3840, 3860, 3890,
|
||||||
|
3910, 3940, 3960, 3970,
|
||||||
|
];
|
||||||
|
|
||||||
|
const PERCENTAGES: [u8; 20] = [
|
||||||
|
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100,
|
||||||
|
];
|
||||||
|
|
||||||
|
impl Device for CloudFlightWireless {
|
||||||
|
fn get_battery_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[2] = GET_BATTERY_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_event_from_device_response(&self, response: &[u8]) -> Option<Vec<DeviceEvent>> {
|
||||||
|
debug_println!("Read packet: {:?}", response);
|
||||||
|
if response[0] != BASE_PACKET[0] || response[1] != BASE_PACKET[1] {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
match response[2] {
|
||||||
|
GET_BATTERY_CMD_ID => {
|
||||||
|
let upper = response[3];
|
||||||
|
let lower = response[4];
|
||||||
|
let mut events = Vec::new();
|
||||||
|
if (upper == 16 && lower >= 20) || upper >= 17 {
|
||||||
|
events.push(DeviceEvent::Charging(ChargingStatus::Charging));
|
||||||
|
} else {
|
||||||
|
let index =
|
||||||
|
match THRESHOLDS.binary_search(&(((upper as u16) << 8) | (lower as u16))) {
|
||||||
|
Ok(i) => i,
|
||||||
|
Err(0) => 0,
|
||||||
|
Err(i) => i - 1,
|
||||||
|
};
|
||||||
|
events.push(DeviceEvent::BatterLevel(PERCENTAGES[index]));
|
||||||
|
events.push(DeviceEvent::Charging(ChargingStatus::NotCharging));
|
||||||
|
}
|
||||||
|
Some(events)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
debug_println!("Unknown device event: {:?}", response);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_device_state(&self) -> &DeviceState {
|
||||||
|
&self.state
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_device_state_mut(&mut self) -> &mut DeviceState {
|
||||||
|
&mut self.state
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allow_passive_refresh(&mut self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_charging_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_automatic_shut_down_packet(&self, _shutdown_after: Duration) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_automatic_shut_down_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mute_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_mute_packet(&self, _mute: bool) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_surround_sound_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_surround_sound_packet(&self, _surround_sound: bool) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mic_connected_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_pairing_info_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_product_color_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_side_tone_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_side_tone_packet(&self, _side_tone_on: bool) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_side_tone_volume_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_side_tone_volume_packet(&self, _volume: u8) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_voice_prompt_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_voice_prompt_packet(&self, _enable: bool) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_wireless_connected_status_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_sirk_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_sirk_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_silent_mode_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_silent_mode_packet(&self, _silence: bool) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod cloud_alpha_wireless;
|
pub mod cloud_alpha_wireless;
|
||||||
|
pub mod cloud_flight_wireless;
|
||||||
pub mod cloud_ii_core_wireless;
|
pub mod cloud_ii_core_wireless;
|
||||||
pub mod cloud_ii_wireless;
|
pub mod cloud_ii_wireless;
|
||||||
pub mod cloud_ii_wireless_dts;
|
pub mod cloud_ii_wireless_dts;
|
||||||
@@ -8,9 +9,10 @@ pub mod cloud_iii_wireless;
|
|||||||
use crate::{
|
use crate::{
|
||||||
debug_println,
|
debug_println,
|
||||||
devices::{
|
devices::{
|
||||||
cloud_alpha_wireless::CloudAlphaWireless, cloud_ii_core_wireless::CloudIICoreWireless,
|
cloud_alpha_wireless::CloudAlphaWireless, cloud_flight_wireless::CloudFlightWireless,
|
||||||
cloud_ii_wireless::CloudIIWireless, cloud_ii_wireless_dts::CloudIIWirelessDTS,
|
cloud_ii_core_wireless::CloudIICoreWireless, cloud_ii_wireless::CloudIIWireless,
|
||||||
cloud_iii_s_wireless::CloudIIISWireless, cloud_iii_wireless::CloudIIIWireless,
|
cloud_ii_wireless_dts::CloudIIWirelessDTS, cloud_iii_s_wireless::CloudIIISWireless,
|
||||||
|
cloud_iii_wireless::CloudIIIWireless,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use hidapi::{HidApi, HidDevice, HidError};
|
use hidapi::{HidApi, HidDevice, HidError};
|
||||||
@@ -62,6 +64,11 @@ const DEVICE_REGISTER: &[DeviceEntry] = &[
|
|||||||
product_ids: &cloud_ii_core_wireless::PRODUCT_IDS,
|
product_ids: &cloud_ii_core_wireless::PRODUCT_IDS,
|
||||||
factory: |s| Box::new(CloudIICoreWireless::new_from_state(s)),
|
factory: |s| Box::new(CloudIICoreWireless::new_from_state(s)),
|
||||||
},
|
},
|
||||||
|
DeviceEntry {
|
||||||
|
vendor_ids: &cloud_flight_wireless::VENDOR_IDS,
|
||||||
|
product_ids: &cloud_flight_wireless::PRODUCT_IDS,
|
||||||
|
factory: |s| Box::new(CloudFlightWireless::new_from_state(s)),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const RESPONSE_BUFFER_SIZE: usize = 256;
|
const RESPONSE_BUFFER_SIZE: usize = 256;
|
||||||
|
|||||||
Reference in New Issue
Block a user