diff --git a/40-streamdeck.rules b/40-streamdeck.rules index 4089591..e7a1955 100644 --- a/40-streamdeck.rules +++ b/40-streamdeck.rules @@ -11,6 +11,7 @@ SUBSYSTEM=="usb", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="009a", MODE="0660", SUBSYSTEM=="usb", ATTR{idVendor}=="5548", ATTR{idProduct}=="6670", MODE="0660", GROUP="plugdev" SUBSYSTEM=="usb", ATTR{idVendor}=="5548", ATTR{idProduct}=="6672", MODE="0660", GROUP="plugdev" SUBSYSTEM=="usb", ATTR{idVendor}=="5548", ATTR{idProduct}=="6674", MODE="0660", GROUP="plugdev" +SUBSYSTEM=="usb", ATTR{idVendor}=="0300", ATTR{idProduct}=="1003", MODE="0660", GROUP="plugdev" SUBSYSTEM=="usb", ATTR{idVendor}=="0300", ATTR{idProduct}=="1010", MODE="0660", GROUP="plugdev" SUBSYSTEM=="usb", ATTR{idVendor}=="0300", ATTR{idProduct}=="1020", MODE="0660", GROUP="plugdev" @@ -27,6 +28,7 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="009a", MODE="0660" SUBSYSTEM=="usb", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6670", MODE="0660", GROUP="plugdev" SUBSYSTEM=="usb", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6672", MODE="0660", GROUP="plugdev" SUBSYSTEM=="usb", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6674", MODE="0660", GROUP="plugdev" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1003", MODE="0660", GROUP="plugdev" SUBSYSTEM=="usb", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1010", MODE="0660", GROUP="plugdev" SUBSYSTEM=="usb", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1020", MODE="0660", GROUP="plugdev" @@ -43,6 +45,7 @@ KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0fd9", ATTR{idProduct}= KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="5548", ATTR{idProduct}=="6670", MODE="0660", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="5548", ATTR{idProduct}=="6672", MODE="0660", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="5548", ATTR{idProduct}=="6674", MODE="0660", GROUP="plugdev" +KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0300", ATTR{idProduct}=="1003", MODE="0660", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0300", ATTR{idProduct}=="1010", MODE="0660", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0300", ATTR{idProduct}=="1020", MODE="0660", GROUP="plugdev" @@ -59,5 +62,6 @@ KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6670", MODE="0660", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6672", MODE="0660", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6674", MODE="0660", GROUP="plugdev" +KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1003", MODE="0660", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1010", MODE="0660", GROUP="plugdev" KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1020", MODE="0660", GROUP="plugdev" diff --git a/README.md b/README.md index 77ecb7e..7d6195e 100644 --- a/README.md +++ b/README.md @@ -78,4 +78,5 @@ As it stands, this library should support the following devices: - Ajazz AKP153E (thanks to [@teras](https://github.com/teras)) - Ajazz AKP153R (thanks to [@teras](https://github.com/teras), [@damnkrat](https://github.com/damnkrat) and [@4ndv](https://github.com/4ndv)) - Ajazz AKP815 (thanks to [@teras](https://github.com/teras)) +- Ajazz AKP03R (thanks to [@4ndv](https://github.com/4ndv)) - MiraBox HSV293S (thanks to [@czyz](https://github.com/czyz)) diff --git a/src/asynchronous.rs b/src/asynchronous.rs index 36d5795..a7b6b86 100644 --- a/src/asynchronous.rs +++ b/src/asynchronous.rs @@ -222,7 +222,7 @@ impl AsyncDeviceStateReader { StreamDeckInput::ButtonStateChange(buttons) => { for (index, (their, mine)) in zip(buttons.iter(), my_states.buttons.iter()).enumerate() { match self.device.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { if *their { updates.push(DeviceStateUpdate::ButtonDown(index as u8)); updates.push(DeviceStateUpdate::ButtonUp(index as u8)); @@ -253,11 +253,21 @@ impl AsyncDeviceStateReader { StreamDeckInput::EncoderStateChange(encoders) => { for (index, (their, mine)) in zip(encoders.iter(), my_states.encoders.iter()).enumerate() { - if *their != *mine { - if *their { - updates.push(DeviceStateUpdate::EncoderDown(index as u8)); - } else { - updates.push(DeviceStateUpdate::EncoderUp(index as u8)); + match self.device.kind { + Kind::Akp03R => { + if *their { + updates.push(DeviceStateUpdate::EncoderDown(index as u8)); + updates.push(DeviceStateUpdate::EncoderUp(index as u8)); + } + } + _ => { + if *their != *mine { + if *their { + updates.push(DeviceStateUpdate::EncoderDown(index as u8)); + } else { + updates.push(DeviceStateUpdate::EncoderUp(index as u8)); + } + } } } } diff --git a/src/info.rs b/src/info.rs index 43cba80..917c9be 100644 --- a/src/info.rs +++ b/src/info.rs @@ -43,6 +43,9 @@ pub const PID_AJAZZ_AKP153E: u16 = 0x1010; /// Product ID of Ajazz AKP153R Desk Controller pub const PID_AJAZZ_AKP153R: u16 = 0x1020; +/// Product ID of Ajazz AKP03R Desk Controller +pub const PID_AJAZZ_AKP03R: u16 = 0x1003; + const RECOGNIZED_VENDORS: [u16; 3] = [ELGATO_VENDOR_ID, AJAZZ_VENDOR_ID_1, AJAZZ_VENDOR_ID_2]; /// Returns true for vendors IDs that are recognized by the library @@ -81,6 +84,8 @@ pub enum Kind { Akp153R, /// Ajazz AKP815 Desk Controller Akp815, + /// Ajazz AKP03R Desk Controller + Akp03R, /// MiraBox HSV293S MiraBoxHSV293S, } @@ -108,6 +113,7 @@ impl Kind { PID_AJAZZ_AKP153E => Some(Kind::Akp153E), PID_AJAZZ_AKP153R => Some(Kind::Akp153R), PID_AJAZZ_AKP815 => Some(Kind::Akp815), + PID_AJAZZ_AKP03R => Some(Kind::Akp03R), PID_MIRABOX_HSV293S => Some(Kind::MiraBoxHSV293S), _ => None, }, @@ -133,6 +139,7 @@ impl Kind { Kind::Akp815 => PID_AJAZZ_AKP815, Kind::Akp153E => PID_AJAZZ_AKP153E, Kind::Akp153R => PID_AJAZZ_AKP153R, + Kind::Akp03R => PID_AJAZZ_AKP03R, Kind::MiraBoxHSV293S => PID_MIRABOX_HSV293S, } } @@ -154,6 +161,7 @@ impl Kind { Kind::Akp815 => AJAZZ_VENDOR_ID_1, Kind::Akp153E => AJAZZ_VENDOR_ID_2, Kind::Akp153R => AJAZZ_VENDOR_ID_2, + Kind::Akp03R => AJAZZ_VENDOR_ID_2, Kind::MiraBoxHSV293S => AJAZZ_VENDOR_ID_1, } } @@ -168,6 +176,7 @@ impl Kind { Kind::Neo | Kind::Plus => 8, Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => 15 + 3, Kind::Akp815 => 15, + Kind::Akp03R => 6 + 3, } } @@ -181,6 +190,7 @@ impl Kind { Kind::Neo | Kind::Plus => 2, Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => 3, Kind::Akp815 => 5, + Kind::Akp03R => 3, } } @@ -194,6 +204,7 @@ impl Kind { Kind::Neo | Kind::Plus => 4, Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => 6, Kind::Akp815 => 3, + Kind::Akp03R => 3, } } @@ -201,6 +212,7 @@ impl Kind { pub fn encoder_count(&self) -> u8 { match self { Kind::Plus => 4, + Kind::Akp03R => 3, _ => 0, } } @@ -287,6 +299,13 @@ impl Kind { rotation: ImageRotation::Rot180, mirror: ImageMirroring::None, }, + + Kind::Akp03R => ImageFormat { + mode: ImageMode::JPEG, + size: (64, 64), + rotation: ImageRotation::Rot0, + mirror: ImageMirroring::None, + }, } } diff --git a/src/lib.rs b/src/lib.rs index 2b1a9e0..8c5f1b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,8 +23,8 @@ use image::{DynamicImage, ImageError}; use crate::info::{is_vendor_familiar, Kind}; use crate::util::{ - ajazz153_to_elgato_input, elgato_to_ajazz153, extract_str, flip_key_index, get_feature_report, inverse_key_index, read_button_states, read_data, read_encoder_input, read_lcd_input, - send_feature_report, write_data, + ajazz03_read_input, ajazz_extend_packet, ajazz153_to_elgato_input, elgato_to_ajazz153, extract_str, flip_key_index, get_feature_report, inverse_key_index, read_button_states, read_data, + read_encoder_input, read_lcd_input, send_feature_report, write_data, }; /// Various information about Stream Deck devices @@ -160,7 +160,7 @@ impl StreamDeck { /// Returns serial number of the device pub fn serial_number(&self) -> Result { match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let serial = self.device.get_serial_number_string()?; match serial { Some(serial) => { @@ -200,7 +200,7 @@ impl StreamDeck { Ok(extract_str(&bytes[5..])?) } - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let bytes = get_feature_report(&self.device, 0x01, 20)?; Ok(extract_str(&bytes[0..])?) } @@ -219,13 +219,13 @@ impl StreamDeck { } self.initialized.store(true, Ordering::Release); match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x44, 0x49, 0x53]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x4c, 0x49, 0x47, 0x00, 0x00, 0x00, 0x00]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; } @@ -279,6 +279,16 @@ impl StreamDeck { Ok(StreamDeckInput::ButtonStateChange(read_button_states(&self.kind, &states))) } + Kind::Akp03R => { + let data = read_data(&self.device, 512, timeout)?; + + if data[0] == 0 { + return Ok(StreamDeckInput::NoData); + } + + ajazz03_read_input(&self.kind, data[9]) + } + _ => { let data = match self.kind { Kind::Original | Kind::Mini | Kind::MiniMk2 => read_data(&self.device, 1 + self.kind.key_count() as usize, timeout), @@ -306,7 +316,7 @@ impl StreamDeck { Ok(send_feature_report(&self.device, buf.as_slice())?) } - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { self.set_brightness(100)?; self.clear_button_image(0xff)?; Ok(()) @@ -336,10 +346,10 @@ impl StreamDeck { Ok(send_feature_report(&self.device, buf.as_slice())?) } - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x4c, 0x49, 0x47, 0x00, 0x00, percent]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; @@ -361,6 +371,11 @@ impl StreamDeck { return Err(StreamDeckError::InvalidKeyIndex); } + // Key count is 9 for Akp03R, but only the first 6 have screens, so don't output anything after 6 + if self.kind == Kind::Akp03R && key > 6 { + return Ok(()); + } + let key = if let Kind::Original = self.kind { flip_key_index(&self.kind, key) } else if let Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S = self.kind { @@ -376,7 +391,7 @@ impl StreamDeck { } match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let mut buf = vec![ 0x00, 0x43, @@ -394,7 +409,7 @@ impl StreamDeck { key + 1, ]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; } @@ -410,7 +425,7 @@ impl StreamDeck { Kind::Mini | Kind::MiniMk2 => vec![0x02, 0x01, page_number as u8, 0, if last_package { 1 } else { 0 }, key + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => vec![0x00], + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => vec![0x00], _ => vec![ 0x02, @@ -550,16 +565,18 @@ impl StreamDeck { pub fn clear_button_image(&self, key: u8) -> Result<(), StreamDeckError> { self.initialize()?; match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let key = if self.kind == Kind::Akp815 { inverse_key_index(&self.kind, key) + } else if self.kind == Kind::Akp03R { + key } else { elgato_to_ajazz153(&self.kind, key) }; let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4c, 0x45, 0x00, 0x00, 0x00, if key == 0xff { 0xff } else { key + 1 }]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; @@ -575,7 +592,7 @@ impl StreamDeck { pub fn clear_all_button_images(&self) -> Result<(), StreamDeckError> { self.initialize()?; match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => self.clear_button_image(0xff), + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => self.clear_button_image(0xff), _ => { for i in 0..self.kind.key_count() { self.clear_button_image(i)? @@ -598,7 +615,7 @@ impl StreamDeck { pub fn set_logo_image(&self, image: DynamicImage) -> Result<(), StreamDeckError> { self.initialize()?; match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => (), + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => (), _ => return Err(StreamDeckError::UnsupportedOperation), } @@ -608,7 +625,7 @@ impl StreamDeck { // 854 * 480 * 3 let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x4c, 0x4f, 0x47, 0x00, 0x12, 0xc3, 0xc0, 0x01]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; @@ -674,12 +691,13 @@ impl StreamDeck { let image_report_length = match self.kind { Kind::Original => 8191, Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => 513, + Kind::Akp03R => 1025, _ => 1024, }; let image_report_header_length = match self.kind { Kind::Original | Kind::Mini | Kind::MiniMk2 => 16, - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => 1, + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => 1, _ => 8, }; @@ -733,10 +751,10 @@ impl StreamDeck { pub fn sleep(&self) -> Result<(), StreamDeckError> { self.initialize()?; match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x48, 0x41, 0x4e]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; @@ -751,9 +769,9 @@ impl StreamDeck { pub fn keep_alive(&self) -> Result<(), StreamDeckError> { self.initialize()?; match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; Ok(()) } @@ -766,13 +784,13 @@ impl StreamDeck { pub fn shutdown(&self) -> Result<(), StreamDeckError> { self.initialize()?; match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R => { let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4c, 0x45, 0x00, 0x00, 0x44, 0x43]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x48, 0x41, 0x4E]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; Ok(()) @@ -795,10 +813,10 @@ impl StreamDeck { } match self.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x53, 0x54, 0x50]; - buf.extend(vec![0u8; 513 - buf.len()]); + ajazz_extend_packet(&self.kind, &mut buf); write_data(&self.device, buf.as_slice())?; } @@ -866,12 +884,13 @@ impl WriteImageParameters { let image_report_length = match kind { Kind::Original => 8191, Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => 513, + Kind::Akp03R => 1025, _ => 1024, }; let image_report_header_length = match kind { Kind::Original | Kind::Mini | Kind::MiniMk2 => 16, - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => 1, + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => 1, _ => 8, }; @@ -1024,7 +1043,7 @@ impl DeviceStateReader { StreamDeckInput::ButtonStateChange(buttons) => { for (index, (their, mine)) in zip(buttons.iter(), my_states.buttons.iter()).enumerate() { match self.device.kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { if *their { updates.push(DeviceStateUpdate::ButtonDown(index as u8)); updates.push(DeviceStateUpdate::ButtonUp(index as u8)); @@ -1054,11 +1073,21 @@ impl DeviceStateReader { StreamDeckInput::EncoderStateChange(encoders) => { for (index, (their, mine)) in zip(encoders.iter(), my_states.encoders.iter()).enumerate() { - if *their != *mine { - if *their { - updates.push(DeviceStateUpdate::EncoderDown(index as u8)); - } else { - updates.push(DeviceStateUpdate::EncoderUp(index as u8)); + match self.device.kind { + Kind::Akp03R => { + if *their { + updates.push(DeviceStateUpdate::EncoderDown(index as u8)); + updates.push(DeviceStateUpdate::EncoderUp(index as u8)); + } + } + _ => { + if *their != *mine { + if *their { + updates.push(DeviceStateUpdate::EncoderDown(index as u8)); + } else { + updates.push(DeviceStateUpdate::EncoderUp(index as u8)); + } + } } } } diff --git a/src/util.rs b/src/util.rs index 71729b4..cb08463 100644 --- a/src/util.rs +++ b/src/util.rs @@ -112,6 +112,16 @@ pub fn flip_key_index(kind: &Kind, key: u8) -> u8 { (key - col) + ((kind.column_count() - 1) - col) } +/// Extends buffer up to required packet length +pub fn ajazz_extend_packet(kind: &Kind, buf: &mut Vec) { + let length = match kind { + Kind::Akp03R => 1025, + _ => 513, + }; + + buf.extend(vec![0u8; length - buf.len()]); +} + /// Reads button states, empty vector if no data pub fn read_button_states(kind: &Kind, states: &[u8]) -> Vec { if states[0] == 0 { @@ -119,7 +129,7 @@ pub fn read_button_states(kind: &Kind, states: &[u8]) -> Vec { } match kind { - Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S => { + Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::Akp03R | Kind::MiraBoxHSV293S => { let mut bools = vec![]; for i in 0..kind.key_count() { @@ -179,3 +189,70 @@ pub fn read_encoder_input(kind: &Kind, data: &[u8]) -> Result Err(StreamDeckError::BadData), } } + +/// Read inputs from Ajazz AKP03 +pub fn ajazz03_read_input(kind: &Kind, input: u8) -> Result { + match input { + (0..=6) | 0x25 | 0x30 | 0x31 => ajazz03_read_button_press(kind, input), + 0x90 | 0x91 | 0x50 | 0x51 | 0x60 | 0x61 => ajazz03_read_encoder_value(kind, input), + 0x33 | 0x34 | 0x35 => ajazz03_read_encoder_press(kind, input), + _ => Err(StreamDeckError::BadData), + } +} + +fn ajazz03_read_button_press(kind: &Kind, input: u8) -> Result { + let mut button_states = vec![0x01]; + button_states.extend(vec![0u8; (kind.key_count() + 1) as usize]); + + if input == 0 { + return Ok(StreamDeckInput::ButtonStateChange(read_button_states(kind, &button_states))); + } + + let pressed_index: usize = match input { + // Six buttons with displays + (1..=6) => input as usize, + // Three buttons without displays + 0x25 => 7, + 0x30 => 8, + 0x31 => 9, + _ => return Err(StreamDeckError::BadData), + }; + + button_states[pressed_index] = 0x1u8; + + Ok(StreamDeckInput::ButtonStateChange(read_button_states(kind, &button_states))) +} + +fn ajazz03_read_encoder_value(kind: &Kind, input: u8) -> Result { + let mut encoder_values = vec![0i8; kind.encoder_count() as usize]; + + let (encoder, value): (usize, i8) = match input { + // Left encoder + 0x90 => (0, -1), + 0x91 => (0, 1), + // Middle (top) encoder + 0x50 => (1, -1), + 0x51 => (1, 1), + // Right encoder + 0x60 => (2, -1), + 0x61 => (2, 1), + _ => return Err(StreamDeckError::BadData), + }; + + encoder_values[encoder] = value; + Ok(StreamDeckInput::EncoderTwist(encoder_values)) +} + +fn ajazz03_read_encoder_press(kind: &Kind, input: u8) -> Result { + let mut encoder_states = vec![false; kind.encoder_count() as usize]; + + let encoder: usize = match input { + 0x33 => 0, // Left encoder + 0x35 => 1, // Middle (top) encoder + 0x34 => 2, // Right encoder + _ => return Err(StreamDeckError::BadData), + }; + + encoder_states[encoder] = true; + Ok(StreamDeckInput::EncoderStateChange(encoder_states)) +}