Skip to main content

linux_cec/
cdc.rs

1/*
2 * Copyright © 2024 Valve Software
3 * SPDX-License-Identifier: LGPL-2.1-or-later
4 */
5
6//! Capability Discovery and Control support
7
8#![allow(clippy::len_without_is_empty)]
9
10use bitfield_struct::bitfield;
11#[cfg(test)]
12use linux_cec_macros::{message_test, opcode_test};
13use linux_cec_macros::{BitfieldSpecifier, MessageEnum, Operand};
14use num_enum::{IntoPrimitive, TryFromPrimitive};
15
16use crate::operand::OperandEncodable;
17#[cfg(test)]
18use crate::Error;
19use crate::{constants, operand, PhysicalAddress, Range, Result};
20
21#[derive(BitfieldSpecifier, Debug, Copy, Clone, PartialEq, Eq, Hash)]
22#[bits = 2]
23#[repr(u8)]
24pub enum CdcErrorCode {
25    NoError = constants::CEC_OP_HPD_ERROR_NONE,
26    InitiatorNotCapable = constants::CEC_OP_HPD_ERROR_INITIATOR_NOT_CAPABLE,
27    InitiatorIncapableState = constants::CEC_OP_HPD_ERROR_INITIATOR_WRONG_STATE,
28    Other = constants::CEC_OP_HPD_ERROR_OTHER,
29}
30
31#[derive(BitfieldSpecifier, Debug, Copy, Clone, PartialEq, Eq, Hash)]
32#[bits = 2]
33#[repr(u8)]
34pub enum FunctionalityState {
35    NotSupported = constants::CEC_OP_ENC_FUNC_STATE_EXT_CON_NOT_SUPPORTED,
36    Inactive = constants::CEC_OP_ENC_FUNC_STATE_EXT_CON_INACTIVE,
37    Active = constants::CEC_OP_ENC_FUNC_STATE_EXT_CON_ACTIVE,
38    #[default]
39    Invalid(u8),
40}
41
42pub type EncFunctionalityState = FunctionalityState;
43pub type HostFunctionalityState = FunctionalityState;
44
45#[derive(BitfieldSpecifier, Debug, Copy, Clone, PartialEq, Eq, Hash)]
46#[bits = 2]
47#[repr(u8)]
48pub enum HecFunctionalityState {
49    NotSupported = constants::CEC_OP_HEC_FUNC_STATE_NOT_SUPPORTED,
50    Inactive = constants::CEC_OP_HEC_FUNC_STATE_INACTIVE,
51    Active = constants::CEC_OP_HEC_FUNC_STATE_ACTIVE,
52    ActivationField = constants::CEC_OP_HEC_FUNC_STATE_ACTIVATION_FIELD,
53}
54
55#[bitfield(u8)]
56#[derive(PartialEq, Eq, Hash, Operand)]
57pub struct HecState {
58    #[bits(2)]
59    pub cdc_error: CdcErrorCode,
60    #[bits(2)]
61    pub enc_functionality: EncFunctionalityState,
62    #[bits(2)]
63    pub host_functionality: HostFunctionalityState,
64    #[bits(2)]
65    pub hec_functionality: HecFunctionalityState,
66}
67
68#[cfg(test)]
69mod test_hec_state {
70    use super::*;
71
72    opcode_test! {
73        ty: HecState,
74        instance: HecState::new()
75            .with_cdc_error(CdcErrorCode::NoError)
76            .with_enc_functionality(EncFunctionalityState::Inactive)
77            .with_host_functionality(HostFunctionalityState::Active)
78            .with_hec_functionality(HecFunctionalityState::ActivationField),
79        bytes: [0xE4],
80        extra: [Overfull],
81    }
82
83    #[test]
84    fn test_decode_empty() {
85        assert_eq!(
86            HecState::try_from_bytes(&[]),
87            Err(Error::OutOfRange {
88                got: 0,
89                expected: Range::AtLeast(1),
90                quantity: "bytes"
91            })
92        );
93    }
94}
95
96#[derive(BitfieldSpecifier, Debug, Copy, Clone, PartialEq, Eq, Hash)]
97#[bits = 4]
98#[repr(u8)]
99pub enum HpdErrorCode {
100    NoError = constants::CEC_OP_HPD_ERROR_NONE,
101    InitiatorNotCapable = constants::CEC_OP_HPD_ERROR_INITIATOR_NOT_CAPABLE,
102    InitiatorIncapableState = constants::CEC_OP_HPD_ERROR_INITIATOR_WRONG_STATE,
103    Other = constants::CEC_OP_HPD_ERROR_OTHER,
104    NoVideo = constants::CEC_OP_HPD_ERROR_NONE_NO_VIDEO,
105    #[default]
106    Invalid(u8),
107}
108
109#[derive(BitfieldSpecifier, Debug, Copy, Clone, PartialEq, Eq, Hash)]
110#[bits = 4]
111#[repr(u8)]
112pub enum HpdState {
113    CpAndEdidDisable = constants::CEC_OP_HPD_STATE_CP_EDID_DISABLE,
114    CpAndEdidEnable = constants::CEC_OP_HPD_STATE_CP_EDID_ENABLE,
115    CpAndEdidDisableEnable = constants::CEC_OP_HPD_STATE_CP_EDID_DISABLE_ENABLE,
116    EdidDisable = constants::CEC_OP_HPD_STATE_EDID_DISABLE,
117    EdidEnable = constants::CEC_OP_HPD_STATE_EDID_ENABLE,
118    EdidDisableEnable = constants::CEC_OP_HPD_STATE_EDID_DISABLE_ENABLE,
119    #[default]
120    Invalid(u8),
121}
122
123#[bitfield(u8)]
124#[derive(PartialEq, Eq, Hash, Operand)]
125pub struct InputPortHpdState {
126    #[bits(4)]
127    pub state: HpdState,
128    #[bits(4)]
129    pub input_port: usize,
130}
131
132#[cfg(test)]
133mod test_input_port_hpd_state {
134    use super::*;
135
136    opcode_test! {
137        ty: InputPortHpdState,
138        instance: InputPortHpdState::new()
139            .with_input_port(0xA)
140            .with_state(HpdState::EdidDisableEnable),
141        bytes: [0xA5],
142        extra: [Overfull],
143    }
144
145    #[test]
146    fn test_decode_empty() {
147        assert_eq!(
148            InputPortHpdState::try_from_bytes(&[]),
149            Err(Error::OutOfRange {
150                got: 0,
151                expected: Range::AtLeast(1),
152                quantity: "bytes"
153            })
154        );
155    }
156}
157
158#[bitfield(u8)]
159#[derive(PartialEq, Eq, Hash, Operand)]
160pub struct HpdStateErrorCode {
161    #[bits(4)]
162    pub error_code: HpdErrorCode,
163    #[bits(4)]
164    pub state: HpdState,
165}
166
167#[cfg(test)]
168mod test_hpd_state_error_code {
169    use super::*;
170
171    opcode_test! {
172        ty: HpdStateErrorCode,
173        instance: HpdStateErrorCode::new()
174            .with_state(HpdState::EdidDisableEnable)
175            .with_error_code(HpdErrorCode::InitiatorNotCapable),
176        bytes: [0x51],
177        extra: [Overfull],
178    }
179
180    #[test]
181    fn test_decode_empty() {
182        assert_eq!(
183            HpdStateErrorCode::try_from_bytes(&[]),
184            Err(Error::OutOfRange {
185                got: 0,
186                expected: Range::AtLeast(1),
187                quantity: "bytes"
188            })
189        );
190    }
191}
192
193#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
194pub struct HecField {
195    pub input: [bool; 14],
196    pub output: bool,
197}
198
199impl OperandEncodable for HecField {
200    fn to_bytes(&self, buf: &mut impl Extend<u8>) {
201        let word = if self.output { 0x4000 } else { 0 };
202        let word = self
203            .input
204            .iter()
205            .enumerate()
206            .fold(word, |accum, (idx, bit)| accum | (u16::from(*bit) << idx));
207        word.to_bytes(buf);
208    }
209
210    fn try_from_bytes(bytes: &[u8]) -> Result<Self> {
211        let word = u16::try_from_bytes(bytes)?;
212        let mut input = [false; 14];
213        for (idx, item) in input.iter_mut().enumerate() {
214            *item = (word >> idx) & 1 == 1;
215        }
216        Ok(HecField {
217            input,
218            output: (word & 0x4000) != 0,
219        })
220    }
221
222    fn len(&self) -> usize {
223        2
224    }
225
226    fn expected_len() -> Range<usize> {
227        Range::AtLeast(2)
228    }
229}
230
231#[cfg(test)]
232mod test_hec_field {
233    use super::*;
234
235    opcode_test! {
236        ty: HecField,
237        instance: HecField {
238            input: [
239                 true, false, false, false,
240                false,  true, false, false,
241                false, false,  true,  true,
242                false, false,
243            ],
244            output: true,
245        },
246        bytes: [0x4C, 0x21],
247        extra: [Overfull],
248    }
249
250    #[test]
251    fn test_decode_empty() {
252        assert_eq!(
253            HecField::try_from_bytes(&[]),
254            Err(Error::OutOfRange {
255                got: 0,
256                expected: Range::AtLeast(2),
257                quantity: "bytes"
258            })
259        );
260    }
261}
262
263#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, MessageEnum)]
264#[repr(u8)]
265#[non_exhaustive]
266pub enum Message {
267    HecInquireState {
268        terminating_address1: PhysicalAddress,
269        terminating_address2: PhysicalAddress,
270    } = constants::CEC_MSG_CDC_HEC_INQUIRE_STATE,
271    HecReportState {
272        physical_address: PhysicalAddress,
273        state: HecState,
274        field: Option<HecField>,
275    } = constants::CEC_MSG_CDC_HEC_REPORT_STATE,
276    HecSetStateAdjacent {
277        terminating_address: PhysicalAddress,
278        state: bool,
279    } = constants::CEC_MSG_CDC_HEC_SET_STATE_ADJACENT,
280    HecSetState {
281        terminating_address1: PhysicalAddress,
282        terminating_address2: PhysicalAddress,
283        state: bool,
284        terminating_addresses: operand::BoundedBufferOperand<3, PhysicalAddress>,
285    } = constants::CEC_MSG_CDC_HEC_SET_STATE,
286    HecRequestDeactivation {
287        terminating_address1: PhysicalAddress,
288        terminating_address2: PhysicalAddress,
289        terminating_address3: PhysicalAddress,
290    } = constants::CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION,
291    HecNotifyAlive = constants::CEC_MSG_CDC_HEC_NOTIFY_ALIVE,
292    HecDiscover = constants::CEC_MSG_CDC_HEC_DISCOVER,
293    HpdSetState(InputPortHpdState) = constants::CEC_MSG_CDC_HPD_SET_STATE,
294    HpdReportState(HpdStateErrorCode) = constants::CEC_MSG_CDC_HPD_REPORT_STATE,
295}
296
297impl Message {
298    #[must_use]
299    pub fn opcode(&self) -> Opcode {
300        let opcode = unsafe { *<*const _>::from(self).cast::<u8>() };
301        Opcode::try_from_primitive(opcode).unwrap()
302    }
303}
304
305impl OperandEncodable for Message {
306    fn to_bytes(&self, buf: &mut impl Extend<u8>) {
307        let bytes = Message::to_bytes(self);
308        buf.extend(bytes);
309    }
310
311    fn try_from_bytes(bytes: &[u8]) -> Result<Self> {
312        Message::try_from_bytes(bytes)
313    }
314
315    fn len(&self) -> usize {
316        Message::len(self)
317    }
318
319    fn expected_len() -> Range<usize> {
320        Range::AtLeast(1)
321    }
322}
323
324#[cfg(test)]
325mod test_hec_inquire_state {
326    use super::*;
327
328    message_test! {
329        ty: HecInquireState,
330        instance: Message::HecInquireState {
331            terminating_address1: PhysicalAddress(0x1234),
332            terminating_address2: PhysicalAddress(0x5678),
333        },
334        bytes: [0x12, 0x34, 0x56, 0x78],
335        extra: [Overfull, Empty],
336    }
337
338    #[test]
339    fn test_decoding_missing_byte() {
340        assert_eq!(
341            Message::try_from_bytes(&[Opcode::HecInquireState as u8, 0x12, 0x34, 0x56]),
342            Err(Error::OutOfRange {
343                expected: Range::AtLeast(5),
344                got: 4,
345                quantity: "bytes",
346            })
347        );
348    }
349
350    #[test]
351    fn test_decoding_missing_operand() {
352        assert_eq!(
353            Message::try_from_bytes(&[Opcode::HecInquireState as u8, 0x12, 0x34]),
354            Err(Error::OutOfRange {
355                expected: Range::AtLeast(5),
356                got: 3,
357                quantity: "bytes",
358            })
359        );
360    }
361
362    #[test]
363    fn test_decoding_missing_operand_and_byte() {
364        assert_eq!(
365            Message::try_from_bytes(&[Opcode::HecInquireState as u8, 0x12]),
366            Err(Error::OutOfRange {
367                expected: Range::AtLeast(5),
368                got: 2,
369                quantity: "bytes",
370            })
371        );
372    }
373}
374
375#[cfg(test)]
376mod test_hec_report_state {
377    use super::*;
378
379    message_test! {
380        name: _field,
381        ty: HecReportState,
382        instance: Message::HecReportState {
383            physical_address: PhysicalAddress(0x1234),
384            state: HecState::new()
385                .with_cdc_error(CdcErrorCode::NoError)
386                .with_enc_functionality(EncFunctionalityState::Inactive)
387                .with_host_functionality(HostFunctionalityState::Active)
388                .with_hec_functionality(HecFunctionalityState::ActivationField),
389            field: Some(HecField {
390                input: [
391                     true, false, false, false,
392                    false,  true, false, false,
393                    false, false,  true,  true,
394                    false, false,
395                ],
396                output: true,
397            }),
398        },
399        bytes: [0x12, 0x34, 0xE4, 0x4C, 0x21],
400        extra: [Overfull],
401    }
402
403    message_test! {
404        name: _no_field,
405        ty: HecReportState,
406        instance: Message::HecReportState {
407            physical_address: PhysicalAddress(0x1234),
408            state: HecState::new()
409                .with_cdc_error(CdcErrorCode::NoError)
410                .with_enc_functionality(EncFunctionalityState::Inactive)
411                .with_host_functionality(HostFunctionalityState::Active)
412                .with_hec_functionality(HecFunctionalityState::ActivationField),
413            field: None,
414        },
415        bytes: [0x12, 0x34, 0xE4],
416    }
417
418    #[test]
419    fn test_decoding_missing_byte() {
420        assert_eq!(
421            Message::try_from_bytes(&[Opcode::HecReportState as u8, 0x12, 0x34, 0xE4, 0x4C]),
422            Err(Error::OutOfRange {
423                expected: Range::AtLeast(6),
424                got: 5,
425                quantity: "bytes",
426            })
427        );
428    }
429
430    #[test]
431    fn test_decoding_missing_operand() {
432        assert_eq!(
433            Message::try_from_bytes(&[Opcode::HecReportState as u8, 0x12, 0x34]),
434            Err(Error::OutOfRange {
435                expected: Range::AtLeast(4),
436                got: 3,
437                quantity: "bytes",
438            })
439        );
440    }
441
442    #[test]
443    fn test_decoding_missing_operand_and_byte() {
444        assert_eq!(
445            Message::try_from_bytes(&[Opcode::HecReportState as u8, 0x12]),
446            Err(Error::OutOfRange {
447                expected: Range::AtLeast(4),
448                got: 2,
449                quantity: "bytes",
450            })
451        );
452    }
453
454    #[test]
455    fn test_decoding_missing_operands() {
456        assert_eq!(
457            Message::try_from_bytes(&[Opcode::HecReportState as u8]),
458            Err(Error::OutOfRange {
459                expected: Range::AtLeast(4),
460                got: 1,
461                quantity: "bytes",
462            })
463        );
464    }
465
466    #[test]
467    fn test_opcode() {
468        assert_eq!(
469            Message::HecReportState {
470                physical_address: PhysicalAddress(0x1234),
471                state: HecState::new()
472                    .with_cdc_error(CdcErrorCode::NoError)
473                    .with_enc_functionality(EncFunctionalityState::Inactive)
474                    .with_host_functionality(HostFunctionalityState::Active)
475                    .with_hec_functionality(HecFunctionalityState::ActivationField),
476                field: None,
477            }
478            .opcode(),
479            Opcode::HecReportState
480        );
481    }
482}
483
484#[cfg(test)]
485mod test_hec_set_state_adjacent {
486    use super::*;
487
488    message_test! {
489        ty: HecSetStateAdjacent,
490        instance: Message::HecSetStateAdjacent {
491            terminating_address: PhysicalAddress(0x1234),
492            state: true,
493        },
494        bytes: [0x12, 0x34, 0x01],
495        extra: [Overfull, Empty],
496    }
497
498    #[test]
499    fn test_decoding_missing_operand() {
500        assert_eq!(
501            Message::try_from_bytes(&[Opcode::HecSetStateAdjacent as u8, 0x12, 0x34]),
502            Err(Error::OutOfRange {
503                expected: Range::AtLeast(4),
504                got: 3,
505                quantity: "bytes",
506            })
507        );
508    }
509
510    #[test]
511    fn test_decoding_missing_operand_and_byte() {
512        assert_eq!(
513            Message::try_from_bytes(&[Opcode::HecSetStateAdjacent as u8, 0x12]),
514            Err(Error::OutOfRange {
515                expected: Range::AtLeast(4),
516                got: 2,
517                quantity: "bytes",
518            })
519        );
520    }
521}
522
523#[cfg(test)]
524mod test_hec_set_state {
525    use super::*;
526
527    message_test! {
528        name: _empty,
529        ty: HecSetState,
530        instance: Message::HecSetState {
531            terminating_address1: PhysicalAddress(0x1234),
532            terminating_address2: PhysicalAddress(0x5678),
533            state: true,
534            terminating_addresses: operand::BoundedBufferOperand::default(),
535        },
536        bytes: [0x12, 0x34, 0x56, 0x78, 0x01],
537    }
538
539    message_test! {
540        name: _1_extra,
541        ty: HecSetState,
542        instance: Message::HecSetState {
543            terminating_address1: PhysicalAddress(0x1234),
544            terminating_address2: PhysicalAddress(0x5678),
545            state: true,
546            terminating_addresses: operand::BoundedBufferOperand::try_from(
547                [PhysicalAddress(0xABCD)].as_ref()).unwrap(),
548        },
549        bytes: [0x12, 0x34, 0x56, 0x78, 0x01, 0xAB, 0xCD],
550    }
551
552    message_test! {
553        name: _2_extra,
554        ty: HecSetState,
555        instance: Message::HecSetState {
556            terminating_address1: PhysicalAddress(0x1234),
557            terminating_address2: PhysicalAddress(0x5678),
558            state: true,
559            terminating_addresses: operand::BoundedBufferOperand::try_from([
560                PhysicalAddress(0xABCD),
561                PhysicalAddress(0xEF01)
562            ].as_ref()).unwrap(),
563        },
564        bytes: [0x12, 0x34, 0x56, 0x78, 0x01, 0xAB, 0xCD, 0xEF, 0x01],
565    }
566
567    message_test! {
568        name: _full,
569        ty: HecSetState,
570        instance: Message::HecSetState {
571            terminating_address1: PhysicalAddress(0x1234),
572            terminating_address2: PhysicalAddress(0x5678),
573            state: true,
574            terminating_addresses: operand::BoundedBufferOperand::try_from([
575                PhysicalAddress(0xABCD),
576                PhysicalAddress(0xEF01),
577                PhysicalAddress(0x2345)
578            ].as_ref()).unwrap(),
579        },
580        bytes: [0x12, 0x34, 0x56, 0x78, 0x01, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45],
581        extra: [Overfull],
582    }
583
584    #[test]
585    fn test_opcode() {
586        assert_eq!(
587            Message::HecSetState {
588                terminating_address1: PhysicalAddress(0x1234),
589                terminating_address2: PhysicalAddress(0x5678),
590                state: true,
591                terminating_addresses: operand::BoundedBufferOperand::default(),
592            }
593            .opcode(),
594            Opcode::HecSetState
595        );
596    }
597
598    #[test]
599    fn test_decoding_missing_operand_1() {
600        assert_eq!(
601            Message::try_from_bytes(&[Opcode::HecSetState as u8, 0x12, 0x34, 0x56, 0x78]),
602            Err(Error::OutOfRange {
603                expected: Range::AtLeast(6),
604                got: 5,
605                quantity: "bytes",
606            })
607        );
608    }
609
610    #[test]
611    fn test_decoding_missing_operand_1_and_byte() {
612        assert_eq!(
613            Message::try_from_bytes(&[Opcode::HecSetState as u8, 0x12, 0x34, 0x56]),
614            Err(Error::OutOfRange {
615                expected: Range::AtLeast(6),
616                got: 4,
617                quantity: "bytes",
618            })
619        );
620    }
621
622    #[test]
623    fn test_decoding_missing_operand_2() {
624        assert_eq!(
625            Message::try_from_bytes(&[Opcode::HecSetState as u8, 0x12, 0x34]),
626            Err(Error::OutOfRange {
627                expected: Range::AtLeast(6),
628                got: 3,
629                quantity: "bytes",
630            })
631        );
632    }
633
634    #[test]
635    fn test_decoding_missing_operand_2_and_byte() {
636        assert_eq!(
637            Message::try_from_bytes(&[Opcode::HecSetState as u8, 0x12]),
638            Err(Error::OutOfRange {
639                expected: Range::AtLeast(6),
640                got: 2,
641                quantity: "bytes",
642            })
643        );
644    }
645
646    #[test]
647    fn test_decoding_missing_operands() {
648        assert_eq!(
649            Message::try_from_bytes(&[Opcode::HecSetState as u8]),
650            Err(Error::OutOfRange {
651                expected: Range::AtLeast(6),
652                got: 1,
653                quantity: "bytes",
654            })
655        );
656    }
657}
658
659#[cfg(test)]
660mod test_hec_request_deactivation {
661    use super::*;
662
663    message_test! {
664        ty: HecRequestDeactivation,
665        instance: Message::HecRequestDeactivation {
666            terminating_address1: PhysicalAddress(0x1234),
667            terminating_address2: PhysicalAddress(0x5678),
668            terminating_address3: PhysicalAddress(0x9ABC),
669        },
670        bytes: [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC],
671        extra: [Overfull, Empty],
672    }
673
674    #[test]
675    fn test_decoding_missing_byte() {
676        assert_eq!(
677            Message::try_from_bytes(&[
678                Opcode::HecRequestDeactivation as u8,
679                0x12,
680                0x34,
681                0x56,
682                0x78,
683                0x9A
684            ]),
685            Err(Error::OutOfRange {
686                expected: Range::AtLeast(7),
687                got: 6,
688                quantity: "bytes",
689            })
690        );
691    }
692
693    #[test]
694    fn test_decoding_missing_operand_1() {
695        assert_eq!(
696            Message::try_from_bytes(&[
697                Opcode::HecRequestDeactivation as u8,
698                0x12,
699                0x34,
700                0x56,
701                0x78
702            ]),
703            Err(Error::OutOfRange {
704                expected: Range::AtLeast(7),
705                got: 5,
706                quantity: "bytes",
707            })
708        );
709    }
710
711    #[test]
712    fn test_decoding_missing_operand_1_and_byte() {
713        assert_eq!(
714            Message::try_from_bytes(&[Opcode::HecRequestDeactivation as u8, 0x12, 0x34, 0x56]),
715            Err(Error::OutOfRange {
716                expected: Range::AtLeast(7),
717                got: 4,
718                quantity: "bytes",
719            })
720        );
721    }
722
723    #[test]
724    fn test_decoding_missing_operand_2() {
725        assert_eq!(
726            Message::try_from_bytes(&[Opcode::HecRequestDeactivation as u8, 0x12, 0x34]),
727            Err(Error::OutOfRange {
728                expected: Range::AtLeast(7),
729                got: 3,
730                quantity: "bytes",
731            })
732        );
733    }
734
735    #[test]
736    fn test_decoding_missing_operand_2_and_byte() {
737        assert_eq!(
738            Message::try_from_bytes(&[Opcode::HecRequestDeactivation as u8, 0x12]),
739            Err(Error::OutOfRange {
740                expected: Range::AtLeast(7),
741                got: 2,
742                quantity: "bytes",
743            })
744        );
745    }
746}
747
748#[cfg(test)]
749mod test_hpd_set_state {
750    use super::*;
751
752    message_test! {
753        ty: HpdSetState,
754        instance: Message::HpdSetState(InputPortHpdState::new()
755            .with_input_port(0xA)
756            .with_state(HpdState::EdidDisableEnable)),
757        bytes: [0xA5],
758        extra: [Overfull, Empty],
759    }
760}
761
762#[cfg(test)]
763mod test_hpd_report_state {
764    use super::*;
765
766    message_test! {
767        ty: HpdReportState,
768        instance: Message::HpdReportState(HpdStateErrorCode::new()
769            .with_state(HpdState::EdidDisableEnable)
770            .with_error_code(HpdErrorCode::InitiatorNotCapable)),
771        bytes: [0x51],
772        extra: [Overfull, Empty],
773    }
774}