Merge pull request #16 from Nubebuster/cloud-iii-s-support
Add Cloud III S Wireless support (partial)
This commit is contained in:
@@ -14,6 +14,7 @@ Although it was only tested on Manjaro and Kubuntu with KDE, it should also work
|
|||||||
- 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 III Wireless
|
- HyperX Cloud III Wireless
|
||||||
|
- HyperX Cloud III S Wireless
|
||||||
- HyperX Cloud Stinger 2 Wireless
|
- HyperX Cloud Stinger 2 Wireless
|
||||||
- HyperX Cloud Flight S
|
- HyperX Cloud Flight S
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ SUBSYSTEMS=="usb", ATTRS{idProduct}=="0696", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1718", ATTRS{idVendor}=="0951", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="1718", ATTRS{idVendor}=="0951", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0d93", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0d93", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="05b7", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="05b7", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="06be", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="16ea", ATTRS{idVendor}=="0951", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="16ea", ATTRS{idVendor}=="0951", MODE="0666"
|
||||||
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0c9d", ATTRS{idVendor}=="03f0", MODE="0666"
|
SUBSYSTEMS=="usb", ATTRS{idProduct}=="0c9d", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
|
||||||
@@ -71,6 +73,7 @@ KERNEL=="hidraw*", ATTRS{idProduct}=="018b", ATTRS{idVendor}=="03f0", MODE="0666
|
|||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="0696", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0696", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="1718", ATTRS{idVendor}=="0951", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="1718", ATTRS{idVendor}=="0951", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="05b7", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="05b7", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
|
KERNEL=="hidraw*", ATTRS{idProduct}=="06be", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="16ea", ATTRS{idVendor}=="0951", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="16ea", ATTRS{idVendor}=="0951", MODE="0666"
|
||||||
KERNEL=="hidraw*", ATTRS{idProduct}=="0c9d", ATTRS{idVendor}=="03f0", MODE="0666"
|
KERNEL=="hidraw*", ATTRS{idProduct}=="0c9d", ATTRS{idVendor}=="03f0", MODE="0666"
|
||||||
```
|
```
|
||||||
|
|||||||
249
src/devices/cloud_iii_s_wireless.rs
Normal file
249
src/devices/cloud_iii_s_wireless.rs
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
use crate::{
|
||||||
|
debug_println,
|
||||||
|
devices::{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] = [0x06BE];
|
||||||
|
|
||||||
|
// Cloud III S uses a different protocol than Cloud III
|
||||||
|
// Header 0x05 for mic control, 20-byte packets
|
||||||
|
const PACKET_SIZE: usize = 20;
|
||||||
|
const MIC_HEADER: u8 = 0x05;
|
||||||
|
|
||||||
|
// Mic control commands (byte 1 after header)
|
||||||
|
// Pattern: (cmd & 0x02) == 0 means ON
|
||||||
|
const MIC_ON_CMD: u8 = 0x00;
|
||||||
|
const MIC_OFF_CMD: u8 = 0x02;
|
||||||
|
|
||||||
|
// Auto-shutdown control (via SET_REPORT, report ID 0x0c)
|
||||||
|
// Packet structure: 0c 02 03 00 00 4a XX 00... (64 bytes total)
|
||||||
|
// XX values: 00=disabled, 02=10min, 04=20min, 07=30min
|
||||||
|
const AUTO_SHUTDOWN_REPORT_ID: u8 = 0x0c;
|
||||||
|
const AUTO_SHUTDOWN_CMD: [u8; 5] = [0x02, 0x03, 0x00, 0x00, 0x4a];
|
||||||
|
const AUTO_SHUTDOWN_PACKET_SIZE: usize = 64;
|
||||||
|
|
||||||
|
// Equalizer control (via SET_REPORT, report ID 0x0c)
|
||||||
|
// Packet structure: 0c 02 03 00 00 5f [band] [value_hi] [value_lo] 00... (64 bytes total)
|
||||||
|
// band: 0-9 (32Hz, 64Hz, 125Hz, 250Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz)
|
||||||
|
// value: signed 16-bit big-endian, dB * 100 (e.g., +6.0dB = 600, -3.5dB = -350)
|
||||||
|
const EQ_REPORT_ID: u8 = 0x0c;
|
||||||
|
const EQ_CMD: [u8; 5] = [0x02, 0x03, 0x00, 0x00, 0x5f];
|
||||||
|
const EQ_PACKET_SIZE: usize = 64;
|
||||||
|
|
||||||
|
// Button report header (incoming from headset)
|
||||||
|
const CONSUMER_CONTROL_HEADER: u8 = 0x0f;
|
||||||
|
// Consumer control button values
|
||||||
|
const _VOL_UP: u8 = 0x01;
|
||||||
|
const _VOL_DOWN: u8 = 0x02;
|
||||||
|
const _PLAY_PAUSE: u8 = 0x08;
|
||||||
|
|
||||||
|
fn make_mic_packet(mute: bool) -> Vec<u8> {
|
||||||
|
let mut packet = vec![0u8; PACKET_SIZE];
|
||||||
|
packet[0] = MIC_HEADER;
|
||||||
|
packet[1] = if mute { MIC_OFF_CMD } else { MIC_ON_CMD };
|
||||||
|
packet
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_auto_shutdown_packet(minutes: u64) -> Vec<u8> {
|
||||||
|
let mut packet = vec![0u8; AUTO_SHUTDOWN_PACKET_SIZE];
|
||||||
|
packet[0] = AUTO_SHUTDOWN_REPORT_ID;
|
||||||
|
packet[1..6].copy_from_slice(&AUTO_SHUTDOWN_CMD);
|
||||||
|
// Value is 16-bit big-endian seconds
|
||||||
|
let seconds = (minutes * 60) as u16;
|
||||||
|
packet[6] = (seconds >> 8) as u8; // High byte
|
||||||
|
packet[7] = (seconds & 0xFF) as u8; // Low byte
|
||||||
|
packet
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_equalizer_band_packet(band_index: u8, db_value: f32) -> Vec<u8> {
|
||||||
|
let mut packet = vec![0u8; EQ_PACKET_SIZE];
|
||||||
|
packet[0] = EQ_REPORT_ID;
|
||||||
|
packet[1..6].copy_from_slice(&EQ_CMD);
|
||||||
|
packet[6] = band_index;
|
||||||
|
// Convert dB to device units (dB * 100), clamp to ±12dB range
|
||||||
|
let value_int = (db_value * 100.0).clamp(-1200.0, 1200.0) as i16;
|
||||||
|
let value_bytes = value_int.to_be_bytes();
|
||||||
|
packet[7] = value_bytes[0]; // High byte
|
||||||
|
packet[8] = value_bytes[1]; // Low byte
|
||||||
|
packet
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CloudIIISWireless {
|
||||||
|
state: DeviceState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CloudIIISWireless {
|
||||||
|
pub fn new_from_state(state: DeviceState) -> Self {
|
||||||
|
CloudIIISWireless { state }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> Result<Self, DeviceError> {
|
||||||
|
let state = DeviceState::new(&PRODUCT_IDS, &VENDOR_IDS)?;
|
||||||
|
Ok(CloudIIISWireless { state })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Device for CloudIIISWireless {
|
||||||
|
// Cloud III S: Battery query not discovered yet
|
||||||
|
fn get_charging_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cloud III S: Battery query not discovered yet
|
||||||
|
fn get_battery_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cloud III S: Auto shutdown via SET_REPORT (report ID 0x0c)
|
||||||
|
fn set_automatic_shut_down_packet(&self, shutdown_after: Duration) -> Option<Vec<u8>> {
|
||||||
|
let minutes = shutdown_after.as_secs() / 60;
|
||||||
|
Some(make_auto_shutdown_packet(minutes))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_automatic_shut_down_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cloud III S: Cannot query mic state (no response received)
|
||||||
|
// Physical mic button doesn't emit state packets over HID
|
||||||
|
fn get_mute_packet(&self) -> Option<Vec<u8>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cloud III S: Mic control - CONFIRMED WORKING
|
||||||
|
fn set_mute_packet(&self, mute: bool) -> Option<Vec<u8>> {
|
||||||
|
Some(make_mic_packet(mute))
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cloud III S: Sidetone not discovered yet
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cloud III S: Equalizer control - CONFIRMED WORKING
|
||||||
|
fn set_equalizer_band_packet(&self, band_index: u8, db_value: f32) -> Option<Vec<u8>> {
|
||||||
|
if band_index > 9 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(make_equalizer_band_packet(band_index, db_value))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_event_from_device_response(&self, response: &[u8]) -> Option<Vec<DeviceEvent>> {
|
||||||
|
debug_println!("Read packet: {response:?}");
|
||||||
|
|
||||||
|
match response[0] {
|
||||||
|
MIC_HEADER => {
|
||||||
|
// Mic state response
|
||||||
|
// Pattern: (byte[1] & 0x02) == 0 means mic is ON (not muted)
|
||||||
|
let muted = (response[1] & 0x02) != 0;
|
||||||
|
Some(vec![DeviceEvent::Muted(muted)])
|
||||||
|
}
|
||||||
|
CONSUMER_CONTROL_HEADER => {
|
||||||
|
// Button press events - we log but don't need to store state
|
||||||
|
debug_println!(
|
||||||
|
"Consumer control event: 0x{:02x}",
|
||||||
|
response.get(1).unwrap_or(&0)
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
debug_println!("Unknown device event: {:?}", response);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allow_passive_refresh(&mut self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_device_state(&self) -> &DeviceState {
|
||||||
|
&self.state
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_device_state_mut(&mut self) -> &mut DeviceState {
|
||||||
|
&mut self.state
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cloud III S has limited status reporting over HID.
|
||||||
|
/// We can SET mic mute but cannot query device state.
|
||||||
|
/// Override to prevent "No response" errors.
|
||||||
|
fn active_refresh_state(&mut self) -> Result<(), DeviceError> {
|
||||||
|
// Cloud III S doesn't respond to status queries.
|
||||||
|
// Just mark as connected since we successfully opened the device.
|
||||||
|
self.state.connected = Some(true);
|
||||||
|
|
||||||
|
// Listen briefly for any incoming events (button presses, etc.)
|
||||||
|
let events = self.wait_for_updates(Duration::from_millis(100));
|
||||||
|
if let Some(events) = events {
|
||||||
|
for event in events {
|
||||||
|
self.state.update_self_with_event(&event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
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_wireless;
|
pub mod cloud_iii_wireless;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
debug_println,
|
debug_println,
|
||||||
devices::{
|
devices::{
|
||||||
cloud_ii_wireless::CloudIIWireless, cloud_ii_wireless_dts::CloudIIWirelessDTS,
|
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};
|
||||||
@@ -16,7 +17,7 @@ use thistermination::TerminationFull;
|
|||||||
// Possible vendor IDs [HyperX, HP]
|
// Possible vendor IDs [HyperX, HP]
|
||||||
const VENDOR_IDS: [u16; 2] = [0x0951, 0x03F0];
|
const VENDOR_IDS: [u16; 2] = [0x0951, 0x03F0];
|
||||||
// All supported product IDs
|
// All supported product IDs
|
||||||
const PRODUCT_IDS: [u16; 8] = [0x1718, 0x018B, 0x0D93, 0x0696, 0x0b92, 0x05B7, 0x16EA, 0x0c9d];
|
const PRODUCT_IDS: [u16; 9] = [0x1718, 0x018B, 0x0D93, 0x0696, 0x0b92, 0x05B7, 0x16EA, 0x0c9d, 0x06BE];
|
||||||
|
|
||||||
const RESPONSE_BUFFER_SIZE: usize = 256;
|
const RESPONSE_BUFFER_SIZE: usize = 256;
|
||||||
const RESPONSE_DELAY: Duration = Duration::from_millis(50);
|
const RESPONSE_DELAY: Duration = Duration::from_millis(50);
|
||||||
@@ -41,6 +42,12 @@ pub fn connect_compatible_device() -> Result<Box<dyn Device>, DeviceError> {
|
|||||||
{
|
{
|
||||||
Box::new(CloudIIWirelessDTS::new_from_state(state))
|
Box::new(CloudIIWirelessDTS::new_from_state(state))
|
||||||
}
|
}
|
||||||
|
(v, p)
|
||||||
|
if cloud_iii_s_wireless::VENDOR_IDS.contains(&v)
|
||||||
|
&& cloud_iii_s_wireless::PRODUCT_IDS.contains(&p) =>
|
||||||
|
{
|
||||||
|
Box::new(CloudIIISWireless::new_from_state(state))
|
||||||
|
}
|
||||||
(v, p)
|
(v, p)
|
||||||
if cloud_iii_wireless::VENDOR_IDS.contains(&v)
|
if cloud_iii_wireless::VENDOR_IDS.contains(&v)
|
||||||
&& cloud_iii_wireless::PRODUCT_IDS.contains(&p) =>
|
&& cloud_iii_wireless::PRODUCT_IDS.contains(&p) =>
|
||||||
@@ -83,6 +90,7 @@ pub struct DeviceState {
|
|||||||
pub can_set_side_tone_volume: bool,
|
pub can_set_side_tone_volume: bool,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for DeviceState {
|
impl Display for DeviceState {
|
||||||
@@ -138,6 +146,7 @@ impl DeviceState {
|
|||||||
can_set_side_tone_volume: false,
|
can_set_side_tone_volume: false,
|
||||||
can_set_voice_prompt: false,
|
can_set_voice_prompt: false,
|
||||||
can_set_silent_mode: false,
|
can_set_silent_mode: false,
|
||||||
|
can_set_equalizer: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,6 +423,11 @@ pub trait Device {
|
|||||||
fn reset_sirk_packet(&self) -> Option<Vec<u8>>;
|
fn reset_sirk_packet(&self) -> Option<Vec<u8>>;
|
||||||
fn get_silent_mode_packet(&self) -> Option<Vec<u8>>;
|
fn get_silent_mode_packet(&self) -> Option<Vec<u8>>;
|
||||||
fn set_silent_mode_packet(&self, silence: bool) -> Option<Vec<u8>>;
|
fn set_silent_mode_packet(&self, silence: bool) -> Option<Vec<u8>>;
|
||||||
|
/// Set equalizer band (0-9) to dB value (-12.0 to +12.0)
|
||||||
|
/// Bands: 0=32Hz, 1=64Hz, 2=125Hz, 3=250Hz, 4=500Hz, 5=1kHz, 6=2kHz, 7=4kHz, 8=8kHz, 9=16kHz
|
||||||
|
fn set_equalizer_band_packet(&self, _band_index: u8, _db_value: f32) -> 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;
|
||||||
@@ -444,6 +458,9 @@ pub trait Device {
|
|||||||
fn can_set_silent_mode(&self) -> bool {
|
fn can_set_silent_mode(&self) -> bool {
|
||||||
self.set_silent_mode_packet(false).is_some()
|
self.set_silent_mode_packet(false).is_some()
|
||||||
}
|
}
|
||||||
|
fn can_set_equalizer(&self) -> bool {
|
||||||
|
self.set_equalizer_band_packet(0, 0.0).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize capability flags in device state
|
// Initialize capability flags in device state
|
||||||
fn init_capabilities(&mut self) {
|
fn init_capabilities(&mut self) {
|
||||||
@@ -455,6 +472,7 @@ pub trait Device {
|
|||||||
let can_set_side_tone_volume = self.can_set_side_tone_volume();
|
let can_set_side_tone_volume = self.can_set_side_tone_volume();
|
||||||
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();
|
||||||
|
|
||||||
// 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();
|
||||||
@@ -465,6 +483,7 @@ pub trait Device {
|
|||||||
state.can_set_side_tone_volume = can_set_side_tone_volume;
|
state.can_set_side_tone_volume = can_set_side_tone_volume;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_headset_specific_functionality(&mut self) -> Result<(), DeviceError> {
|
fn execute_headset_specific_functionality(&mut self) -> Result<(), DeviceError> {
|
||||||
|
|||||||
Reference in New Issue
Block a user