Add initial code for supporting cloud II core wireless
This commit is contained in:
@@ -10,6 +10,7 @@ SUBSYSTEMS=="usb", ATTRS{idProduct}=="0c9d", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="098d", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="098d", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1765", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1765", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0aa0", 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"
|
||||||
@@ -24,3 +25,4 @@ KERNEL=="hidraw*", ATTRS{idProduct}=="0c9d", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="098d", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="098d", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="1765", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="1765", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0aa0", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ However, the tray application is only functional on Linux.
|
|||||||
**Supported Headsets**:
|
**Supported Headsets**:
|
||||||
- HyperX Cloud II Wireless HP vendorID
|
- HyperX Cloud II Wireless HP vendorID
|
||||||
- HyperX Cloud II Wireless HyperX vendorID
|
- HyperX Cloud II Wireless HyperX vendorID
|
||||||
|
- HyperX Cloud II Core Wireless
|
||||||
- HyperX Cloud III Wireless
|
- HyperX Cloud III Wireless
|
||||||
- HyperX Cloud III S Wireless
|
- HyperX Cloud III S Wireless
|
||||||
- HyperX Cloud Stinger 2 Wireless
|
- HyperX Cloud Stinger 2 Wireless
|
||||||
@@ -103,6 +104,7 @@ SUBSYSTEMS=="usb", ATTRS{idProduct}=="0c9d", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="098d", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="098d", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1765", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1765", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0aa0", 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"
|
||||||
@@ -116,6 +118,7 @@ KERNEL=="hidraw*", ATTRS{idProduct}=="0c9d", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="098d", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="098d", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="1765", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="1765", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="1743", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0aa0", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
```
|
```
|
||||||
|
|
||||||
Once created, replug the wireless dongle.
|
Once created, replug the wireless dongle.
|
||||||
|
|||||||
268
src/devices/cloud_ii_core_wireless.rs
Normal file
268
src/devices/cloud_ii_core_wireless.rs
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
use crate::{
|
||||||
|
debug_println,
|
||||||
|
devices::{ChargingStatus, Device, DeviceError, DeviceEvent, DeviceState},
|
||||||
|
};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
const HP: u16 = 0x03F0;
|
||||||
|
pub const VENDOR_IDS: [u16; 1] = [HP];
|
||||||
|
pub const PRODUCT_IDS: [u16; 1] = [0x0aa0];
|
||||||
|
|
||||||
|
const BASE_PACKET: [u8; 64] = {
|
||||||
|
let mut packet = [0; 64];
|
||||||
|
packet[0] = 102;
|
||||||
|
packet
|
||||||
|
};
|
||||||
|
|
||||||
|
const GET_CHARGING_CMD_ID: u8 = 138;
|
||||||
|
const CHARGING_RESPONSE_ID: u8 = 12;
|
||||||
|
const GET_MIC_CONNECTED_CMD_ID: u8 = 140;
|
||||||
|
const GET_BATTERY_CMD_ID: u8 = 137;
|
||||||
|
const BATTERY_RESPONSE_ID: u8 = 13;
|
||||||
|
const GET_AUTO_SHUTDOWN_CMD_ID: u8 = 133;
|
||||||
|
const SET_AUTO_SHUTDOWN_CMD_ID: u8 = 2;
|
||||||
|
const GET_MUTE_CMD_ID: u8 = 134;
|
||||||
|
const MUTE_RESPONSE_ID: u8 = 10;
|
||||||
|
const SET_MUTE_CMD_ID: u8 = 3;
|
||||||
|
const GET_PAIRING_CMD_ID: u8 = 129;
|
||||||
|
const GET_SIDE_TONE_ON_CMD_ID: u8 = 132;
|
||||||
|
const SIDE_TONE_RESPONSE_ID: u8 = 9;
|
||||||
|
const SET_SIDE_TONE_ON_CMD_ID: u8 = 1;
|
||||||
|
const GET_SIDE_TONE_VOLUME_CMD_ID: u8 = 136;
|
||||||
|
const SET_SIDE_TONE_VOLUME_CMD_ID: u8 = 5;
|
||||||
|
const GET_WIRELESS_STATUS_CMD_ID: u8 = 130;
|
||||||
|
const WIRELESS_STATUS_RESPONSE_ID: u8 = 11;
|
||||||
|
const GET_PLAY_BACK_MUTE_CMD_ID: u8 = 135;
|
||||||
|
const SET_PLAY_BACK_MUTE_CMD_ID: u8 = 4;
|
||||||
|
const GET_NOISE_GATE_CMD_ID: u8 = 141;
|
||||||
|
const SET_NOISE_GATE_CMD_ID: u8 = 15;
|
||||||
|
|
||||||
|
pub struct CloudIICoreWireless {
|
||||||
|
state: DeviceState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CloudIICoreWireless {
|
||||||
|
pub fn new_from_state(state: DeviceState) -> Self {
|
||||||
|
let mut state = state;
|
||||||
|
state.connected = Some(true);
|
||||||
|
CloudIICoreWireless { state }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> Result<Self, DeviceError> {
|
||||||
|
let mut state = DeviceState::new(&PRODUCT_IDS, &VENDOR_IDS)?;
|
||||||
|
state.connected = Some(true);
|
||||||
|
Ok(CloudIICoreWireless { state })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Device for CloudIICoreWireless {
|
||||||
|
fn get_charging_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_CHARGING_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_battery_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_BATTERY_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_automatic_shut_down_packet(&self, shutdown_after: Duration) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = SET_AUTO_SHUTDOWN_CMD_ID;
|
||||||
|
tmp[2] = (shutdown_after.as_secs() / 60) as u8;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_automatic_shut_down_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_AUTO_SHUTDOWN_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mute_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_MUTE_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_mute_packet(&self, mute: bool) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = SET_MUTE_CMD_ID;
|
||||||
|
tmp[2] = mute as u8;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
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>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_MIC_CONNECTED_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_pairing_info_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_PAIRING_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_product_color_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_side_tone_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_SIDE_TONE_ON_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_side_tone_packet(&self, side_tone_on: bool) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = SET_SIDE_TONE_ON_CMD_ID;
|
||||||
|
tmp[2] = side_tone_on as u8;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_side_tone_volume_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_SIDE_TONE_VOLUME_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_side_tone_volume_packet(&self, volume: u8) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = SET_SIDE_TONE_VOLUME_CMD_ID;
|
||||||
|
tmp[2] = (volume as i8).clamp(-5, 5) as u8;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
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>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_WIRELESS_STATUS_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
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>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_PLAY_BACK_MUTE_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_silent_mode_packet(&self, silence: bool) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = SET_PLAY_BACK_MUTE_CMD_ID;
|
||||||
|
tmp[2] = silence as u8;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_noise_gate_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = GET_NOISE_GATE_CMD_ID;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_noise_gate_packet(&self, enable: bool) -> Option<Vec<u8>> {
|
||||||
|
let mut tmp = BASE_PACKET.to_vec();
|
||||||
|
tmp[1] = SET_NOISE_GATE_CMD_ID;
|
||||||
|
tmp[2] = enable as u8;
|
||||||
|
Some(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_event_from_device_response(&self, response: &[u8]) -> Option<Vec<DeviceEvent>> {
|
||||||
|
debug_println!("Read packet: {:?}", response);
|
||||||
|
if response[0] != 102 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
match (response[1], response[2], response[3], response[4]) {
|
||||||
|
(GET_CHARGING_CMD_ID, status, _, _) | (CHARGING_RESPONSE_ID, status, _, _) => {
|
||||||
|
Some(vec![DeviceEvent::Charging(ChargingStatus::from(status))])
|
||||||
|
}
|
||||||
|
(GET_MIC_CONNECTED_CMD_ID, status, _, _) => {
|
||||||
|
Some(vec![DeviceEvent::MicConnected(status == 1)])
|
||||||
|
}
|
||||||
|
(GET_BATTERY_CMD_ID, b2, b3, level) | (BATTERY_RESPONSE_ID, b2, b3, level) => {
|
||||||
|
if b2 != 0 || b3 != 0 {
|
||||||
|
Some(vec![DeviceEvent::BatterLevel(level)])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(GET_AUTO_SHUTDOWN_CMD_ID, time, _, _) | (SET_AUTO_SHUTDOWN_CMD_ID, time, _, _) => {
|
||||||
|
Some(vec![DeviceEvent::AutomaticShutdownAfter(
|
||||||
|
Duration::from_secs(time as u64 * 60),
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
(SET_MUTE_CMD_ID, status, _, _)
|
||||||
|
| (GET_MUTE_CMD_ID, status, _, _)
|
||||||
|
| (MUTE_RESPONSE_ID, status, _, _) => Some(vec![DeviceEvent::Muted(status == 1)]),
|
||||||
|
(GET_PAIRING_CMD_ID, status, _, _) => Some(vec![DeviceEvent::PairingInfo(status)]),
|
||||||
|
(GET_SIDE_TONE_ON_CMD_ID, status, _, _)
|
||||||
|
| (SET_SIDE_TONE_ON_CMD_ID, status, _, _)
|
||||||
|
| (SIDE_TONE_RESPONSE_ID, status, _, _) => {
|
||||||
|
Some(vec![DeviceEvent::SideToneOn(status == 1)])
|
||||||
|
}
|
||||||
|
(GET_SIDE_TONE_VOLUME_CMD_ID, status, _, _)
|
||||||
|
| (SET_SIDE_TONE_VOLUME_CMD_ID, status, _, _) => {
|
||||||
|
let status = if status >= 251 {
|
||||||
|
(status as i32 | -256i32) as u8
|
||||||
|
} else if (0..=5).contains(&status) {
|
||||||
|
status
|
||||||
|
} else {
|
||||||
|
0u8
|
||||||
|
};
|
||||||
|
Some(vec![DeviceEvent::SideToneVolume(status)])
|
||||||
|
}
|
||||||
|
(GET_WIRELESS_STATUS_CMD_ID, status, _, _)
|
||||||
|
| (WIRELESS_STATUS_RESPONSE_ID, status, _, _) => {
|
||||||
|
Some(vec![DeviceEvent::WirelessConnected(status == 1)])
|
||||||
|
}
|
||||||
|
(GET_PLAY_BACK_MUTE_CMD_ID, status, _, _)
|
||||||
|
| (SET_PLAY_BACK_MUTE_CMD_ID, status, _, _) => {
|
||||||
|
Some(vec![DeviceEvent::Silent(status == 1)])
|
||||||
|
}
|
||||||
|
(GET_NOISE_GATE_CMD_ID, status, _, _) | (SET_NOISE_GATE_CMD_ID, status, _, _) => {
|
||||||
|
Some(vec![DeviceEvent::NoiseGateActive(status == 1)])
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod cloud_alpha_wireless;
|
pub mod cloud_alpha_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;
|
||||||
pub mod cloud_iii_s_wireless;
|
pub mod cloud_iii_s_wireless;
|
||||||
@@ -7,9 +8,9 @@ pub mod cloud_iii_wireless;
|
|||||||
use crate::{
|
use crate::{
|
||||||
debug_println,
|
debug_println,
|
||||||
devices::{
|
devices::{
|
||||||
cloud_alpha_wireless::CloudAlphaWireless, cloud_ii_wireless::CloudIIWireless,
|
cloud_alpha_wireless::CloudAlphaWireless, cloud_ii_core_wireless::CloudIICoreWireless,
|
||||||
cloud_ii_wireless_dts::CloudIIWirelessDTS, cloud_iii_s_wireless::CloudIIISWireless,
|
cloud_ii_wireless::CloudIIWireless, cloud_ii_wireless_dts::CloudIIWirelessDTS,
|
||||||
cloud_iii_wireless::CloudIIIWireless,
|
cloud_iii_s_wireless::CloudIIISWireless, cloud_iii_wireless::CloudIIIWireless,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use hidapi::{HidApi, HidDevice, HidError};
|
use hidapi::{HidApi, HidDevice, HidError};
|
||||||
@@ -50,6 +51,11 @@ const DEVICE_REGISTER: &[DeviceEntry] = &[
|
|||||||
product_ids: &cloud_alpha_wireless::PRODUCT_IDS,
|
product_ids: &cloud_alpha_wireless::PRODUCT_IDS,
|
||||||
factory: |s| Box::new(CloudAlphaWireless::new_from_state(s)),
|
factory: |s| Box::new(CloudAlphaWireless::new_from_state(s)),
|
||||||
},
|
},
|
||||||
|
DeviceEntry {
|
||||||
|
vendor_ids: &cloud_ii_core_wireless::VENDOR_IDS,
|
||||||
|
product_ids: &cloud_ii_core_wireless::PRODUCT_IDS,
|
||||||
|
factory: |s| Box::new(CloudIICoreWireless::new_from_state(s)),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const RESPONSE_BUFFER_SIZE: usize = 256;
|
const RESPONSE_BUFFER_SIZE: usize = 256;
|
||||||
@@ -103,6 +109,7 @@ pub struct DeviceState {
|
|||||||
pub voice_prompt_on: Option<bool>,
|
pub voice_prompt_on: Option<bool>,
|
||||||
pub connected: Option<bool>,
|
pub connected: Option<bool>,
|
||||||
pub silent: Option<bool>,
|
pub silent: Option<bool>,
|
||||||
|
pub noise_gate_active: Option<bool>,
|
||||||
// Capability flags - set once during device initialization
|
// Capability flags - set once during device initialization
|
||||||
pub can_set_mute: bool,
|
pub can_set_mute: bool,
|
||||||
pub can_set_surround_sound: bool,
|
pub can_set_surround_sound: bool,
|
||||||
@@ -112,6 +119,7 @@ pub struct DeviceState {
|
|||||||
pub can_set_voice_prompt: bool,
|
pub can_set_voice_prompt: bool,
|
||||||
pub can_set_silent_mode: bool,
|
pub can_set_silent_mode: bool,
|
||||||
pub can_set_equalizer: bool,
|
pub can_set_equalizer: bool,
|
||||||
|
pub can_set_noise_gate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for DeviceState {
|
impl Display for DeviceState {
|
||||||
@@ -208,6 +216,7 @@ impl DeviceState {
|
|||||||
voice_prompt_on: None,
|
voice_prompt_on: None,
|
||||||
connected: None,
|
connected: None,
|
||||||
silent: None,
|
silent: None,
|
||||||
|
noise_gate_active: None,
|
||||||
// Capability flags - will be set by init_capabilities()
|
// Capability flags - will be set by init_capabilities()
|
||||||
can_set_mute: false,
|
can_set_mute: false,
|
||||||
can_set_surround_sound: false,
|
can_set_surround_sound: false,
|
||||||
@@ -217,6 +226,7 @@ impl DeviceState {
|
|||||||
can_set_voice_prompt: false,
|
can_set_voice_prompt: false,
|
||||||
can_set_silent_mode: false,
|
can_set_silent_mode: false,
|
||||||
can_set_equalizer: false,
|
can_set_equalizer: false,
|
||||||
|
can_set_noise_gate: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,18 +299,24 @@ impl DeviceState {
|
|||||||
"",
|
"",
|
||||||
!self.can_set_voice_prompt,
|
!self.can_set_voice_prompt,
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"Connected:",
|
|
||||||
self.connected.map(|c| c.to_string()),
|
|
||||||
"",
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"Playback muted:",
|
"Playback muted:",
|
||||||
self.silent.map(|c| c.to_string()),
|
self.silent.map(|c| c.to_string()),
|
||||||
"",
|
"",
|
||||||
!self.can_set_silent_mode,
|
!self.can_set_silent_mode,
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"Noise gate active:",
|
||||||
|
self.noise_gate_active.map(|c| c.to_string()),
|
||||||
|
"",
|
||||||
|
!self.can_set_noise_gate,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Connected:",
|
||||||
|
self.connected.map(|c| c.to_string()),
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,8 +367,9 @@ impl DeviceState {
|
|||||||
DeviceEvent::WirelessConnected(connected) => self.connected = Some(*connected),
|
DeviceEvent::WirelessConnected(connected) => self.connected = Some(*connected),
|
||||||
DeviceEvent::Silent(silent) => self.silent = Some(*silent),
|
DeviceEvent::Silent(silent) => self.silent = Some(*silent),
|
||||||
DeviceEvent::RequireSIRKReset(reset) => {
|
DeviceEvent::RequireSIRKReset(reset) => {
|
||||||
println!("requested SIRK reset {reset}")
|
debug_println!("requested SIRK reset {reset}");
|
||||||
}
|
}
|
||||||
|
DeviceEvent::NoiseGateActive(on) => self.noise_gate_active = Some(*on),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,6 +387,7 @@ impl DeviceState {
|
|||||||
self.voice_prompt_on = None;
|
self.voice_prompt_on = None;
|
||||||
self.connected = None;
|
self.connected = None;
|
||||||
self.silent = None;
|
self.silent = None;
|
||||||
|
self.noise_gate_active = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,6 +421,7 @@ pub enum DeviceEvent {
|
|||||||
SurroundSound(bool),
|
SurroundSound(bool),
|
||||||
Silent(bool),
|
Silent(bool),
|
||||||
RequireSIRKReset(bool),
|
RequireSIRKReset(bool),
|
||||||
|
NoiseGateActive(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@@ -504,6 +523,12 @@ pub trait Device {
|
|||||||
fn set_equalizer_band_packet(&self, _band_index: u8, _db_value: f32) -> Option<Vec<u8>> {
|
fn set_equalizer_band_packet(&self, _band_index: u8, _db_value: f32) -> Option<Vec<u8>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
fn get_noise_gate_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn set_noise_gate_packet(&self, _enable: bool) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
fn get_event_from_device_response(&self, response: &[u8]) -> Option<Vec<DeviceEvent>>;
|
fn get_event_from_device_response(&self, response: &[u8]) -> Option<Vec<DeviceEvent>>;
|
||||||
fn get_device_state(&self) -> &DeviceState;
|
fn get_device_state(&self) -> &DeviceState;
|
||||||
fn get_device_state_mut(&mut self) -> &mut DeviceState;
|
fn get_device_state_mut(&mut self) -> &mut DeviceState;
|
||||||
@@ -537,6 +562,9 @@ pub trait Device {
|
|||||||
fn can_set_equalizer(&self) -> bool {
|
fn can_set_equalizer(&self) -> bool {
|
||||||
self.set_equalizer_band_packet(0, 0.0).is_some()
|
self.set_equalizer_band_packet(0, 0.0).is_some()
|
||||||
}
|
}
|
||||||
|
fn can_set_noise_gate(&self) -> bool {
|
||||||
|
self.set_noise_gate_packet(true).is_none()
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize capability flags in device state
|
// Initialize capability flags in device state
|
||||||
fn init_capabilities(&mut self) {
|
fn init_capabilities(&mut self) {
|
||||||
@@ -549,6 +577,7 @@ pub trait Device {
|
|||||||
let can_set_voice_prompt = self.can_set_voice_prompt();
|
let can_set_voice_prompt = self.can_set_voice_prompt();
|
||||||
let can_set_silent_mode = self.can_set_silent_mode();
|
let can_set_silent_mode = self.can_set_silent_mode();
|
||||||
let can_set_equalizer = self.can_set_equalizer();
|
let can_set_equalizer = self.can_set_equalizer();
|
||||||
|
let can_set_noise_gate = self.can_set_noise_gate();
|
||||||
|
|
||||||
// Now set them in device state
|
// Now set them in device state
|
||||||
let state = self.get_device_state_mut();
|
let state = self.get_device_state_mut();
|
||||||
@@ -560,6 +589,7 @@ pub trait Device {
|
|||||||
state.can_set_voice_prompt = can_set_voice_prompt;
|
state.can_set_voice_prompt = can_set_voice_prompt;
|
||||||
state.can_set_silent_mode = can_set_silent_mode;
|
state.can_set_silent_mode = can_set_silent_mode;
|
||||||
state.can_set_equalizer = can_set_equalizer;
|
state.can_set_equalizer = can_set_equalizer;
|
||||||
|
state.can_set_noise_gate = can_set_noise_gate;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_headset_specific_functionality(&mut self) -> Result<(), DeviceError> {
|
fn execute_headset_specific_functionality(&mut self) -> Result<(), DeviceError> {
|
||||||
@@ -597,6 +627,7 @@ pub trait Device {
|
|||||||
self.get_voice_prompt_packet(),
|
self.get_voice_prompt_packet(),
|
||||||
self.get_sirk_packet(),
|
self.get_sirk_packet(),
|
||||||
self.get_silent_mode_packet(),
|
self.get_silent_mode_packet(),
|
||||||
|
self.get_noise_gate_packet(),
|
||||||
];
|
];
|
||||||
|
|
||||||
self.execute_headset_specific_functionality()?;
|
self.execute_headset_specific_functionality()?;
|
||||||
|
|||||||
Reference in New Issue
Block a user