use crate::{prelude::internal::*, structures::desc::DisplayDescriptor};
use descriptors::{range_limits, *};
mod descriptors;
mod preferred_tm;
#[tracing::instrument(skip_all)]
pub(crate) fn parse(input: &[u8]) -> Result<EighteenByteDescriptors, EdidError> {
let first = &input[0x36..=0x47];
let second = &input[0x48..=0x59];
let third = &input[0x5A..=0x6B];
let fourth = &input[0x6C..=0x7D];
let preferred_timing_mode = preferred_tm::parse(first.try_into()?)?;
let blocks = [
one(second.try_into()?, input)?,
one(third.try_into()?, input)?,
one(fourth.try_into()?, input)?,
];
Ok(EighteenByteDescriptors {
preferred_timing_mode,
blocks,
})
}
#[tracing::instrument(skip_all)]
fn one(input: &[u8; 18], edid: &[u8]) -> Result<EighteenByteBlock, EdidError> {
if input[0] != 0x00 && input[1] != 0x00 {
return Ok(EighteenByteBlock::Timing(preferred_tm::parse(input)?));
}
{
let header = &input[0..5];
if !matches!(header, [0x00, 0x00, 0x00, _, 0x00]) {
tracing::error!("Given descriptor data had a malformed header: {header:x?}");
return Err(EdidError::DescriptorUnexpectedHeader(header.try_into()?));
}
}
let kind_byte = input[3];
let desc = match kind_byte {
0xFF => DisplayDescriptor::ProductSerial(_13_byte_string::parse(input)?),
0xFE => DisplayDescriptor::DataString(_13_byte_string::parse(input)?),
0xFC => DisplayDescriptor::ProductName(_13_byte_string::parse(input)?),
0xFD => DisplayDescriptor::DisplayRangeLimits(range_limits::parse(input, edid)?),
0xFB => descriptors::color_point::parse(input),
0xFA => descriptors::more_std_timings::parse(input)?,
0xF9 => descriptors::dcm::parse(input),
0xF8 => descriptors::cvt::parse(input)?, 0xF7 => descriptors::iii::parse(input)?,
0x10 => {
if input[5..=17].iter().map(|i| *i as u16).sum::<u16>() != 0 {
tracing::warn!("The EDID supplied a dummy 18-byte descriptor, but it contained data! (data: {input:?})");
}
DisplayDescriptor::DummyDescriptor
}
m if (0x00..=0x0F).contains(&m) => {
tracing::debug!("Got a manufacturer descriptor. (tag: `{m:x}`)");
DisplayDescriptor::Manufacturer { data: *input }
}
tag if (0x11..=0xF6).contains(&tag) => {
tracing::error!("EDID supplied an 18-byte descriptor that used a reserved tag. (tag: ");
return Err(EdidError::DescriptorUsedReservedKind { kind_byte });
}
ty => todo!("this descriptor type (`{ty:x}`) is unimplemented!"),
};
Ok(EighteenByteBlock::Display(desc))
}