Add equalizer band control for Cloud III S Wireless
- Add can_set_equalizer capability flag to DeviceState - Add set_equalizer_band_packet trait method with default None implementation - Add can_set_equalizer() helper method to Device trait - Implement equalizer protocol: 10 bands (32Hz-16kHz), ±12dB range - Encode values as dB*100 in 16-bit big-endian signed format - Add Cloud III S Wireless implementation of set_equalizer_band_packet() - Validate band index (0-9) and clamp dB values to valid range Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,14 @@ 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
|
||||
@@ -50,6 +58,19 @@ fn make_auto_shutdown_packet(minutes: u64) -> Vec<u8> {
|
||||
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,
|
||||
}
|
||||
@@ -162,6 +183,14 @@ impl Device for CloudIIISWireless {
|
||||
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:?}");
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ pub struct DeviceState {
|
||||
pub can_set_side_tone_volume: bool,
|
||||
pub can_set_voice_prompt: bool,
|
||||
pub can_set_silent_mode: bool,
|
||||
pub can_set_equalizer: bool,
|
||||
}
|
||||
|
||||
impl Display for DeviceState {
|
||||
@@ -145,6 +146,7 @@ impl DeviceState {
|
||||
can_set_side_tone_volume: false,
|
||||
can_set_voice_prompt: false,
|
||||
can_set_silent_mode: false,
|
||||
can_set_equalizer: false,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -421,6 +423,11 @@ pub trait Device {
|
||||
fn reset_sirk_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>>;
|
||||
/// 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_device_state(&self) -> &DeviceState;
|
||||
fn get_device_state_mut(&mut self) -> &mut DeviceState;
|
||||
@@ -451,6 +458,9 @@ pub trait Device {
|
||||
fn can_set_silent_mode(&self) -> bool {
|
||||
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
|
||||
fn init_capabilities(&mut self) {
|
||||
@@ -462,6 +472,7 @@ pub trait Device {
|
||||
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_silent_mode = self.can_set_silent_mode();
|
||||
let can_set_equalizer = self.can_set_equalizer();
|
||||
|
||||
// Now set them in device state
|
||||
let state = self.get_device_state_mut();
|
||||
@@ -472,6 +483,7 @@ pub trait Device {
|
||||
state.can_set_side_tone_volume = can_set_side_tone_volume;
|
||||
state.can_set_voice_prompt = can_set_voice_prompt;
|
||||
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> {
|
||||
|
||||
Reference in New Issue
Block a user