Skip to content

Commit

Permalink
fixup! Add Linux CEC Adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
Kwiboo committed Jan 1, 2019
1 parent 76b86ac commit 97d8c30
Showing 1 changed file with 48 additions and 8 deletions.
56 changes: 48 additions & 8 deletions src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* This file is part of the libCEC(R) library.
*
* libCEC Linux CEC Adapter is Copyright (C) 2017-2018 Jonas Karlman
* libCEC Linux CEC Adapter is Copyright (C) 2017-2019 Jonas Karlman
* based heavily on:
* libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs
* libCEC Exynos Code is Copyright (C) 2014 Valentin Manea
Expand Down Expand Up @@ -97,15 +97,24 @@ bool CLinuxCECAdapterCommunication::Open(uint32_t UNUSED(iTimeoutMs), bool UNUSE
return false;
}

// Clear existing logical addresses and set the CEC device to the unconfigured state
// Set logical address to unregistered, without any logical address configured no messages is transmitted or received
struct cec_log_addrs log_addrs = {};
log_addrs.cec_version = CEC_OP_CEC_VERSION_1_4;
log_addrs.vendor_id = CEC_VENDOR_PULSE_EIGHT;
log_addrs.num_log_addrs = 1;
log_addrs.log_addr[0] = CEC_LOG_ADDR_UNREGISTERED;
log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH;
log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs))
{
LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno);
Close();
return false;
}

LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs);

if (CreateThread())
return true;

Expand Down Expand Up @@ -156,7 +165,7 @@ cec_adapter_message_state CLinuxCECAdapterCommunication::Write(const cec_command

LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Write - ioctl CEC_TRANSMIT - tx_status=%02x len=%d addr=%02x opcode=%02x", msg.tx_status, msg.len, msg.msg[0], cec_msg_opcode(&msg));

// The CEC device will already make multiple transmit attempts
// The CEC driver will make re-transmission attempts
bRetry = false;

if (msg.tx_status & CEC_TX_STATUS_OK)
Expand All @@ -165,9 +174,6 @@ cec_adapter_message_state CLinuxCECAdapterCommunication::Write(const cec_command
if (msg.tx_status & CEC_TX_STATUS_NACK)
return ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;

if (msg.tx_status & CEC_TX_STATUS_ERROR)
bRetry = true;

return ADAPTER_MESSAGE_STATE_ERROR;
}

Expand All @@ -185,6 +191,19 @@ bool CLinuxCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addres
return false;
}

// Clear existing logical addresses and set the CEC device to the unconfigured state
if (log_addrs.num_log_addrs)
{
log_addrs = {};
if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs))
{
LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno);
return false;
}

LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs);
}

if (!addresses.IsEmpty())
{
// NOTE: This can only be configured when num_log_addrs > 0
Expand Down Expand Up @@ -304,6 +323,8 @@ cec_vendor_id CLinuxCECAdapterCommunication::GetVendorId(void)

void *CLinuxCECAdapterCommunication::Process(void)
{
CTimeout phys_addr_timeout;
bool phys_addr_invalid = false;
fd_set rd_fds;
fd_set ex_fds;

Expand Down Expand Up @@ -334,8 +355,21 @@ void *CLinuxCECAdapterCommunication::Process(void)

// TODO: handle ev.state_change.log_addr_mask change

if (!IsStopped() && !(ev.flags & CEC_EVENT_FL_INITIAL_STATE))
m_callback->HandlePhysicalAddressChanged(ev.state_change.phys_addr);
if (ev.state_change.phys_addr == CEC_PHYS_ADDR_INVALID)
{
// NOTE: Delay change to invalid physical address with 10 seconds because
// EDID refresh and other events may cause short periods of invalid physical address
phys_addr_timeout.Init(10000);
phys_addr_invalid = true;
}
else
{
phys_addr_invalid = false;

// TODO: delay change until after log_addr_mask may have been updated
if (!IsStopped())
m_callback->HandlePhysicalAddressChanged(ev.state_change.phys_addr);
}
}
}

Expand All @@ -356,6 +390,12 @@ void *CLinuxCECAdapterCommunication::Process(void)
}
}

if (phys_addr_invalid && !phys_addr_timeout.TimeLeft() && !IsStopped())
{
phys_addr_invalid = false;
m_callback->HandlePhysicalAddressChanged(CEC_INVALID_PHYSICAL_ADDRESS);
}

if (!IsStopped())
Sleep(5);
}
Expand Down

0 comments on commit 97d8c30

Please sign in to comment.