1#![cfg_attr(feature = "no_std", no_std)]
2
3pub trait Read {
35 fn read(&mut self, buf: &mut [u8]) -> Option<usize>;
36}
37
38#[cfg(not(feature = "no_std"))]
39impl<T: std::io::Read> Read for T {
40 fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
41 self.read(buf).ok()
42 }
43}
44
45#[cfg(feature = "no_std")]
46#[macro_use]
47extern crate alloc;
48#[cfg(feature = "no_std")]
49use alloc::{vec::Vec, string::String};
50
51
52pub type Result<T> = core::result::Result<T, &'static str>;
54
55fn ensure(pred: bool, msg: &'static str) -> Result<()> {
57 if pred {
58 Ok(())
59 } else {
60 Err(msg)
61 }
62}
63
64pub struct Reader<'a> {
66 value: &'a mut dyn Read,
68 buffer: Vec<u8>
70}
71
72impl<'a> Reader<'a> {
73 pub fn new<T: Read>(value: &'a mut T) -> Reader<'a> {
74 Reader {
75 value: value as &mut dyn Read, buffer: Vec::with_capacity(128)
76 }
77 }
78
79 fn get(&mut self) -> Result<u8> {
81 if self.buffer.len() == 0 {
82 self.buffer.resize(128, 0);
83 let num = self.value.read(self.buffer.as_mut()).ok_or("Error reading data!")?;
84 self.buffer.truncate(num);
85 }
86
87 if self.buffer.len() > 0 {
88 Ok(self.buffer.remove(0))
89 } else{
90 Err("Unexpectedly out of data!")
91 }
92 }
93
94 fn read_u8(&mut self) -> Result<u8> {
95 self.get()
96 }
97
98 fn read_u16(&mut self) -> Result<u16> {
100 Ok((self.read_u8()? as u16) | ((self.read_u8()? as u16) << 8))
101 }
102
103 fn read_u32(&mut self) -> Result<u32> {
104 Ok((self.read_u16()? as u32) | ((self.read_u16()? as u32) << 16))
105 }
106}
107
108#[derive(Debug, Clone)]
110pub struct EDID {
111 pub product: ProductInformation,
113 pub version: Version,
115 pub display: DisplayParameters,
117 pub color: ColorCharacteristics,
119 pub timings: Timings,
121 pub descriptors: MonitorDescriptors,
123 pub extensions: u8,
125}
126
127impl EDID {
128 pub fn parse(r: &mut Reader) -> Result<EDID> {
129 ensure(r.read_u32()? == 0xffffff00, "Invalid header.")?;
130 ensure(r.read_u32()? == 0x00ffffff, "Invalid header.")?;
131
132 let product = ProductInformation::parse(r)?;
134 let version = Version::parse(r)?;
135 let display = DisplayParameters::parse(r)?;
136 let mut color = ColorCharacteristics::parse(r)?;
137 let mut timings = Timings::parse(r)?;
138 let (descriptors, mut detailed_timings, mut standard_timings, mut white) = MonitorDescriptors::parse(r)?;
139
140 color.white_points.append(&mut white);
143 timings.detailed_timings.append(&mut detailed_timings);
144 timings.standard_timings.append(&mut standard_timings);
145
146 let extensions = r.read_u8()?;
149
150 Ok(EDID {
151 product, version, display, color, timings, descriptors, extensions
152 })
153 }
154}
155
156#[derive(Debug, Clone)]
158pub struct ProductInformation {
159 pub manufacturer_id: ManufacturerID,
160 pub product_code: u16,
161 pub serial_number: u32,
162 pub manufacture_date: ManufactureDate
163}
164
165impl ProductInformation {
166 fn parse(r: &mut Reader) -> Result<ProductInformation> {
167 let manufacturer_id = ManufacturerID::parse(r)?;
168 let product_code = r.read_u16()?;
169 let serial_number = r.read_u32()?;
170 let manufacture_date = ManufactureDate::parse(r)?;
171
172 Ok(ProductInformation {
173 manufacturer_id, product_code, serial_number, manufacture_date
174 })
175 }
176}
177
178#[derive(Debug, Clone, Copy)]
180pub struct ManufacturerID(pub char, pub char, pub char);
181
182impl ManufacturerID {
183 fn parse(r: &mut Reader) -> Result<ManufacturerID> {
184 let k = r.read_u16()?;
187 let c1 = ((k & 0b0111110000000000) >> 10) as u8;
188 let c2 = ((k & 0b0000001111100000) >> 05) as u8;
189 let c3 = ((k & 0b0000000000011111) >> 00) as u8;
190 Ok(ManufacturerID(c1 as char, c2 as char, c3 as char))
191 }
192}
193
194#[derive(Debug, Clone, Copy)]
196pub struct ManufactureDate {
197 pub week: u8,
198 pub year: u16
199}
200
201impl ManufactureDate {
202 fn parse(r: &mut Reader) -> Result<ManufactureDate> {
203 let week = r.read_u8()?;
204 let year = r.read_u8()? as u16 + 1990;
205
206 Ok(ManufactureDate { week, year })
207 }
208}
209
210#[derive(Debug, Clone, Copy)]
212pub struct Version {
213 pub version: u8,
214 pub revision: u8
215}
216
217impl Version {
218 fn parse(r: &mut Reader) -> Result<Version> {
219 let version = r.read_u8()?;
220 let revision = r.read_u8()?;
221
222 Ok(Version { version, revision })
223 }
224}
225
226#[derive(Debug, Clone)]
228pub struct DisplayParameters {
229 pub input: VideoInput,
230 pub max_size: Option<ImageSize>,
232 pub gamma: Option<f32>,
234 pub dpms: DPMSFeatures
236}
237
238impl DisplayParameters {
239 fn parse(r: &mut Reader) -> Result<DisplayParameters> {
240 let input = VideoInput::parse(r)?;
241 let max_width = r.read_u8()?;
242 let max_height = r.read_u8()?;
243
244 let max_size = if max_width == 0 || max_height == 0 {
245 None
246 } else {
247 Some(ImageSize {
248 width: max_width as f32,
249 height: max_height as f32
250 })
251 };
252
253 let gamma_val = r.read_u8()?;
254 let gamma = if gamma_val == 0xff {
255 None
256 } else {
257 Some((gamma_val as f32 + 100.0) / 100.0)
258 };
259
260 let dpms = DPMSFeatures::parse(r)?;
261
262 Ok(DisplayParameters { input, max_size, gamma, dpms })
263 }
264}
265
266#[derive(Debug, Clone, Copy)]
268pub enum VideoInput {
269 Analog {
270 signal_level: SignalLevel,
272 setup_expected: bool,
274 supported_sync: SupportedSync
276 },
277 Digital {
278 dfp_compatible: bool
280 }
281}
282
283impl VideoInput {
284 fn parse(r: &mut Reader) -> Result<VideoInput> {
285 let val = r.read_u8()?;
286 if val & (1 << 7) == 0 {
287 let signal_level = match (val & 0b01100000) >> 5 {
288 0 => SignalLevel { high: 0.700, low: 0.300 },
289 1 => SignalLevel { high: 0.714, low: 0.286 },
290 2 => SignalLevel { high: 1.000, low: 0.400 },
291 3 => SignalLevel { high: 0.700, low: 0.000 },
292 _ => unreachable!()
293 };
294 let setup_expected = val & (1 << 4) > 0;
295 let supported_sync = SupportedSync {
296 serrated_vsync: val & (1 << 3) > 0,
297 sync_on_green: val & (1 << 2) > 0,
298 composite_sync: val & (1 << 1) > 0,
299 seperate_sync: val & (1 << 0) > 0
300 };
301 Ok(VideoInput::Analog { signal_level, setup_expected, supported_sync })
302 } else {
303 Ok(VideoInput::Digital { dfp_compatible: val & 1 > 0 })
304 }
305 }
306}
307
308#[derive(Debug, Clone, Copy)]
310pub struct SignalLevel {
311 pub high: f32,
312 pub low: f32
313}
314
315#[derive(Debug, Clone, Copy)]
317pub struct SupportedSync {
318 pub serrated_vsync: bool,
320 pub sync_on_green: bool,
322 pub composite_sync: bool,
324 pub seperate_sync: bool
326}
327
328#[derive(Debug, Clone, Copy)]
330pub struct ImageSize {
331 pub width: f32,
332 pub height: f32
333}
334
335#[derive(Debug, Clone)]
337pub struct DPMSFeatures {
338 pub standby_supported: bool,
339 pub suspend_supported: bool,
340 pub low_power_supported: bool,
341 pub display_type: DisplayType,
342 pub default_srgb: bool,
343 pub preferred_timing_mode: bool,
346 pub default_gtf_supported: bool
348}
349
350impl DPMSFeatures {
351 fn parse(r: &mut Reader) -> Result<DPMSFeatures> {
352 let val = r.read_u8()?;
353
354 Ok(DPMSFeatures {
355 standby_supported: val & (1 << 7) > 0,
356 suspend_supported: val & (1 << 6) > 0,
357 low_power_supported: val & (1 << 5) > 0,
358 display_type: match (val & 0b00011000) >> 3 {
359 0 => DisplayType::Monochrome,
360 1 => DisplayType::RGBColor,
361 2 => DisplayType::OtherColor,
362 3 => DisplayType::Undefined,
363 _ => unreachable!()
364 },
365 default_srgb: val & (1 << 2) > 0,
366 preferred_timing_mode: val & (1 << 1) > 0,
367 default_gtf_supported: val & (1 << 0) > 0
368 })
369 }
370}
371
372#[derive(Debug, Clone, Copy)]
374pub enum DisplayType {
375 Monochrome,
376 RGBColor,
377 OtherColor,
378 Undefined
379}
380
381#[derive(Debug, Clone)]
384pub struct ColorCharacteristics {
385 pub red: (f32, f32),
386 pub green: (f32, f32),
387 pub blue: (f32, f32),
388 pub white: (f32, f32),
389 pub white_points: Vec<WhitePoint>
390}
391
392impl ColorCharacteristics {
393 fn parse(r: &mut Reader) -> Result<ColorCharacteristics> {
394 let rg_low = r.read_u8()? as u16;
395 let bw_low = r.read_u8()? as u16;
396 let rh_x = r.read_u8()? as u16;
397 let rh_y = r.read_u8()? as u16;
398 let gh_x = r.read_u8()? as u16;
399 let gh_y = r.read_u8()? as u16;
400 let bh_x = r.read_u8()? as u16;
401 let bh_y = r.read_u8()? as u16;
402 let wh_x = r.read_u8()? as u16;
403 let wh_y = r.read_u8()? as u16;
404
405 let red_x = (rh_x << 2 | (rg_low & 0b11000000) >> 6) as f32 / 1024.0;
406 let red_y = (rh_y << 2 | (rg_low & 0b00110000) >> 4) as f32 / 1024.0;
407 let green_x = (gh_x << 2 | (rg_low & 0b00001100) >> 2) as f32 / 1024.0;
408 let green_y = (gh_y << 2 | (rg_low & 0b00000011) >> 0) as f32 / 1024.0;
409 let blue_x = (bh_x << 2 | (bw_low & 0b11000000) >> 6) as f32 / 1024.0;
410 let blue_y = (bh_y << 2 | (bw_low & 0b00110000) >> 4) as f32 / 1024.0;
411 let white_x = (wh_x << 2 | (bw_low & 0b00001100) >> 2) as f32 / 1024.0;
412 let white_y = (wh_y << 2 | (bw_low & 0b00000011) >> 0) as f32 / 1024.0;
413
414 Ok(ColorCharacteristics {
415 red: (red_x, red_y),
416 green: (green_x, green_y),
417 blue: (blue_x, blue_y),
418 white: (white_x, white_y),
419 white_points: Vec::new()
420 })
421 }
422}
423
424#[derive(Debug, Clone, Copy)]
427pub struct WhitePoint {
428 pub index: u8,
429 pub x: f32,
430 pub y: f32,
431 pub gamma: f32
432}
433
434#[derive(Debug, Clone)]
436pub struct Timings {
437 pub established_timings: Vec<EstablishedTiming>,
439 pub standard_timings: Vec<StandardTiming>,
441 pub detailed_timings: Vec<DetailedTiming>
444}
445
446impl Timings {
447 fn parse(r: &mut Reader) -> Result<Timings> {
448 let mut ft = r.read_u16()?;
449
450 let mut established_timings = Vec::new();
451 if ft & 1 > 0 {
452 established_timings.push(EstablishedTiming::H800V600F60);
453 }
454 ft >>= 1;
455 if ft & 1 > 0 {
456 established_timings.push(EstablishedTiming::H800V600F56);
457 }
458 ft >>= 1;
459 if ft & 1 > 0 {
460 established_timings.push(EstablishedTiming::H640V480F75);
461 }
462 ft >>= 1;
463 if ft & 1 > 0 {
464 established_timings.push(EstablishedTiming::H640V480F72);
465 }
466 ft >>= 1;
467 if ft & 1 > 0 {
468 established_timings.push(EstablishedTiming::H640V480F67);
469 }
470 ft >>= 1;
471 if ft & 1 > 0 {
472 established_timings.push(EstablishedTiming::H640V480F60);
473 }
474 ft >>= 1;
475 if ft & 1 > 0 {
476 established_timings.push(EstablishedTiming::H720V400F88);
477 }
478 ft >>= 1;
479 if ft & 1 > 0 {
480 established_timings.push(EstablishedTiming::H720V400F70);
481 }
482 ft >>= 1;
483 if ft & 1 > 0 {
484 established_timings.push(EstablishedTiming::H1280V1024F75);
485 }
486 ft >>= 1;
487 if ft & 1 > 0 {
488 established_timings.push(EstablishedTiming::H1024V768F75);
489 }
490 ft >>= 1;
491 if ft & 1 > 0 {
492 established_timings.push(EstablishedTiming::H1024V768F70);
493 }
494 ft >>= 1;
495 if ft & 1 > 0 {
496 established_timings.push(EstablishedTiming::H1024V768F60);
497 }
498 ft >>= 1;
499 if ft & 1 > 0 {
500 established_timings.push(EstablishedTiming::H1024V768F87);
501 }
502 ft >>= 1;
503 if ft & 1 > 0 {
504 established_timings.push(EstablishedTiming::H832V624F75);
505 }
506 ft >>= 1;
507 if ft & 1 > 0 {
508 established_timings.push(EstablishedTiming::H800V600F75);
509 }
510 ft >>= 1;
511 if ft & 1 > 0 {
512 established_timings.push(EstablishedTiming::H800V600F72);
513 }
514
515 let ft = r.read_u8()?;
516 if ft & (1 << 7) > 0 {
517 established_timings.push(EstablishedTiming::H1152V870F75);
518 }
519
520 let mut standard_timings = Vec::new();
521 for _ in 0..8 {
522 let low = r.read_u8()?;
523 let high = r.read_u8()?;
524 if low == 1 && high == 1 {
525 continue;
526 } else {
527 standard_timings.push(StandardTiming {
528 horizontal_resolution: (low as u16 + 31) * 8,
529 aspect_ratio: match high >> 6 {
530 0 => 16.0/10.0,
531 1 => 4.0/3.0,
532 2 => 5.0/4.0,
533 3 => 16.0/9.0,
534 _ => unreachable!()
535 },
536 refresh_rate: (high & 0b00111111) + 60
537 });
538 }
539 }
540
541 let detailed_timings = Vec::new();
542
543 Ok(Timings { established_timings, standard_timings, detailed_timings })
544 }
545}
546
547#[derive(Debug, Clone, Copy)]
549pub enum EstablishedTiming {
550 H720V400F70,
551 H720V400F88,
552 H640V480F60,
553 H640V480F67,
554 H640V480F72,
555 H640V480F75,
556 H800V600F56,
557 H800V600F60,
558 H800V600F72,
559 H800V600F75,
560 H832V624F75,
561 H1024V768F87,
562 H1024V768F60,
563 H1024V768F70,
564 H1024V768F75,
565 H1280V1024F75,
566 H1152V870F75
567}
568
569#[derive(Debug, Clone, Copy)]
572pub struct StandardTiming {
573 pub horizontal_resolution: u16,
574 pub aspect_ratio: f32,
575 pub refresh_rate: u8
576}
577
578#[derive(Debug, Clone)]
580pub struct DetailedTiming {
581 pub pixel_clock: u32,
583 pub active: (u16, u16),
585 pub front_porch: (u16, u16),
587 pub sync_length: (u16, u16),
589 pub back_porch: (u16, u16),
591 pub image_size: ImageSize,
593 pub border: (u16, u16),
595 pub interlaced: bool,
596 pub stereo: StereoType,
597 pub sync_type: SyncType
598}
599
600impl DetailedTiming {
601 fn parse(r: &mut Reader) -> Result<Option<DetailedTiming>> {
602 let pixel_clock = r.read_u16()? as u32 * 10000;
603 let ha_low = r.read_u8()? as u16;
604
605 if pixel_clock == 0 || ha_low == 0 {
606 return Ok(None);
607 }
608
609 let hb_low = r.read_u8()? as u16;
610 let h_high = r.read_u8()? as u16;
611
612 let horizontal_active = ha_low | (((h_high & 0xf0) >> 4) << 8);
613 let horizontal_blanking = hb_low | (((h_high & 0x0f) >> 0) << 8);
614
615 let va_low = r.read_u8()? as u16;
616 let vb_low = r.read_u8()? as u16;
617 let v_high = r.read_u8()? as u16;
618
619 let vertical_active = va_low | (((v_high & 0xf0) >> 4) << 8);
620 let vertical_blanking = vb_low | (((v_high & 0x0f) >> 0) << 8);
621
622 let hso_low = r.read_u8()? as u16;
623 let hsw_low = r.read_u8()? as u16;
624 let vs_low = r.read_u8()? as u16;
625 let hvs_high = r.read_u8()? as u16;
626
627 let hso_high = (hvs_high & 0b11000000) >> 6;
628 let hsw_high = (hvs_high & 0b00110000) >> 4;
629 let vso_high = (hvs_high & 0b00001100) >> 2;
630 let vsw_high = (hvs_high & 0b00000011) >> 0;
631 let vso_low = (vs_low & 0xf0) >> 4;
632 let vsw_low = (vs_low & 0x0f) >> 0;
633 let vertical_front_porch = vso_low | (vso_high << 4);
634 let horizontal_front_porch = hso_low | (hso_high << 8);
635 let vertical_sync_width = vsw_low | (vsw_high << 4);
636 let horizontal_sync_width = hsw_low | (hsw_high << 8);
637 let active = (horizontal_active, vertical_active);
638 let front_porch = (horizontal_front_porch, vertical_front_porch);
639 let sync_length = (horizontal_sync_width, vertical_sync_width);
640 let back_porch = (
641 horizontal_blanking - horizontal_sync_width - horizontal_front_porch,
642 vertical_blanking - vertical_sync_width - vertical_front_porch
643 );
644
645 let hs_low = r.read_u8()? as u16;
646 let vs_low = r.read_u8()? as u16;
647 let s_high = r.read_u8()? as u16;
648
649 let h_size = hs_low | ((s_high & 0xf0) >> 4) << 8;
650 let v_size = vs_low | ((s_high & 0x0f) >> 0) << 8;
651 let image_size = ImageSize { width: (h_size as f32) / 10.0, height: (v_size as f32) / 10.0 };
652
653 let hb = r.read_u8()? as u16;
654 let vb = r.read_u8()? as u16;
655
656 let border = (hb, vb);
657
658 let (interlaced, stereo, sync_type) = SyncType::parse(r)?;
659
660 Ok(Some(DetailedTiming {
661 pixel_clock, active, front_porch, sync_length, back_porch,
662 image_size, border, interlaced, stereo, sync_type
663 }))
664 }
665}
666
667#[derive(Debug, Clone, Copy)]
669pub enum StereoType {
670 None,
671 SequentialRightSync,
672 SequentialLeftSync,
673 InterleavedLinesRightEven,
674 InterleavedLinesLeftEven,
675 Interleaved4Way,
676 SideBySide
677}
678
679#[derive(Debug, Clone, Copy)]
681pub enum SyncType {
682 Composite {
684 serrated: bool,
686 line: SyncLine
688 },
689 Seperate {
691 horizontal: SyncPolarity,
693 vertical: SyncPolarity
695 }
696}
697
698impl SyncType {
699 fn parse(r: &mut Reader) -> Result<(bool, StereoType, SyncType)> {
700 let val = r.read_u8()?;
701
702 let interlaced = val & (1 << 7) > 0;
703 let stereo = match (val & (1 << 6) > 0, val & (1 << 5) > 0, val & (1 << 0) > 0) {
704 (false, false, _) => StereoType::None,
705 (false, true, false) => StereoType::SequentialRightSync,
706 (true, false, false) => StereoType::SequentialLeftSync,
707 (false, true, true) => StereoType::InterleavedLinesRightEven,
708 (true, false, true) => StereoType::InterleavedLinesLeftEven,
709 (true, true, false) => StereoType::Interleaved4Way,
710 (true, true, true) => StereoType::SideBySide
711 };
712
713 let sync_type = match (val & 0b00011000) >> 3 {
714 0 | 1 => SyncType::Composite {
715 serrated: val & (1 << 2) > 0,
716 line: if val & (1 << 1) > 0 {
717 SyncLine::RGB
718 } else {
719 SyncLine::Green
720 }
721 },
722 2 => SyncType::Composite {
723 serrated: val & (1 << 2) > 0,
724 line: SyncLine::Digital(if val & (1 << 1) > 0 {
725 SyncPolarity::Positive
726 } else {
727 SyncPolarity::Negative
728 })
729 },
730 3 => SyncType::Seperate {
731 vertical: if val & (1 << 2) > 0 {
732 SyncPolarity::Positive
733 } else {
734 SyncPolarity::Negative
735 },
736 horizontal: if val & (1 << 1) > 0 {
737 SyncPolarity::Positive
738 } else {
739 SyncPolarity::Negative
740 }
741 },
742 _ => unreachable!()
743 };
744
745 Ok((interlaced, stereo, sync_type))
746 }
747}
748
749#[derive(Debug, Clone, Copy)]
751pub enum SyncLine {
752 RGB,
753 Green,
754 Digital(SyncPolarity)
755}
756
757#[derive(Debug, Clone, Copy)]
759pub enum SyncPolarity {
760 Positive,
761 Negative
762}
763
764#[derive(Debug, Clone)]
766pub struct MonitorDescriptors(pub Vec<MonitorDescriptor>);
767
768impl MonitorDescriptors {
769 fn parse(r: &mut Reader) -> Result<(MonitorDescriptors, Vec<DetailedTiming>, Vec<StandardTiming>, Vec<WhitePoint>)> {
770 let mut detailed_timings = vec![DetailedTiming::parse(r)?.ok_or("Expected detailed timing block.")?];
771
772 let mut standard_timings = Vec::new();
773 let mut monitor_descriptors = Vec::new();
774 let mut white_points = Vec::new();
775
776 for _ in 0..3 {
777 if let Some(timing) = DetailedTiming::parse(r)? {
778 detailed_timings.push(timing);
779 } else {
780 let tag = r.read_u8()?;
781 r.read_u8()?;
782
783 match tag {
784 0x00..=0x0f => monitor_descriptors.push(MonitorDescriptor::ManufacturerDefined(tag, [
785 r.read_u8()?,
786 r.read_u8()?,
787 r.read_u8()?,
788 r.read_u8()?,
789 r.read_u8()?,
790 r.read_u8()?,
791 r.read_u8()?,
792 r.read_u8()?,
793 r.read_u8()?,
794 r.read_u8()?,
795 r.read_u8()?,
796 r.read_u8()?,
797 r.read_u8()?
798 ])),
799 0x10 => continue,
800 0x11..=0xf9 => monitor_descriptors.push(MonitorDescriptor::Undefined(tag, [
801 r.read_u8()?,
802 r.read_u8()?,
803 r.read_u8()?,
804 r.read_u8()?,
805 r.read_u8()?,
806 r.read_u8()?,
807 r.read_u8()?,
808 r.read_u8()?,
809 r.read_u8()?,
810 r.read_u8()?,
811 r.read_u8()?,
812 r.read_u8()?,
813 r.read_u8()?
814 ])),
815 0xfa => {
816 for _ in 0..6 {
817 let low = r.read_u8()?;
818 let high = r.read_u8()?;
819 if low == 1 && high == 1 {
820 continue;
821 } else {
822 standard_timings.push(StandardTiming {
823 horizontal_resolution: (low as u16 + 31) * 8,
824 aspect_ratio: match high >> 6 {
825 0 => 16.0/10.0,
826 1 => 4.0/3.0,
827 2 => 5.0/4.0,
828 3 => 16.0/9.0,
829 _ => unreachable!()
830 },
831 refresh_rate: (high & 0b00111111) + 60
832 });
833 }
834 }
835
836 ensure(r.read_u8()? == 0x0a, "Expected 0x0a in monitor descriptor.")?;
837 },
838 0xfb => {
839 for _ in 0..2 {
840 let index = r.read_u8()?;
841 let w_low = r.read_u8()? as u16;
842 let wx_high = r.read_u8()? as u16;
843 let wy_high = r.read_u8()? as u16;
844 let white_x = (wx_high << 2 | (w_low & 0b00001100) >> 2) as f32 / 1024.0;
845 let white_y = (wy_high << 2 | (w_low & 0b00000011) >> 0) as f32 / 1024.0;
846 let gamma_val = r.read_u8()? as u16;
847 let gamma = (gamma_val as f32 + 100.0) / 100.0;
848 white_points.push(WhitePoint { x: white_x, y: white_y, gamma, index });
849 if index == 0 {
850 r.read_u32()?;
851 r.read_u8()?;
852 break;
853 }
854 }
855
856 ensure(r.read_u8()? == 0x0a, "Expected 0x0a in monitor descriptor.")?;
857 ensure(r.read_u16()? == 0x2020, "Expected 0x20 in monitor descriptor.")?;
858 },
859 0xfc | 0xfe | 0xff => {
860 let mut out = String::new();
861 let mut byte = r.read_u8()?;
862 let mut i = 0;
863 while byte != 0x0a {
864 out.push(byte as char);
865 i += 1;
866 if i == 13 {
867 break;
868 }
869 byte = r.read_u8()?;
870 }
871 i += 1;
872 while i < 13 {
873 ensure(r.read_u8()? == 0x20, "Expected 0x20 in monitor descriptor.")?;
874 i += 1;
875 }
876
877 match tag {
878 0xfc => monitor_descriptors.push(MonitorDescriptor::MonitorName(out)),
879 0xfe => monitor_descriptors.push(MonitorDescriptor::OtherString(out)),
880 0xff => monitor_descriptors.push(MonitorDescriptor::SerialNumber(out)),
881 _ => unreachable!()
882 }
883 },
884 0xfd => {
885 let min_vrate = r.read_u8()?;
886 let max_vrate = r.read_u8()?;
887 let min_hrate = r.read_u8()? as u32 * 1000;
888 let max_hrate = r.read_u8()? as u32 * 1000;
889 let pixel_clock = r.read_u8()? as u32 * 10000000;
890 let stime = r.read_u8()?;
891 let secondary_timing = match stime {
892 0x00 => {
893 ensure(r.read_u8()? == 0x0a, "Expected 0x0a in monitor descriptor.")?;
894 ensure(r.read_u16()? == 0x2020, "Expected 0x20 in monitor descriptor.")?;
895 ensure(r.read_u16()? == 0x2020, "Expected 0x20 in monitor descriptor.")?;
896 ensure(r.read_u16()? == 0x2020, "Expected 0x20 in monitor descriptor.")?;
897 SecondaryTiming::None
898 },
899 0x02 => {
900 ensure(r.read_u8()? == 0x00, "Expected 0x0a in monitor descriptor.")?;
901 let start_horizontal_freq = r.read_u8()? as u32 * 2000;
902 let c = r.read_u8()? as f32 / 2.0;
903 let m = r.read_u16()? as f32;
904 let k = r.read_u8()? as f32;
905 let j = r.read_u8()? as f32 / 2.0;
906 SecondaryTiming::GTF {
907 start_horizontal_freq, c, m, k, j
908 }
909 },
910 _ => {
911 let data = [
912 r.read_u8()?,
913 r.read_u8()?,
914 r.read_u8()?,
915 r.read_u8()?,
916 r.read_u8()?,
917 r.read_u8()?,
918 r.read_u8()?
919 ];
920 SecondaryTiming::Other(stime, data)
921 }
922 };
923 monitor_descriptors.push(MonitorDescriptor::RangeLimits {
924 vertical_rate: (min_vrate, max_vrate),
925 horizontal_rate: (min_hrate, max_hrate),
926 pixel_clock, secondary_timing
927 });
928 }
929 }
930 }
931 }
932
933 Ok((MonitorDescriptors(monitor_descriptors), detailed_timings, standard_timings, white_points))
934 }
935}
936
937#[derive(Debug, Clone)]
939pub enum MonitorDescriptor {
940 SerialNumber(String),
941 OtherString(String),
942 RangeLimits {
943 vertical_rate: (u8, u8),
945 horizontal_rate: (u32, u32),
947 pixel_clock: u32,
949 secondary_timing: SecondaryTiming
951 },
952 MonitorName(String),
953 Undefined(u8, [u8; 13]),
954 ManufacturerDefined(u8, [u8; 13])
955}
956
957#[derive(Debug, Clone)]
959pub enum SecondaryTiming {
960 None,
961 GTF {
963 start_horizontal_freq: u32,
965 c: f32,
966 m: f32,
967 k: f32,
968 j: f32
969 },
970 Other(u8, [u8; 7])
971}
972
973pub fn parse<T: Read + 'static>(value: &mut T) -> Result<EDID> {
975 EDID::parse(&mut Reader::new(value))
976}