Struct CecDevice

Source
pub struct CecDevice(/* private fields */);
Expand description

A handle on a CEC device.

Implementations§

Source§

impl CecDevice

Source

pub fn open<P: AsRef<Path>>(path: P) -> Result<Self>

Open a CEC device. Typically /dev/cecX

let cec = CecDevice::open("/dev/cec0")?;
Examples found in repository?
examples/monitor.rs (line 10)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas();
12    println!("capas  {:?}", capas);
13    cec.set_mode(CecModeInitiator::None, CecModeFollower::Monitor)?;
14
15    loop {
16        let f = cec.poll(
17            PollFlags::POLLIN | PollFlags::POLLRDNORM | PollFlags::POLLPRI,
18            PollTimeout::NONE,
19        )?;
20
21        if f.intersects(PollFlags::POLLPRI) {
22            let evt = cec.get_event()?;
23            println!("evt {:x?}", evt);
24        }
25        if f.contains(PollFlags::POLLIN | PollFlags::POLLRDNORM) {
26            let msg = cec.rec()?;
27
28            if msg.is_ok() {
29                match (msg.initiator(), msg.destination(), msg.opcode()) {
30                    (i, d, Some(Ok(o))) => {
31                        println!("msg {:?}->{:?} {:?} {:x?}", i, d, o, msg.parameters());
32                    }
33                    _ => println!("msg {:x?}", msg),
34                }
35            } else {
36                println!("msg {:x?}", msg);
37            }
38        }
39    }
40}
More examples
Hide additional examples
examples/switch_power.rs (line 10)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas()?;
12    println!("capas  {:?}", capas);
13
14    // clear existing logical addresses
15    let log = CecLogAddrs::default();
16    cec.set_log(log)?;
17
18    // set new address (PLAYBACK)
19    let log = CecLogAddrs::new(
20        VendorID::NONE,
21        Version::V1_4,
22        "pi4".to_string().try_into().unwrap(),
23        &[CecPrimDevType::PLAYBACK],
24        &[CecLogAddrType::PLAYBACK],
25    );
26    cec.set_log(log)?;
27
28    // ask Audiosystem to turn on (from standby)
29    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Audiosystem)?;
30
31    sleep(Duration::from_millis(10000));
32
33    // ask Audiosystem to switch to standby
34    cec.transmit(
35        CecLogicalAddress::Playback2,
36        CecLogicalAddress::Audiosystem,
37        CecOpcode::Standby,
38    )?;
39
40    sleep(Duration::from_millis(10000));
41
42    // ask TV to turn on
43    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Tv)?;
44
45    sleep(Duration::from_millis(10000));
46
47    // ask TV to switch to standby
48    cec.transmit(
49        CecLogicalAddress::Playback2,
50        CecLogicalAddress::Tv,
51        CecOpcode::Standby,
52    )?;
53
54    Ok(())
55}
examples/pass.rs (line 9)
8fn main() -> std::io::Result<()> {
9    let cec = CecDevice::open("/dev/cec0")?;
10
11    cec.set_mode(CecModeInitiator::Send, CecModeFollower::ExclusivePassthru)?;
12
13    let physical_addr = cec.get_phys()?;
14
15    loop {
16        let msg = cec.rec()?;
17        match msg.opcode() {
18            Some(Ok(CecOpcode::ActiveSource))
19            | Some(Ok(CecOpcode::RoutingInformation))
20            | Some(Ok(CecOpcode::SetStreamPath))
21                if physical_addr == msg.parameters() =>
22            {
23                // this is not done by the core
24                println!("THIS IS US {:?}", msg.opcode().unwrap().unwrap());
25                cec.transmit_data(
26                    CecLogicalAddress::Playback2,
27                    CecLogicalAddress::UnregisteredBroadcast,
28                    CecOpcode::ActiveSource,
29                    &physical_addr.to_bytes(),
30                )?;
31            }
32            Some(Ok(CecOpcode::ReportPhysicalAddr)) => {} //core is still taking care of that
33            Some(Ok(opcode)) if msg.destination() == CecLogicalAddress::UnregisteredBroadcast => {
34                //dont answer brodcasts
35                println!(
36                    "{:?}: {:?} {:x?}",
37                    msg.initiator(),
38                    opcode,
39                    msg.parameters()
40                );
41            }
42            Some(Ok(CecOpcode::GetCecVersion)) => {
43                cec.transmit_data(
44                    msg.destination(),
45                    msg.initiator(),
46                    CecOpcode::CecVersion,
47                    &[Version::V1_3A.into()],
48                )?;
49            }
50            Some(Ok(CecOpcode::GiveDeviceVendorId)) => {
51                cec.transmit_data(
52                    msg.destination(),
53                    msg.initiator(),
54                    CecOpcode::FeatureAbort,
55                    &[
56                        CecOpcode::GiveDeviceVendorId.into(),
57                        CecAbortReason::Unrecognized.into(),
58                    ],
59                )?; /*
60                    cec.transmit_data(
61                        msg.destination(),
62                        msg.initiator(),
63                        CecOpcode::DeviceVendorId,
64                    &[0,0,0])?;*/
65            }
66            Some(Ok(CecOpcode::Abort)) => {
67                cec.transmit_data(
68                    msg.destination(),
69                    msg.initiator(),
70                    CecOpcode::FeatureAbort,
71                    &[CecOpcode::Abort.into(), CecAbortReason::Other.into()],
72                )?;
73            }
74            Some(Ok(CecOpcode::GivePhysicalAddr)) => {
75                let l = cec.get_log()?;
76                let mut addr = Vec::with_capacity(3);
77                if let Some(log) = l.addresses().first() {
78                    addr.extend_from_slice(&physical_addr.to_bytes());
79                    addr.push((*log).into());
80
81                    cec.transmit_data(
82                        msg.destination(),
83                        msg.initiator(),
84                        CecOpcode::ReportPhysicalAddr,
85                        &addr,
86                    )?;
87                } //else no address yet?!?!?
88            }
89            Some(Ok(CecOpcode::GiveOsdName)) => {
90                cec.transmit_data(
91                    msg.destination(),
92                    msg.initiator(),
93                    CecOpcode::SetOsdName,
94                    b"pi4",
95                )?;
96            }
97            Some(Ok(CecOpcode::GiveDevicePowerStatus)) => {
98                cec.transmit_data(
99                    msg.destination(),
100                    msg.initiator(),
101                    CecOpcode::ReportPowerStatus,
102                    &[CecPowerStatus::On.into()],
103                )?;
104            }
105            Some(Ok(CecOpcode::GiveFeatures)) => {}
106            Some(Ok(opcode)) => {
107                println!(
108                    "{:?} -> {:?} : {:?} {:x?}",
109                    msg.initiator(),
110                    msg.destination(),
111                    opcode,
112                    msg.parameters()
113                );
114            }
115            _ => {
116                println!("{:?}", msg);
117            }
118        }
119    }
120}
Source

pub fn poll<T: Into<PollTimeout>>( &self, events: PollFlags, timeout: T, ) -> Result<PollFlags>

Available on crate feature poll only.

Poll for

  1. newly received Messages (POLLIN and POLLRDNORM flags)
  2. room in the transmit queue (POLLOUT and POLLWRNORM flags)
  3. events in the event queue (POLLPRI flag)

Specifying a PollTimeout::NONE in timeout means an infinite timeout. Specifying a timeout of PollTimeout::ZERO causes poll() to return immediately, even if no file descriptors are ready.

You might want to look into polling multiple file descriptors at once by using CecDevice::as_raw_fd or tokio::AsyncCec.

Examples found in repository?
examples/monitor.rs (lines 16-19)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas();
12    println!("capas  {:?}", capas);
13    cec.set_mode(CecModeInitiator::None, CecModeFollower::Monitor)?;
14
15    loop {
16        let f = cec.poll(
17            PollFlags::POLLIN | PollFlags::POLLRDNORM | PollFlags::POLLPRI,
18            PollTimeout::NONE,
19        )?;
20
21        if f.intersects(PollFlags::POLLPRI) {
22            let evt = cec.get_event()?;
23            println!("evt {:x?}", evt);
24        }
25        if f.contains(PollFlags::POLLIN | PollFlags::POLLRDNORM) {
26            let msg = cec.rec()?;
27
28            if msg.is_ok() {
29                match (msg.initiator(), msg.destination(), msg.opcode()) {
30                    (i, d, Some(Ok(o))) => {
31                        println!("msg {:?}->{:?} {:?} {:x?}", i, d, o, msg.parameters());
32                    }
33                    _ => println!("msg {:x?}", msg),
34                }
35            } else {
36                println!("msg {:x?}", msg);
37            }
38        }
39    }
40}
Source

pub fn get_capas(&self) -> Result<CecCaps>

query information on the devices capabilities. See CecCaps

Examples found in repository?
examples/monitor.rs (line 11)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas();
12    println!("capas  {:?}", capas);
13    cec.set_mode(CecModeInitiator::None, CecModeFollower::Monitor)?;
14
15    loop {
16        let f = cec.poll(
17            PollFlags::POLLIN | PollFlags::POLLRDNORM | PollFlags::POLLPRI,
18            PollTimeout::NONE,
19        )?;
20
21        if f.intersects(PollFlags::POLLPRI) {
22            let evt = cec.get_event()?;
23            println!("evt {:x?}", evt);
24        }
25        if f.contains(PollFlags::POLLIN | PollFlags::POLLRDNORM) {
26            let msg = cec.rec()?;
27
28            if msg.is_ok() {
29                match (msg.initiator(), msg.destination(), msg.opcode()) {
30                    (i, d, Some(Ok(o))) => {
31                        println!("msg {:?}->{:?} {:?} {:x?}", i, d, o, msg.parameters());
32                    }
33                    _ => println!("msg {:x?}", msg),
34                }
35            } else {
36                println!("msg {:x?}", msg);
37            }
38        }
39    }
40}
More examples
Hide additional examples
examples/switch_power.rs (line 11)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas()?;
12    println!("capas  {:?}", capas);
13
14    // clear existing logical addresses
15    let log = CecLogAddrs::default();
16    cec.set_log(log)?;
17
18    // set new address (PLAYBACK)
19    let log = CecLogAddrs::new(
20        VendorID::NONE,
21        Version::V1_4,
22        "pi4".to_string().try_into().unwrap(),
23        &[CecPrimDevType::PLAYBACK],
24        &[CecLogAddrType::PLAYBACK],
25    );
26    cec.set_log(log)?;
27
28    // ask Audiosystem to turn on (from standby)
29    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Audiosystem)?;
30
31    sleep(Duration::from_millis(10000));
32
33    // ask Audiosystem to switch to standby
34    cec.transmit(
35        CecLogicalAddress::Playback2,
36        CecLogicalAddress::Audiosystem,
37        CecOpcode::Standby,
38    )?;
39
40    sleep(Duration::from_millis(10000));
41
42    // ask TV to turn on
43    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Tv)?;
44
45    sleep(Duration::from_millis(10000));
46
47    // ask TV to switch to standby
48    cec.transmit(
49        CecLogicalAddress::Playback2,
50        CecLogicalAddress::Tv,
51        CecOpcode::Standby,
52    )?;
53
54    Ok(())
55}
Source

pub fn set_mode( &self, initiator: CecModeInitiator, follower: CecModeFollower, ) -> Result<()>

Change this handles mode.

By default any filehandle can use RECEIVE and TRANSMIT. This sets initiator and/or follower mode which can be exclusive depending on the chosen mode.
The initiator is the filehandle that is used to initiate messages, i.e. it commands other CEC devices.
The follower is the filehandle that receives messages sent to the CEC adapter and processes them.
The CEC framework will process core messages unless requested otherwise by the follower.

Examples found in repository?
examples/monitor.rs (line 13)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas();
12    println!("capas  {:?}", capas);
13    cec.set_mode(CecModeInitiator::None, CecModeFollower::Monitor)?;
14
15    loop {
16        let f = cec.poll(
17            PollFlags::POLLIN | PollFlags::POLLRDNORM | PollFlags::POLLPRI,
18            PollTimeout::NONE,
19        )?;
20
21        if f.intersects(PollFlags::POLLPRI) {
22            let evt = cec.get_event()?;
23            println!("evt {:x?}", evt);
24        }
25        if f.contains(PollFlags::POLLIN | PollFlags::POLLRDNORM) {
26            let msg = cec.rec()?;
27
28            if msg.is_ok() {
29                match (msg.initiator(), msg.destination(), msg.opcode()) {
30                    (i, d, Some(Ok(o))) => {
31                        println!("msg {:?}->{:?} {:?} {:x?}", i, d, o, msg.parameters());
32                    }
33                    _ => println!("msg {:x?}", msg),
34                }
35            } else {
36                println!("msg {:x?}", msg);
37            }
38        }
39    }
40}
More examples
Hide additional examples
examples/pass.rs (line 11)
8fn main() -> std::io::Result<()> {
9    let cec = CecDevice::open("/dev/cec0")?;
10
11    cec.set_mode(CecModeInitiator::Send, CecModeFollower::ExclusivePassthru)?;
12
13    let physical_addr = cec.get_phys()?;
14
15    loop {
16        let msg = cec.rec()?;
17        match msg.opcode() {
18            Some(Ok(CecOpcode::ActiveSource))
19            | Some(Ok(CecOpcode::RoutingInformation))
20            | Some(Ok(CecOpcode::SetStreamPath))
21                if physical_addr == msg.parameters() =>
22            {
23                // this is not done by the core
24                println!("THIS IS US {:?}", msg.opcode().unwrap().unwrap());
25                cec.transmit_data(
26                    CecLogicalAddress::Playback2,
27                    CecLogicalAddress::UnregisteredBroadcast,
28                    CecOpcode::ActiveSource,
29                    &physical_addr.to_bytes(),
30                )?;
31            }
32            Some(Ok(CecOpcode::ReportPhysicalAddr)) => {} //core is still taking care of that
33            Some(Ok(opcode)) if msg.destination() == CecLogicalAddress::UnregisteredBroadcast => {
34                //dont answer brodcasts
35                println!(
36                    "{:?}: {:?} {:x?}",
37                    msg.initiator(),
38                    opcode,
39                    msg.parameters()
40                );
41            }
42            Some(Ok(CecOpcode::GetCecVersion)) => {
43                cec.transmit_data(
44                    msg.destination(),
45                    msg.initiator(),
46                    CecOpcode::CecVersion,
47                    &[Version::V1_3A.into()],
48                )?;
49            }
50            Some(Ok(CecOpcode::GiveDeviceVendorId)) => {
51                cec.transmit_data(
52                    msg.destination(),
53                    msg.initiator(),
54                    CecOpcode::FeatureAbort,
55                    &[
56                        CecOpcode::GiveDeviceVendorId.into(),
57                        CecAbortReason::Unrecognized.into(),
58                    ],
59                )?; /*
60                    cec.transmit_data(
61                        msg.destination(),
62                        msg.initiator(),
63                        CecOpcode::DeviceVendorId,
64                    &[0,0,0])?;*/
65            }
66            Some(Ok(CecOpcode::Abort)) => {
67                cec.transmit_data(
68                    msg.destination(),
69                    msg.initiator(),
70                    CecOpcode::FeatureAbort,
71                    &[CecOpcode::Abort.into(), CecAbortReason::Other.into()],
72                )?;
73            }
74            Some(Ok(CecOpcode::GivePhysicalAddr)) => {
75                let l = cec.get_log()?;
76                let mut addr = Vec::with_capacity(3);
77                if let Some(log) = l.addresses().first() {
78                    addr.extend_from_slice(&physical_addr.to_bytes());
79                    addr.push((*log).into());
80
81                    cec.transmit_data(
82                        msg.destination(),
83                        msg.initiator(),
84                        CecOpcode::ReportPhysicalAddr,
85                        &addr,
86                    )?;
87                } //else no address yet?!?!?
88            }
89            Some(Ok(CecOpcode::GiveOsdName)) => {
90                cec.transmit_data(
91                    msg.destination(),
92                    msg.initiator(),
93                    CecOpcode::SetOsdName,
94                    b"pi4",
95                )?;
96            }
97            Some(Ok(CecOpcode::GiveDevicePowerStatus)) => {
98                cec.transmit_data(
99                    msg.destination(),
100                    msg.initiator(),
101                    CecOpcode::ReportPowerStatus,
102                    &[CecPowerStatus::On.into()],
103                )?;
104            }
105            Some(Ok(CecOpcode::GiveFeatures)) => {}
106            Some(Ok(opcode)) => {
107                println!(
108                    "{:?} -> {:?} : {:?} {:x?}",
109                    msg.initiator(),
110                    msg.destination(),
111                    opcode,
112                    msg.parameters()
113                );
114            }
115            _ => {
116                println!("{:?}", msg);
117            }
118        }
119    }
120}
Source

pub fn get_mode(&self) -> Result<(CecModeInitiator, CecModeFollower)>

Source

pub fn set_phys(&self, addr: CecPhysicalAddress) -> Result<()>

Set the physical address of the adapter.

Only available if Capabilities::PHYS_ADDR is set. May not be available if that is handled internally. Not possible with CecModeInitiator::None.

To clear an existing physical address use CecPhysicalAddress::INVALID. The adapter will go to the unconfigured state.
If logical address types have been defined (see CecDevice::set_log), then it will block until all requested logical addresses have been claimed. If the file descriptor is in non-blocking mode then it will not wait for the logical addresses to be claimed, instead it just returns.

A CecEvent::StateChange event is sent when the physical address changes.

Source

pub fn get_phys(&self) -> Result<CecPhysicalAddress>

Query physical addresses If nothing is connected, then phys_addr is CecPhysicalAddress::INVALID.

Examples found in repository?
examples/pass.rs (line 13)
8fn main() -> std::io::Result<()> {
9    let cec = CecDevice::open("/dev/cec0")?;
10
11    cec.set_mode(CecModeInitiator::Send, CecModeFollower::ExclusivePassthru)?;
12
13    let physical_addr = cec.get_phys()?;
14
15    loop {
16        let msg = cec.rec()?;
17        match msg.opcode() {
18            Some(Ok(CecOpcode::ActiveSource))
19            | Some(Ok(CecOpcode::RoutingInformation))
20            | Some(Ok(CecOpcode::SetStreamPath))
21                if physical_addr == msg.parameters() =>
22            {
23                // this is not done by the core
24                println!("THIS IS US {:?}", msg.opcode().unwrap().unwrap());
25                cec.transmit_data(
26                    CecLogicalAddress::Playback2,
27                    CecLogicalAddress::UnregisteredBroadcast,
28                    CecOpcode::ActiveSource,
29                    &physical_addr.to_bytes(),
30                )?;
31            }
32            Some(Ok(CecOpcode::ReportPhysicalAddr)) => {} //core is still taking care of that
33            Some(Ok(opcode)) if msg.destination() == CecLogicalAddress::UnregisteredBroadcast => {
34                //dont answer brodcasts
35                println!(
36                    "{:?}: {:?} {:x?}",
37                    msg.initiator(),
38                    opcode,
39                    msg.parameters()
40                );
41            }
42            Some(Ok(CecOpcode::GetCecVersion)) => {
43                cec.transmit_data(
44                    msg.destination(),
45                    msg.initiator(),
46                    CecOpcode::CecVersion,
47                    &[Version::V1_3A.into()],
48                )?;
49            }
50            Some(Ok(CecOpcode::GiveDeviceVendorId)) => {
51                cec.transmit_data(
52                    msg.destination(),
53                    msg.initiator(),
54                    CecOpcode::FeatureAbort,
55                    &[
56                        CecOpcode::GiveDeviceVendorId.into(),
57                        CecAbortReason::Unrecognized.into(),
58                    ],
59                )?; /*
60                    cec.transmit_data(
61                        msg.destination(),
62                        msg.initiator(),
63                        CecOpcode::DeviceVendorId,
64                    &[0,0,0])?;*/
65            }
66            Some(Ok(CecOpcode::Abort)) => {
67                cec.transmit_data(
68                    msg.destination(),
69                    msg.initiator(),
70                    CecOpcode::FeatureAbort,
71                    &[CecOpcode::Abort.into(), CecAbortReason::Other.into()],
72                )?;
73            }
74            Some(Ok(CecOpcode::GivePhysicalAddr)) => {
75                let l = cec.get_log()?;
76                let mut addr = Vec::with_capacity(3);
77                if let Some(log) = l.addresses().first() {
78                    addr.extend_from_slice(&physical_addr.to_bytes());
79                    addr.push((*log).into());
80
81                    cec.transmit_data(
82                        msg.destination(),
83                        msg.initiator(),
84                        CecOpcode::ReportPhysicalAddr,
85                        &addr,
86                    )?;
87                } //else no address yet?!?!?
88            }
89            Some(Ok(CecOpcode::GiveOsdName)) => {
90                cec.transmit_data(
91                    msg.destination(),
92                    msg.initiator(),
93                    CecOpcode::SetOsdName,
94                    b"pi4",
95                )?;
96            }
97            Some(Ok(CecOpcode::GiveDevicePowerStatus)) => {
98                cec.transmit_data(
99                    msg.destination(),
100                    msg.initiator(),
101                    CecOpcode::ReportPowerStatus,
102                    &[CecPowerStatus::On.into()],
103                )?;
104            }
105            Some(Ok(CecOpcode::GiveFeatures)) => {}
106            Some(Ok(opcode)) => {
107                println!(
108                    "{:?} -> {:?} : {:?} {:x?}",
109                    msg.initiator(),
110                    msg.destination(),
111                    opcode,
112                    msg.parameters()
113                );
114            }
115            _ => {
116                println!("{:?}", msg);
117            }
118        }
119    }
120}
Source

pub fn set_log(&self, log: CecLogAddrs) -> Result<()>

Set logical address.

Only available if Capabilities::LOG_ADDRS is set. Not possible with CecModeInitiator::None.

To clear existing logical addresses set CecLogAddrs::default(). The adapter will go to the unconfigured state. Attempting to call set_log when logical address types are already defined will return with error EBUSY.

If the physical address is valid (see CecDevice::set_phys), then it will block until all requested logical addresses have been claimed. If the file descriptor is in non-blocking mode then it will not wait for the logical addresses to be claimed, instead it just returns.

A CecEvent::StateChange event is sent when the logical addresses are claimed or cleared.

Examples found in repository?
examples/switch_power.rs (line 16)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas()?;
12    println!("capas  {:?}", capas);
13
14    // clear existing logical addresses
15    let log = CecLogAddrs::default();
16    cec.set_log(log)?;
17
18    // set new address (PLAYBACK)
19    let log = CecLogAddrs::new(
20        VendorID::NONE,
21        Version::V1_4,
22        "pi4".to_string().try_into().unwrap(),
23        &[CecPrimDevType::PLAYBACK],
24        &[CecLogAddrType::PLAYBACK],
25    );
26    cec.set_log(log)?;
27
28    // ask Audiosystem to turn on (from standby)
29    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Audiosystem)?;
30
31    sleep(Duration::from_millis(10000));
32
33    // ask Audiosystem to switch to standby
34    cec.transmit(
35        CecLogicalAddress::Playback2,
36        CecLogicalAddress::Audiosystem,
37        CecOpcode::Standby,
38    )?;
39
40    sleep(Duration::from_millis(10000));
41
42    // ask TV to turn on
43    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Tv)?;
44
45    sleep(Duration::from_millis(10000));
46
47    // ask TV to switch to standby
48    cec.transmit(
49        CecLogicalAddress::Playback2,
50        CecLogicalAddress::Tv,
51        CecOpcode::Standby,
52    )?;
53
54    Ok(())
55}
Source

pub fn get_log(&self) -> Result<CecLogAddrs>

Query logical addresses

Examples found in repository?
examples/pass.rs (line 75)
8fn main() -> std::io::Result<()> {
9    let cec = CecDevice::open("/dev/cec0")?;
10
11    cec.set_mode(CecModeInitiator::Send, CecModeFollower::ExclusivePassthru)?;
12
13    let physical_addr = cec.get_phys()?;
14
15    loop {
16        let msg = cec.rec()?;
17        match msg.opcode() {
18            Some(Ok(CecOpcode::ActiveSource))
19            | Some(Ok(CecOpcode::RoutingInformation))
20            | Some(Ok(CecOpcode::SetStreamPath))
21                if physical_addr == msg.parameters() =>
22            {
23                // this is not done by the core
24                println!("THIS IS US {:?}", msg.opcode().unwrap().unwrap());
25                cec.transmit_data(
26                    CecLogicalAddress::Playback2,
27                    CecLogicalAddress::UnregisteredBroadcast,
28                    CecOpcode::ActiveSource,
29                    &physical_addr.to_bytes(),
30                )?;
31            }
32            Some(Ok(CecOpcode::ReportPhysicalAddr)) => {} //core is still taking care of that
33            Some(Ok(opcode)) if msg.destination() == CecLogicalAddress::UnregisteredBroadcast => {
34                //dont answer brodcasts
35                println!(
36                    "{:?}: {:?} {:x?}",
37                    msg.initiator(),
38                    opcode,
39                    msg.parameters()
40                );
41            }
42            Some(Ok(CecOpcode::GetCecVersion)) => {
43                cec.transmit_data(
44                    msg.destination(),
45                    msg.initiator(),
46                    CecOpcode::CecVersion,
47                    &[Version::V1_3A.into()],
48                )?;
49            }
50            Some(Ok(CecOpcode::GiveDeviceVendorId)) => {
51                cec.transmit_data(
52                    msg.destination(),
53                    msg.initiator(),
54                    CecOpcode::FeatureAbort,
55                    &[
56                        CecOpcode::GiveDeviceVendorId.into(),
57                        CecAbortReason::Unrecognized.into(),
58                    ],
59                )?; /*
60                    cec.transmit_data(
61                        msg.destination(),
62                        msg.initiator(),
63                        CecOpcode::DeviceVendorId,
64                    &[0,0,0])?;*/
65            }
66            Some(Ok(CecOpcode::Abort)) => {
67                cec.transmit_data(
68                    msg.destination(),
69                    msg.initiator(),
70                    CecOpcode::FeatureAbort,
71                    &[CecOpcode::Abort.into(), CecAbortReason::Other.into()],
72                )?;
73            }
74            Some(Ok(CecOpcode::GivePhysicalAddr)) => {
75                let l = cec.get_log()?;
76                let mut addr = Vec::with_capacity(3);
77                if let Some(log) = l.addresses().first() {
78                    addr.extend_from_slice(&physical_addr.to_bytes());
79                    addr.push((*log).into());
80
81                    cec.transmit_data(
82                        msg.destination(),
83                        msg.initiator(),
84                        CecOpcode::ReportPhysicalAddr,
85                        &addr,
86                    )?;
87                } //else no address yet?!?!?
88            }
89            Some(Ok(CecOpcode::GiveOsdName)) => {
90                cec.transmit_data(
91                    msg.destination(),
92                    msg.initiator(),
93                    CecOpcode::SetOsdName,
94                    b"pi4",
95                )?;
96            }
97            Some(Ok(CecOpcode::GiveDevicePowerStatus)) => {
98                cec.transmit_data(
99                    msg.destination(),
100                    msg.initiator(),
101                    CecOpcode::ReportPowerStatus,
102                    &[CecPowerStatus::On.into()],
103                )?;
104            }
105            Some(Ok(CecOpcode::GiveFeatures)) => {}
106            Some(Ok(opcode)) => {
107                println!(
108                    "{:?} -> {:?} : {:?} {:x?}",
109                    msg.initiator(),
110                    msg.destination(),
111                    opcode,
112                    msg.parameters()
113                );
114            }
115            _ => {
116                println!("{:?}", msg);
117            }
118        }
119    }
120}
Source

pub fn get_event(&self) -> Result<CecEvent>

Examples found in repository?
examples/monitor.rs (line 22)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas();
12    println!("capas  {:?}", capas);
13    cec.set_mode(CecModeInitiator::None, CecModeFollower::Monitor)?;
14
15    loop {
16        let f = cec.poll(
17            PollFlags::POLLIN | PollFlags::POLLRDNORM | PollFlags::POLLPRI,
18            PollTimeout::NONE,
19        )?;
20
21        if f.intersects(PollFlags::POLLPRI) {
22            let evt = cec.get_event()?;
23            println!("evt {:x?}", evt);
24        }
25        if f.contains(PollFlags::POLLIN | PollFlags::POLLRDNORM) {
26            let msg = cec.rec()?;
27
28            if msg.is_ok() {
29                match (msg.initiator(), msg.destination(), msg.opcode()) {
30                    (i, d, Some(Ok(o))) => {
31                        println!("msg {:?}->{:?} {:?} {:x?}", i, d, o, msg.parameters());
32                    }
33                    _ => println!("msg {:x?}", msg),
34                }
35            } else {
36                println!("msg {:x?}", msg);
37            }
38        }
39    }
40}
Source

pub fn turn_on( &self, from: CecLogicalAddress, to: CecLogicalAddress, ) -> Result<()>

wake a remote cec device from standby

Examples found in repository?
examples/switch_power.rs (line 29)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas()?;
12    println!("capas  {:?}", capas);
13
14    // clear existing logical addresses
15    let log = CecLogAddrs::default();
16    cec.set_log(log)?;
17
18    // set new address (PLAYBACK)
19    let log = CecLogAddrs::new(
20        VendorID::NONE,
21        Version::V1_4,
22        "pi4".to_string().try_into().unwrap(),
23        &[CecPrimDevType::PLAYBACK],
24        &[CecLogAddrType::PLAYBACK],
25    );
26    cec.set_log(log)?;
27
28    // ask Audiosystem to turn on (from standby)
29    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Audiosystem)?;
30
31    sleep(Duration::from_millis(10000));
32
33    // ask Audiosystem to switch to standby
34    cec.transmit(
35        CecLogicalAddress::Playback2,
36        CecLogicalAddress::Audiosystem,
37        CecOpcode::Standby,
38    )?;
39
40    sleep(Duration::from_millis(10000));
41
42    // ask TV to turn on
43    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Tv)?;
44
45    sleep(Duration::from_millis(10000));
46
47    // ask TV to switch to standby
48    cec.transmit(
49        CecLogicalAddress::Playback2,
50        CecLogicalAddress::Tv,
51        CecOpcode::Standby,
52    )?;
53
54    Ok(())
55}
Source

pub fn keypress( &self, from: CecLogicalAddress, to: CecLogicalAddress, key: CecUserControlCode, ) -> Result<()>

send a button press to a remote cec device

Source

pub fn transmit( &self, from: CecLogicalAddress, to: CecLogicalAddress, opcode: CecOpcode, ) -> Result<()>

send a cec command without parameters to a remote device

transmitting from an address not in CecLogAddrMask will return InvalidInput

Examples found in repository?
examples/switch_power.rs (lines 34-38)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas()?;
12    println!("capas  {:?}", capas);
13
14    // clear existing logical addresses
15    let log = CecLogAddrs::default();
16    cec.set_log(log)?;
17
18    // set new address (PLAYBACK)
19    let log = CecLogAddrs::new(
20        VendorID::NONE,
21        Version::V1_4,
22        "pi4".to_string().try_into().unwrap(),
23        &[CecPrimDevType::PLAYBACK],
24        &[CecLogAddrType::PLAYBACK],
25    );
26    cec.set_log(log)?;
27
28    // ask Audiosystem to turn on (from standby)
29    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Audiosystem)?;
30
31    sleep(Duration::from_millis(10000));
32
33    // ask Audiosystem to switch to standby
34    cec.transmit(
35        CecLogicalAddress::Playback2,
36        CecLogicalAddress::Audiosystem,
37        CecOpcode::Standby,
38    )?;
39
40    sleep(Duration::from_millis(10000));
41
42    // ask TV to turn on
43    cec.turn_on(CecLogicalAddress::Playback2, CecLogicalAddress::Tv)?;
44
45    sleep(Duration::from_millis(10000));
46
47    // ask TV to switch to standby
48    cec.transmit(
49        CecLogicalAddress::Playback2,
50        CecLogicalAddress::Tv,
51        CecOpcode::Standby,
52    )?;
53
54    Ok(())
55}
Source

pub fn transmit_data( &self, from: CecLogicalAddress, to: CecLogicalAddress, opcode: CecOpcode, data: &[u8], ) -> Result<()>

send a cec command with parameters to a remote device. The format of data depends on the opcode.

Examples found in repository?
examples/pass.rs (lines 25-30)
8fn main() -> std::io::Result<()> {
9    let cec = CecDevice::open("/dev/cec0")?;
10
11    cec.set_mode(CecModeInitiator::Send, CecModeFollower::ExclusivePassthru)?;
12
13    let physical_addr = cec.get_phys()?;
14
15    loop {
16        let msg = cec.rec()?;
17        match msg.opcode() {
18            Some(Ok(CecOpcode::ActiveSource))
19            | Some(Ok(CecOpcode::RoutingInformation))
20            | Some(Ok(CecOpcode::SetStreamPath))
21                if physical_addr == msg.parameters() =>
22            {
23                // this is not done by the core
24                println!("THIS IS US {:?}", msg.opcode().unwrap().unwrap());
25                cec.transmit_data(
26                    CecLogicalAddress::Playback2,
27                    CecLogicalAddress::UnregisteredBroadcast,
28                    CecOpcode::ActiveSource,
29                    &physical_addr.to_bytes(),
30                )?;
31            }
32            Some(Ok(CecOpcode::ReportPhysicalAddr)) => {} //core is still taking care of that
33            Some(Ok(opcode)) if msg.destination() == CecLogicalAddress::UnregisteredBroadcast => {
34                //dont answer brodcasts
35                println!(
36                    "{:?}: {:?} {:x?}",
37                    msg.initiator(),
38                    opcode,
39                    msg.parameters()
40                );
41            }
42            Some(Ok(CecOpcode::GetCecVersion)) => {
43                cec.transmit_data(
44                    msg.destination(),
45                    msg.initiator(),
46                    CecOpcode::CecVersion,
47                    &[Version::V1_3A.into()],
48                )?;
49            }
50            Some(Ok(CecOpcode::GiveDeviceVendorId)) => {
51                cec.transmit_data(
52                    msg.destination(),
53                    msg.initiator(),
54                    CecOpcode::FeatureAbort,
55                    &[
56                        CecOpcode::GiveDeviceVendorId.into(),
57                        CecAbortReason::Unrecognized.into(),
58                    ],
59                )?; /*
60                    cec.transmit_data(
61                        msg.destination(),
62                        msg.initiator(),
63                        CecOpcode::DeviceVendorId,
64                    &[0,0,0])?;*/
65            }
66            Some(Ok(CecOpcode::Abort)) => {
67                cec.transmit_data(
68                    msg.destination(),
69                    msg.initiator(),
70                    CecOpcode::FeatureAbort,
71                    &[CecOpcode::Abort.into(), CecAbortReason::Other.into()],
72                )?;
73            }
74            Some(Ok(CecOpcode::GivePhysicalAddr)) => {
75                let l = cec.get_log()?;
76                let mut addr = Vec::with_capacity(3);
77                if let Some(log) = l.addresses().first() {
78                    addr.extend_from_slice(&physical_addr.to_bytes());
79                    addr.push((*log).into());
80
81                    cec.transmit_data(
82                        msg.destination(),
83                        msg.initiator(),
84                        CecOpcode::ReportPhysicalAddr,
85                        &addr,
86                    )?;
87                } //else no address yet?!?!?
88            }
89            Some(Ok(CecOpcode::GiveOsdName)) => {
90                cec.transmit_data(
91                    msg.destination(),
92                    msg.initiator(),
93                    CecOpcode::SetOsdName,
94                    b"pi4",
95                )?;
96            }
97            Some(Ok(CecOpcode::GiveDevicePowerStatus)) => {
98                cec.transmit_data(
99                    msg.destination(),
100                    msg.initiator(),
101                    CecOpcode::ReportPowerStatus,
102                    &[CecPowerStatus::On.into()],
103                )?;
104            }
105            Some(Ok(CecOpcode::GiveFeatures)) => {}
106            Some(Ok(opcode)) => {
107                println!(
108                    "{:?} -> {:?} : {:?} {:x?}",
109                    msg.initiator(),
110                    msg.destination(),
111                    opcode,
112                    msg.parameters()
113                );
114            }
115            _ => {
116                println!("{:?}", msg);
117            }
118        }
119    }
120}
Source

pub fn request_data( &self, from: CecLogicalAddress, to: CecLogicalAddress, opcode: CecOpcode, data: &[u8], wait_for: CecOpcode, ) -> Result<Vec<u8>>

send a cec command with parameters and wait for a reply with opcode wait_for. Then return its payload. returns timeout if no reply is received

if let Ok(audio) = cec.request_data(CecLogicalAddress::Playback2, CecLogicalAddress::Audiosystem, CecOpcode::GiveAudioStatus, b"", CecOpcode::ReportAudioStatus){
   let v = audio[0];
   println!("Muted: {}", v & 0x80);
   println!("Vol: {}%", v & 0x7f);
}
Source

pub fn rec(&self) -> Result<CecMsg>

receive a single message. block forever the available messages depend on CecModeFollower

Examples found in repository?
examples/monitor.rs (line 26)
9fn main() -> std::io::Result<()> {
10    let cec = CecDevice::open("/dev/cec0")?;
11    let capas = cec.get_capas();
12    println!("capas  {:?}", capas);
13    cec.set_mode(CecModeInitiator::None, CecModeFollower::Monitor)?;
14
15    loop {
16        let f = cec.poll(
17            PollFlags::POLLIN | PollFlags::POLLRDNORM | PollFlags::POLLPRI,
18            PollTimeout::NONE,
19        )?;
20
21        if f.intersects(PollFlags::POLLPRI) {
22            let evt = cec.get_event()?;
23            println!("evt {:x?}", evt);
24        }
25        if f.contains(PollFlags::POLLIN | PollFlags::POLLRDNORM) {
26            let msg = cec.rec()?;
27
28            if msg.is_ok() {
29                match (msg.initiator(), msg.destination(), msg.opcode()) {
30                    (i, d, Some(Ok(o))) => {
31                        println!("msg {:?}->{:?} {:?} {:x?}", i, d, o, msg.parameters());
32                    }
33                    _ => println!("msg {:x?}", msg),
34                }
35            } else {
36                println!("msg {:x?}", msg);
37            }
38        }
39    }
40}
More examples
Hide additional examples
examples/pass.rs (line 16)
8fn main() -> std::io::Result<()> {
9    let cec = CecDevice::open("/dev/cec0")?;
10
11    cec.set_mode(CecModeInitiator::Send, CecModeFollower::ExclusivePassthru)?;
12
13    let physical_addr = cec.get_phys()?;
14
15    loop {
16        let msg = cec.rec()?;
17        match msg.opcode() {
18            Some(Ok(CecOpcode::ActiveSource))
19            | Some(Ok(CecOpcode::RoutingInformation))
20            | Some(Ok(CecOpcode::SetStreamPath))
21                if physical_addr == msg.parameters() =>
22            {
23                // this is not done by the core
24                println!("THIS IS US {:?}", msg.opcode().unwrap().unwrap());
25                cec.transmit_data(
26                    CecLogicalAddress::Playback2,
27                    CecLogicalAddress::UnregisteredBroadcast,
28                    CecOpcode::ActiveSource,
29                    &physical_addr.to_bytes(),
30                )?;
31            }
32            Some(Ok(CecOpcode::ReportPhysicalAddr)) => {} //core is still taking care of that
33            Some(Ok(opcode)) if msg.destination() == CecLogicalAddress::UnregisteredBroadcast => {
34                //dont answer brodcasts
35                println!(
36                    "{:?}: {:?} {:x?}",
37                    msg.initiator(),
38                    opcode,
39                    msg.parameters()
40                );
41            }
42            Some(Ok(CecOpcode::GetCecVersion)) => {
43                cec.transmit_data(
44                    msg.destination(),
45                    msg.initiator(),
46                    CecOpcode::CecVersion,
47                    &[Version::V1_3A.into()],
48                )?;
49            }
50            Some(Ok(CecOpcode::GiveDeviceVendorId)) => {
51                cec.transmit_data(
52                    msg.destination(),
53                    msg.initiator(),
54                    CecOpcode::FeatureAbort,
55                    &[
56                        CecOpcode::GiveDeviceVendorId.into(),
57                        CecAbortReason::Unrecognized.into(),
58                    ],
59                )?; /*
60                    cec.transmit_data(
61                        msg.destination(),
62                        msg.initiator(),
63                        CecOpcode::DeviceVendorId,
64                    &[0,0,0])?;*/
65            }
66            Some(Ok(CecOpcode::Abort)) => {
67                cec.transmit_data(
68                    msg.destination(),
69                    msg.initiator(),
70                    CecOpcode::FeatureAbort,
71                    &[CecOpcode::Abort.into(), CecAbortReason::Other.into()],
72                )?;
73            }
74            Some(Ok(CecOpcode::GivePhysicalAddr)) => {
75                let l = cec.get_log()?;
76                let mut addr = Vec::with_capacity(3);
77                if let Some(log) = l.addresses().first() {
78                    addr.extend_from_slice(&physical_addr.to_bytes());
79                    addr.push((*log).into());
80
81                    cec.transmit_data(
82                        msg.destination(),
83                        msg.initiator(),
84                        CecOpcode::ReportPhysicalAddr,
85                        &addr,
86                    )?;
87                } //else no address yet?!?!?
88            }
89            Some(Ok(CecOpcode::GiveOsdName)) => {
90                cec.transmit_data(
91                    msg.destination(),
92                    msg.initiator(),
93                    CecOpcode::SetOsdName,
94                    b"pi4",
95                )?;
96            }
97            Some(Ok(CecOpcode::GiveDevicePowerStatus)) => {
98                cec.transmit_data(
99                    msg.destination(),
100                    msg.initiator(),
101                    CecOpcode::ReportPowerStatus,
102                    &[CecPowerStatus::On.into()],
103                )?;
104            }
105            Some(Ok(CecOpcode::GiveFeatures)) => {}
106            Some(Ok(opcode)) => {
107                println!(
108                    "{:?} -> {:?} : {:?} {:x?}",
109                    msg.initiator(),
110                    msg.destination(),
111                    opcode,
112                    msg.parameters()
113                );
114            }
115            _ => {
116                println!("{:?}", msg);
117            }
118        }
119    }
120}
Source

pub fn rec_for(&self, timeout: u32) -> Result<CecMsg>

receive a single message. block for at most timeout ms. the available messages depend on CecModeFollower

Trait Implementations§

Source§

impl AsRawFd for CecDevice

Source§

fn as_raw_fd(&self) -> RawFd

Extracts the raw file descriptor. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.