use std::fmt::Debug;
use crate::{
channel::{ChannelError, HidppChannel},
nibble::{self, U4},
};
pub mod v10;
pub mod v20;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum ProtocolVersion {
V10,
V20 {
protocol_num: u8,
target_sw: u8,
},
}
pub async fn determine_version(
chan: &HidppChannel,
device_index: u8,
) -> Result<Option<ProtocolVersion>, ChannelError> {
let sw_id = chan.get_sw_id();
let msg = v20::Message::Short(
v20::MessageHeader {
device_index,
feature_index: 0x00,
function_id: U4::from_lo(0x1),
software_id: sw_id,
},
[0x00, 0x00, 0x00],
);
let response = chan
.send(msg.into(), move |resp| {
if v20::Message::from(*resp).header() == msg.header() {
return true;
}
if let v10::Message::Short(header, payload) = v10::Message::from(*resp) {
if header.device_index == device_index
&& header.sub_id == v10::MessageType::Error.into()
&& payload[0] == 0x00
&& payload[1] == nibble::combine(msg.header().function_id, sw_id)
{
return true;
}
}
false
})
.await?;
let v20_msg = v20::Message::from(response);
if v20_msg.header() == msg.header() {
let payload = v20_msg.extend_payload();
return Ok(Some(ProtocolVersion::V20 {
protocol_num: payload[0],
target_sw: payload[1],
}));
}
let v10::Message::Short(_, payload) = v10::Message::from(response) else {
return Ok(None);
};
if payload[2] == v10::ErrorType::InvalidSubId.into() {
Ok(Some(ProtocolVersion::V10))
} else {
Ok(None)
}
}