diff options
Diffstat (limited to 'tv')
-rw-r--r-- | tv/cec/1.0/types.hal | 2 | ||||
-rw-r--r-- | tv/cec/2.0/Android.bp | 46 | ||||
-rw-r--r-- | tv/cec/2.0/IHdmiCec.hal | 209 | ||||
-rw-r--r-- | tv/cec/2.0/IHdmiCecCallback.hal | 41 | ||||
-rw-r--r-- | tv/cec/2.0/default/Android.bp | 42 | ||||
-rw-r--r-- | tv/cec/2.0/default/HdmiCec.cpp | 421 | ||||
-rw-r--r-- | tv/cec/2.0/default/HdmiCec.h | 115 | ||||
-rw-r--r-- | tv/cec/2.0/default/OWNERS | 4 | ||||
-rw-r--r-- | tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.rc | 4 | ||||
-rw-r--r-- | tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.xml | 11 | ||||
-rw-r--r-- | tv/cec/2.0/default/service.cpp | 27 | ||||
-rw-r--r-- | tv/cec/2.0/types.hal | 548 |
12 files changed, 1470 insertions, 0 deletions
diff --git a/tv/cec/1.0/types.hal b/tv/cec/1.0/types.hal index c734c4d7a..ebe65ae9d 100644 --- a/tv/cec/1.0/types.hal +++ b/tv/cec/1.0/types.hal @@ -114,6 +114,8 @@ enum CecMessageType : int32_t { VENDOR_COMMAND_WITH_ID = 0xA0, CLEAR_EXTERNAL_TIMER = 0xA1, SET_EXTERNAL_TIMER = 0xA2, + REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3, + REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4, INITIATE_ARC = 0xC0, REPORT_ARC_INITIATED = 0xC1, REPORT_ARC_TERMINATED = 0xC2, diff --git a/tv/cec/2.0/Android.bp b/tv/cec/2.0/Android.bp new file mode 100644 index 000000000..998cb23ec --- /dev/null +++ b/tv/cec/2.0/Android.bp @@ -0,0 +1,46 @@ +// This file is autogenerated by hidl-gen -Landroidbp. + +hidl_interface { + name: "android.hardware.tv.cec@2.0", + root: "android.hardware", + vndk: { + enabled: true, + }, + srcs: [ + "types.hal", + "IHdmiCec.hal", + "IHdmiCecCallback.hal", + ], + interfaces: [ + "android.hidl.base@1.0", + "android.hidl.safe_union@1.0", + ], + types: [ + "AbortReason", + "CecAllDeviceTypeValue", + "CecDeviceFeature", + "CecDeviceInfo", + "CecDeviceType", + "CecLogicalAddress", + "CecMessage", + "CecMessageType", + "CecPowerState", + "CecRcProfile", + "CecRcProfile1", + "CecRcProfileId", + "CecRcProfileSource", + "CecTopologyEvent", + "CecTopologyEventType", + "CecUICommandCodes", + "CecVersion", + "HdmiPortInfo", + "HdmiPortType", + "HotplugEvent", + "MaxLength", + "OptionKey", + "Result", + "SendMessageResult", + ], + gen_java: true, +} + diff --git a/tv/cec/2.0/IHdmiCec.hal b/tv/cec/2.0/IHdmiCec.hal new file mode 100644 index 000000000..0723bad8c --- /dev/null +++ b/tv/cec/2.0/IHdmiCec.hal @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec@2.0; + +import IHdmiCecCallback; + +/** + * HDMI-CEC HAL interface definition. + */ +interface IHdmiCec { + /** + * Passes Primary Device Type that must be used in this system. + * + * HAL must use it to allocate logical address as specified in CEC section + * 11.3.2 of the CEC spec 2.0b. Then CEC commands addressed the given + * logical address can be filtered in. + * This method shall be able to be called up to twice to support two Primary + * Device Type as specified in CEC Table 11-8 of the CEC spec 2.0b. + * + * @param deviceType that must be used in this system. It must be a valid + * value in CecDeviceType for the call to succeed. + * @return result Result status of the operation. SUCCESS if successful, + * FAILURE_INVALID_ARGS if the given device type is invalid, + * FAILURE_BUSY if device or resource is busy + */ + @callflow(next={"*"}) + addDeviceType(CecDeviceType deviceType) generates (Result result); + + /** + * Clears all Primary Device Types. + * + * It is used when the system plan to reconfigure Primary Device Type, + * hence to tell HAL to release all logical address associated to them, + * and change the state back to the beginning. + */ + @callflow(next="addDeviceType") + @exit + clearDeviceTypes(); + + /** + * Set All Device Types for a Primary Device Type. + * + * This value must be used in REPORT_FEATURES message to response + * GIVE_FEATURES message in HAL. + * + * @param allDeviceTypes device all device types for a Primary Device Type. + */ + @callflow(next="addDeviceType") + setAllDeviceTypes(CecAllDeviceTypes allDeviceTypes); + + /** + * Set Device Features for a Primary Device Type. + * + * This value must be used in REPORT_FEATURES message to response + * GIVE_FEATURES message in HAL. + * + * @param deviceType The device Primary Device Type. + * @param deviceFeatures device features for a Primary Device Type. + */ + @callflow(next="addDeviceType") + setDeviceFeatures(CecDeviceType deviceType, + CecDeviceFeatures deviceFeatures); + + /** + * Set Remote Control Profile for a Primary Device Type. + * + * This value must be used in REPORT_FEATURES message to response + * GIVE_FEATURES message in HAL. + * + * @param deviceType The device Primary Device Type. + * @param rcProliles remote control profiles for a Primary Device Type. + */ + @callflow(next="addDeviceType") + setRcProfile(CecDeviceType deviceType, CecRcProfile rcProfile); + + /** + * Retrieve CEC device information. + * + * CEC section 11.3 of the CEC spec 2.0b specify that a device should not + * ask for static information that another device has already supplied. + * Therefore, CEC 2.0 software stack need a map to store all cec + * devices’ information of current CEC network. + * The device information is broadcasted by a device after it allocates a + * logical address. Messages used to send out these information are + * REPORT_FEATURES, REPORT_PHYSICAL_ADDRESS, DEVICE_VENDOR_ID. + * The spec also requires less than 1 second between REPORT_FEATURES and + * REPORT_PHYSICAL_ADDRESS message, and less than 2 second between + * REPORT_PHYSICAL_ADDRESS and DEVICE_VENDOR_ID. An Implementation of + * device information map in hal can help to meet the timing constraints. + * Logical addressing is part of the process to build this map, so the + * implementation shall include allocating logical address too. + * Whenever a device plug/unplug, the topology of CEC network changes. + * The hal implementation shall update devices’ information map, and + * send out onTopologyEvent to Android system. Then Android system + * will use readDeviceInfo to retreive latest devices’ information of CEC + * network. + * If SYSTEM_CEC_CONTROL is false, the hal implementation need continue to + * maintain and update device information map, and send out pending + * onTopologyEvent to Android system when SYSTEM_CEC_CONTROL is + * changed to true. + * + * @param logicalAddress logical address of CEC device. + * @param physicalAddress physical address of CEC device. + * @return CecDeviceInfo from device information map. + * @return result Result status of the operation. SUCCESS if successful, + * FAILURE_INVALID_ARGS if logical or physical address is invalid. + * FAILURE_INVALID_STATE if device information isn't available yet. + */ + @callflow(next="onTopologyChangeEvent") + readDeviceInfo(CecLogicalAddress logicalAddress, + CecPhysicalAddress physicalAddress) + generates (Result result, CecDeviceInfo deviceInfo); + + /** + * Transmits HDMI-CEC message to other HDMI device. + * + * The method must be designed to return in a certain amount of time and not + * hanging forever. This method MUST complete with in 1 second. + * + * It must try retransmission at least once as specified in the section '7.1 + * Frame Re-transmissions' of the CEC Spec 1.4b. + * + * @param message CEC message to be sent to other HDMI device. + * @return result Result status of the operation. SUCCESS if successful, + * NACK if the sent message is not acknowledged, + * BUSY if the CEC bus is busy. + */ + @callflow(next="*") + sendMessage(CecMessage message) generates (SendMessageResult result); + + /** + * Set the callback + * + * It is used by the framework to receive CecMessages, HDMI hotplug event + * and topology update event. Only one callback client is supported. + * + * @param callback Callback object to pass hdmi events to the system. The + * previously registered callback must be replaced with this one. + */ + @callflow(next={"*"}) + @entry + setCallback(IHdmiCecCallback callback); + + /** + * Gets the hdmi port information of underlying hardware. + * + * @return infos The list of HDMI port information + */ + @callflow(next={"*"}) + getPortInfo() generates (vec<HdmiPortInfo> infos); + + /** + * Sets flags controlling the way HDMI-CEC service works down to HAL + * implementation. Those flags must be used in case the feature needs update + * in HAL itself, firmware or microcontroller. + * + * @param key The key of the option to be updated with a new value. + * @param value Value to be set. + */ + @callflow(next="*") + setOption(OptionKey key, bool value); + + /** + * Passes the updated language information of Android system. Contains + * three-letter code as defined in ISO/FDIS 639-2. Must be used for HAL to + * respond to <Get Menu Language> while in standby mode. + * + * @param language Three-letter code defined in ISO/FDIS 639-2. Must be + * lowercase letters. (e.g., eng for English) + */ + @callflow(next="*") + setLanguage(string language); + + /** + * Configures ARC circuit in the hardware logic to start or stop the + * feature. + * + * @param portId Port id to be configured. + * @param enable Flag must be either true to start the feature or false to + * stop it. + */ + @callflow(next="*") + enableAudioReturnChannel(HdmiPortId portId, bool enable); + + /** + * Gets the connection status of the specified port. + * + * It's specified in CEC section 10.8 of the CEC spec 2.0b + * + * @param portId Port id to be inspected for the connection status. + * @return status True if a device is connected, otherwise false. + */ + @callflow(next="*") + isConnected(HdmiPortId portId) generates (bool connected); +}; diff --git a/tv/cec/2.0/IHdmiCecCallback.hal b/tv/cec/2.0/IHdmiCecCallback.hal new file mode 100644 index 000000000..1a8a4895c --- /dev/null +++ b/tv/cec/2.0/IHdmiCecCallback.hal @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec@2.0; + +interface IHdmiCecCallback { + /** + * The callback function that must be called by HAL implementation to notify + * the system of new CEC message arrival. + */ + oneway onCecMessage(CecMessage message); + + /** + * The callback function that must be called by HAL implementation to notify + * the system of new hotplug event. + */ + oneway onHotplugEvent(HotplugEvent event); + + /** + * The callback function must be called by HAL implementation to notify the + * system whenever CEC device information of CEC network change. + * HAL shall be ready for readDeviceInfo call before invoke this callback. + * This event is triggered by topology change of whole CEC network. It's + * different from HotplugEvent which is triggered between devices which are + * connected directly through HDMI cable. + */ + oneway onTopologyEvent(CecTopologyEvent event); +}; diff --git a/tv/cec/2.0/default/Android.bp b/tv/cec/2.0/default/Android.bp new file mode 100644 index 000000000..6e624e3e7 --- /dev/null +++ b/tv/cec/2.0/default/Android.bp @@ -0,0 +1,42 @@ +cc_library_shared { + name: "android.hardware.tv.cec@2.0-impl", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + srcs: ["HdmiCec.cpp"], + + shared_libs: [ + "libhidlbase", + "libhidltransport", + "liblog", + "libbase", + "libutils", + "libhardware", + "android.hardware.tv.cec@2.0", + ], + +} + +cc_binary { + name: "android.hardware.tv.cec@2.0-service", + vintf_fragments: ["android.hardware.tv.cec@2.0-service.xml"], + defaults: ["hidl_defaults"], + relative_install_path: "hw", + vendor: true, + init_rc: ["android.hardware.tv.cec@2.0-service.rc"], + srcs: ["service.cpp"], + + shared_libs: [ + "liblog", + "libcutils", + "libdl", + "libbase", + "libutils", + "libhardware_legacy", + "libhardware", + "libhidlbase", + "libhidltransport", + "android.hardware.tv.cec@2.0", + ], + +} diff --git a/tv/cec/2.0/default/HdmiCec.cpp b/tv/cec/2.0/default/HdmiCec.cpp new file mode 100644 index 000000000..f45171955 --- /dev/null +++ b/tv/cec/2.0/default/HdmiCec.cpp @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.cec@2.0-impl" +#include <android-base/logging.h> + +#include <hardware/hardware.h> +#include <hardware/hdmi_cec.h> +#include "HdmiCec.h" + +namespace android { +namespace hardware { +namespace tv { +namespace cec { +namespace V2_0 { +namespace implementation { + +static_assert(CEC_DEVICE_INACTIVE == static_cast<int>(CecDeviceType::INACTIVE), + "CecDeviceType::INACTIVE must match legacy value."); +static_assert(CEC_DEVICE_TV == static_cast<int>(CecDeviceType::TV), + "CecDeviceType::TV must match legacy value."); +static_assert(CEC_DEVICE_RECORDER == static_cast<int>(CecDeviceType::RECORDER), + "CecDeviceType::RECORDER must match legacy value."); +static_assert(CEC_DEVICE_TUNER == static_cast<int>(CecDeviceType::TUNER), + "CecDeviceType::TUNER must match legacy value."); +static_assert(CEC_DEVICE_PLAYBACK == static_cast<int>(CecDeviceType::PLAYBACK), + "CecDeviceType::PLAYBACK must match legacy value."); +static_assert(CEC_DEVICE_AUDIO_SYSTEM == static_cast<int>(CecDeviceType::AUDIO_SYSTEM), + "CecDeviceType::AUDIO_SYSTEM must match legacy value."); +/* TODO: Adjust for cec@2.0 +static_assert(CEC_DEVICE_MAX == static_cast<int>(CecDeviceType::MAX), + "CecDeviceType::MAX must match legacy value."); +*/ +static_assert(CEC_ADDR_TV == static_cast<int>(CecLogicalAddress::TV), + "CecLogicalAddress::TV must match legacy value."); +static_assert(CEC_ADDR_RECORDER_1 == static_cast<int>(CecLogicalAddress::RECORDER_1), + "CecLogicalAddress::RECORDER_1 must match legacy value."); +static_assert(CEC_ADDR_RECORDER_2 == static_cast<int>(CecLogicalAddress::RECORDER_2), + "CecLogicalAddress::RECORDER_2 must match legacy value."); +static_assert(CEC_ADDR_TUNER_1 == static_cast<int>(CecLogicalAddress::TUNER_1), + "CecLogicalAddress::TUNER_1 must match legacy value."); +static_assert(CEC_ADDR_PLAYBACK_1 == static_cast<int>(CecLogicalAddress::PLAYBACK_1), + "CecLogicalAddress::PLAYBACK_1 must match legacy value."); +static_assert(CEC_ADDR_AUDIO_SYSTEM == static_cast<int>(CecLogicalAddress::AUDIO_SYSTEM), + "CecLogicalAddress::AUDIO_SYSTEM must match legacy value."); +static_assert(CEC_ADDR_TUNER_2 == static_cast<int>(CecLogicalAddress::TUNER_2), + "CecLogicalAddress::TUNER_2 must match legacy value."); +static_assert(CEC_ADDR_TUNER_3 == static_cast<int>(CecLogicalAddress::TUNER_3), + "CecLogicalAddress::TUNER_3 must match legacy value."); +static_assert(CEC_ADDR_PLAYBACK_2 == static_cast<int>(CecLogicalAddress::PLAYBACK_2), + "CecLogicalAddress::PLAYBACK_2 must match legacy value."); +static_assert(CEC_ADDR_RECORDER_3 == static_cast<int>(CecLogicalAddress::RECORDER_3), + "CecLogicalAddress::RECORDER_3 must match legacy value."); +static_assert(CEC_ADDR_TUNER_4 == static_cast<int>(CecLogicalAddress::TUNER_4), + "CecLogicalAddress::TUNER_4 must match legacy value."); +static_assert(CEC_ADDR_PLAYBACK_3 == static_cast<int>(CecLogicalAddress::PLAYBACK_3), + "CecLogicalAddress::PLAYBACK_3 must match legacy value."); +/* TODO: Adjust for cec@2.0 +static_assert(CEC_ADDR_FREE_USE == static_cast<int>(CecLogicalAddress::FREE_USE), + "CecLogicalAddress::FREE_USE must match legacy value."); +*/ +static_assert(CEC_ADDR_UNREGISTERED == static_cast<int>(CecLogicalAddress::UNREGISTERED), + "CecLogicalAddress::UNREGISTERED must match legacy value."); +static_assert(CEC_ADDR_BROADCAST == static_cast<int>(CecLogicalAddress::BROADCAST), + "CecLogicalAddress::BROADCAST must match legacy value."); + +static_assert(CEC_MESSAGE_FEATURE_ABORT == static_cast<int>(CecMessageType::FEATURE_ABORT), + "CecMessageType::FEATURE_ABORT must match legacy value."); +static_assert(CEC_MESSAGE_IMAGE_VIEW_ON == static_cast<int>(CecMessageType::IMAGE_VIEW_ON), + "CecMessageType::IMAGE_VIEW_ON must match legacy value."); +static_assert(CEC_MESSAGE_TUNER_STEP_INCREMENT == + static_cast<int>(CecMessageType::TUNER_STEP_INCREMENT), + "CecMessageType::TUNER_STEP_INCREMENT must match legacy value."); +static_assert(CEC_MESSAGE_TUNER_STEP_DECREMENT == + static_cast<int>(CecMessageType::TUNER_STEP_DECREMENT), + "CecMessageType::TUNER_STEP_DECREMENT must match legacy value."); +static_assert(CEC_MESSAGE_TUNER_DEVICE_STATUS == + static_cast<int>(CecMessageType::TUNER_DEVICE_STATUS), + "CecMessageType::TUNER_DEVICE_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_TUNER_DEVICE_STATUS == + static_cast<int>(CecMessageType::GIVE_TUNER_DEVICE_STATUS), + "CecMessageType::GIVE_TUNER_DEVICE_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_RECORD_ON == static_cast<int>(CecMessageType::RECORD_ON), + "CecMessageType::RECORD_ON must match legacy value."); +static_assert(CEC_MESSAGE_RECORD_STATUS == static_cast<int>(CecMessageType::RECORD_STATUS), + "CecMessageType::RECORD_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_RECORD_OFF == static_cast<int>(CecMessageType::RECORD_OFF), + "CecMessageType::RECORD_OFF must match legacy value."); +static_assert(CEC_MESSAGE_TEXT_VIEW_ON == static_cast<int>(CecMessageType::TEXT_VIEW_ON), + "CecMessageType::TEXT_VIEW_ON must match legacy value."); +static_assert(CEC_MESSAGE_RECORD_TV_SCREEN == static_cast<int>(CecMessageType::RECORD_TV_SCREEN), + "CecMessageType::RECORD_TV_SCREEN must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_DECK_STATUS == static_cast<int>(CecMessageType::GIVE_DECK_STATUS), + "CecMessageType::GIVE_DECK_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_STANDBY == static_cast<int>(CecMessageType::STANDBY), + "CecMessageType::STANDBY must match legacy value."); +static_assert(CEC_MESSAGE_PLAY == static_cast<int>(CecMessageType::PLAY), + "CecMessageType::PLAY must match legacy value."); +static_assert(CEC_MESSAGE_DECK_CONTROL == static_cast<int>(CecMessageType::DECK_CONTROL), + "CecMessageType::DECK_CONTROL must match legacy value."); +static_assert(CEC_MESSAGE_TIMER_CLEARED_STATUS == + static_cast<int>(CecMessageType::TIMER_CLEARED_STATUS), + "CecMessageType::TIMER_CLEARED_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_USER_CONTROL_PRESSED == + static_cast<int>(CecMessageType::USER_CONTROL_PRESSED), + "CecMessageType::USER_CONTROL_PRESSED must match legacy value."); +static_assert(CEC_MESSAGE_USER_CONTROL_RELEASED == + static_cast<int>(CecMessageType::USER_CONTROL_RELEASED), + "CecMessageType::USER_CONTROL_RELEASED must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_OSD_NAME == static_cast<int>(CecMessageType::GIVE_OSD_NAME), + "CecMessageType::GIVE_OSD_NAME must match legacy value."); +static_assert(CEC_MESSAGE_SET_OSD_NAME == static_cast<int>(CecMessageType::SET_OSD_NAME), + "CecMessageType::SET_OSD_NAME must match legacy value."); +static_assert(CEC_MESSAGE_SYSTEM_AUDIO_MODE_REQUEST == + static_cast<int>(CecMessageType::SYSTEM_AUDIO_MODE_REQUEST), + "CecMessageType::SYSTEM_AUDIO_MODE_REQUEST must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_AUDIO_STATUS == static_cast<int>(CecMessageType::GIVE_AUDIO_STATUS), + "CecMessageType::GIVE_AUDIO_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_SET_SYSTEM_AUDIO_MODE == + static_cast<int>(CecMessageType::SET_SYSTEM_AUDIO_MODE), + "CecMessageType::SET_SYSTEM_AUDIO_MODE must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_AUDIO_STATUS == + static_cast<int>(CecMessageType::REPORT_AUDIO_STATUS), + "CecMessageType::REPORT_AUDIO_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS == + static_cast<int>(CecMessageType::GIVE_SYSTEM_AUDIO_MODE_STATUS), + "CecMessageType::GIVE_SYSTEM_AUDIO_MODE_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_SYSTEM_AUDIO_MODE_STATUS == + static_cast<int>(CecMessageType::SYSTEM_AUDIO_MODE_STATUS), + "CecMessageType::SYSTEM_AUDIO_MODE_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_ROUTING_CHANGE == static_cast<int>(CecMessageType::ROUTING_CHANGE), + "CecMessageType::ROUTING_CHANGE must match legacy value."); +static_assert(CEC_MESSAGE_ROUTING_INFORMATION == + static_cast<int>(CecMessageType::ROUTING_INFORMATION), + "CecMessageType::ROUTING_INFORMATION must match legacy value."); +static_assert(CEC_MESSAGE_ACTIVE_SOURCE == static_cast<int>(CecMessageType::ACTIVE_SOURCE), + "CecMessageType::ACTIVE_SOURCE must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS == + static_cast<int>(CecMessageType::GIVE_PHYSICAL_ADDRESS), + "CecMessageType::GIVE_PHYSICAL_ADDRESS must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS == + static_cast<int>(CecMessageType::REPORT_PHYSICAL_ADDRESS), + "CecMessageType::REPORT_PHYSICAL_ADDRESS must match legacy value."); +static_assert(CEC_MESSAGE_REQUEST_ACTIVE_SOURCE == + static_cast<int>(CecMessageType::REQUEST_ACTIVE_SOURCE), + "CecMessageType::REQUEST_ACTIVE_SOURCE must match legacy value."); +static_assert(CEC_MESSAGE_SET_STREAM_PATH == static_cast<int>(CecMessageType::SET_STREAM_PATH), + "CecMessageType::SET_STREAM_PATH must match legacy value."); +static_assert(CEC_MESSAGE_DEVICE_VENDOR_ID == static_cast<int>(CecMessageType::DEVICE_VENDOR_ID), + "CecMessageType::DEVICE_VENDOR_ID must match legacy value."); +static_assert(CEC_MESSAGE_VENDOR_COMMAND == static_cast<int>(CecMessageType::VENDOR_COMMAND), + "CecMessageType::VENDOR_COMMAND must match legacy value."); +static_assert(CEC_MESSAGE_VENDOR_REMOTE_BUTTON_DOWN == + static_cast<int>(CecMessageType::VENDOR_REMOTE_BUTTON_DOWN), + "CecMessageType::VENDOR_REMOTE_BUTTON_DOWN must match legacy value."); +static_assert(CEC_MESSAGE_VENDOR_REMOTE_BUTTON_UP == + static_cast<int>(CecMessageType::VENDOR_REMOTE_BUTTON_UP), + "CecMessageType::VENDOR_REMOTE_BUTTON_UP must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_DEVICE_VENDOR_ID == + static_cast<int>(CecMessageType::GIVE_DEVICE_VENDOR_ID), + "CecMessageType::GIVE_DEVICE_VENDOR_ID must match legacy value."); +static_assert(CEC_MESSAGE_MENU_REQUEST == static_cast<int>(CecMessageType::MENU_REQUEST), + "CecMessageType::MENU_REQUEST must match legacy value."); +static_assert(CEC_MESSAGE_MENU_STATUS == static_cast<int>(CecMessageType::MENU_STATUS), + "CecMessageType::MENU_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_GIVE_DEVICE_POWER_STATUS == + static_cast<int>(CecMessageType::GIVE_DEVICE_POWER_STATUS), + "CecMessageType::GIVE_DEVICE_POWER_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_POWER_STATUS == + static_cast<int>(CecMessageType::REPORT_POWER_STATUS), + "CecMessageType::REPORT_POWER_STATUS must match legacy value."); +static_assert(CEC_MESSAGE_GET_MENU_LANGUAGE == static_cast<int>(CecMessageType::GET_MENU_LANGUAGE), + "CecMessageType::GET_MENU_LANGUAGE must match legacy value."); +static_assert(CEC_MESSAGE_SELECT_ANALOG_SERVICE == + static_cast<int>(CecMessageType::SELECT_ANALOG_SERVICE), + "CecMessageType::SELECT_ANALOG_SERVICE must match legacy value."); +static_assert(CEC_MESSAGE_SELECT_DIGITAL_SERVICE == + static_cast<int>(CecMessageType::SELECT_DIGITAL_SERVICE), + "CecMessageType::SELECT_DIGITAL_SERVICE must match legacy value."); +static_assert(CEC_MESSAGE_SET_DIGITAL_TIMER == static_cast<int>(CecMessageType::SET_DIGITAL_TIMER), + "CecMessageType::SET_DIGITAL_TIMER must match legacy value."); +static_assert(CEC_MESSAGE_CLEAR_DIGITAL_TIMER == + static_cast<int>(CecMessageType::CLEAR_DIGITAL_TIMER), + "CecMessageType::CLEAR_DIGITAL_TIMER must match legacy value."); +static_assert(CEC_MESSAGE_SET_AUDIO_RATE == static_cast<int>(CecMessageType::SET_AUDIO_RATE), + "CecMessageType::SET_AUDIO_RATE must match legacy value."); +static_assert(CEC_MESSAGE_INACTIVE_SOURCE == static_cast<int>(CecMessageType::INACTIVE_SOURCE), + "CecMessageType::INACTIVE_SOURCE must match legacy value."); +static_assert(CEC_MESSAGE_CEC_VERSION == static_cast<int>(CecMessageType::CEC_VERSION), + "CecMessageType::CEC_VERSION must match legacy value."); +static_assert(CEC_MESSAGE_GET_CEC_VERSION == static_cast<int>(CecMessageType::GET_CEC_VERSION), + "CecMessageType::GET_CEC_VERSION must match legacy value."); +static_assert(CEC_MESSAGE_VENDOR_COMMAND_WITH_ID == + static_cast<int>(CecMessageType::VENDOR_COMMAND_WITH_ID), + "CecMessageType::VENDOR_COMMAND_WITH_ID must match legacy value."); +static_assert(CEC_MESSAGE_CLEAR_EXTERNAL_TIMER == + static_cast<int>(CecMessageType::CLEAR_EXTERNAL_TIMER), + "CecMessageType::CLEAR_EXTERNAL_TIMER must match legacy value."); +static_assert(CEC_MESSAGE_SET_EXTERNAL_TIMER == + static_cast<int>(CecMessageType::SET_EXTERNAL_TIMER), + "CecMessageType::SET_EXTERNAL_TIMER must match legacy value."); +static_assert(CEC_MESSAGE_INITIATE_ARC == static_cast<int>(CecMessageType::INITIATE_ARC), + "CecMessageType::INITIATE_ARC must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_ARC_INITIATED == + static_cast<int>(CecMessageType::REPORT_ARC_INITIATED), + "CecMessageType::REPORT_ARC_INITIATED must match legacy value."); +static_assert(CEC_MESSAGE_REPORT_ARC_TERMINATED == + static_cast<int>(CecMessageType::REPORT_ARC_TERMINATED), + "CecMessageType::REPORT_ARC_TERMINATED must match legacy value."); +static_assert(CEC_MESSAGE_REQUEST_ARC_INITIATION == + static_cast<int>(CecMessageType::REQUEST_ARC_INITIATION), + "CecMessageType::REQUEST_ARC_INITIATION must match legacy value."); +static_assert(CEC_MESSAGE_REQUEST_ARC_TERMINATION == + static_cast<int>(CecMessageType::REQUEST_ARC_TERMINATION), + "CecMessageType::REQUEST_ARC_TERMINATION must match legacy value."); +static_assert(CEC_MESSAGE_TERMINATE_ARC == static_cast<int>(CecMessageType::TERMINATE_ARC), + "CecMessageType::TERMINATE_ARC must match legacy value."); +static_assert(CEC_MESSAGE_ABORT == static_cast<int>(CecMessageType::ABORT), + "CecMessageType::ABORT must match legacy value."); + +static_assert(ABORT_UNRECOGNIZED_MODE == static_cast<int>(AbortReason::UNRECOGNIZED_MODE), + "AbortReason::UNRECOGNIZED_MODE must match legacy value."); +static_assert(ABORT_NOT_IN_CORRECT_MODE == static_cast<int>(AbortReason::NOT_IN_CORRECT_MODE), + "AbortReason::NOT_IN_CORRECT_MODE must match legacy value."); +static_assert(ABORT_CANNOT_PROVIDE_SOURCE == static_cast<int>(AbortReason::CANNOT_PROVIDE_SOURCE), + "AbortReason::CANNOT_PROVIDE_SOURCE must match legacy value."); +static_assert(ABORT_INVALID_OPERAND == static_cast<int>(AbortReason::INVALID_OPERAND), + "AbortReason::INVALID_OPERAND must match legacy value."); +static_assert(ABORT_REFUSED == static_cast<int>(AbortReason::REFUSED), + "AbortReason::REFUSED must match legacy value."); +static_assert(ABORT_UNABLE_TO_DETERMINE == static_cast<int>(AbortReason::UNABLE_TO_DETERMINE), + "AbortReason::UNABLE_TO_DETERMINE must match legacy value."); + +static_assert(HDMI_RESULT_SUCCESS == static_cast<int>(SendMessageResult::SUCCESS), + "SendMessageResult::SUCCESS must match legacy value."); +static_assert(HDMI_RESULT_NACK == static_cast<int>(SendMessageResult::NACK), + "SendMessageResult::NACK must match legacy value."); +static_assert(HDMI_RESULT_BUSY == static_cast<int>(SendMessageResult::BUSY), + "SendMessageResult::BUSY must match legacy value."); +static_assert(HDMI_RESULT_FAIL == static_cast<int>(SendMessageResult::FAIL), + "SendMessageResult::FAIL must match legacy value."); + +static_assert(HDMI_INPUT == static_cast<int>(HdmiPortType::INPUT), + "HdmiPortType::INPUT must match legacy value."); +static_assert(HDMI_OUTPUT == static_cast<int>(HdmiPortType::OUTPUT), + "HdmiPortType::OUTPUT must match legacy value."); + +static_assert(HDMI_OPTION_WAKEUP == static_cast<int>(OptionKey::WAKEUP), + "OptionKey::WAKEUP must match legacy value."); +static_assert(HDMI_OPTION_ENABLE_CEC == static_cast<int>(OptionKey::ENABLE_CEC), + "OptionKey::ENABLE_CEC must match legacy value."); +static_assert(HDMI_OPTION_SYSTEM_CEC_CONTROL == static_cast<int>(OptionKey::SYSTEM_CEC_CONTROL), + "OptionKey::SYSTEM_CEC_CONTROL must match legacy value."); + +sp<IHdmiCecCallback> HdmiCec::mCallback = nullptr; + +HdmiCec::HdmiCec(hdmi_cec_device_t* device) : mDevice(device) {} + +// Methods from ::android::hardware::tv::cec::V2_0::IHdmiCec follow. +Return<Result> HdmiCec::addDeviceType(CecDeviceType deviceType) { + // TODO implement + if (deviceType <= CecDeviceType::MAX) { + return Result::SUCCESS; + } else { + return Result::FAILURE_INVALID_ARGS; + } +} + +Return<void> HdmiCec::clearDeviceTypes() { + // TODO implement + return Void(); +} + +Return<void> HdmiCec::setAllDeviceTypes(CecAllDeviceTypes allDeviceTypes) { + // TODO implement + if (allDeviceTypes == 1) { + } + return Void(); +} + +Return<void> HdmiCec::setDeviceFeatures(CecDeviceType deviceType, + CecDeviceFeatures /* deviceFeatures */) { + // TODO implement + if (deviceType != CecDeviceType::MAX) { + } + return Void(); +} + +Return<void> HdmiCec::setRcProfile(CecDeviceType deviceType, const CecRcProfile& /* rcProfile */) { + // TODO implement + if (deviceType != CecDeviceType::MAX) { + } + return Void(); +} + +Return<void> HdmiCec::readDeviceInfo(CecLogicalAddress logicalAddress, + CecPhysicalAddress physicalAddress, + const readDeviceInfo_cb _hidl_cb) { + // TODO implement + CecDeviceInfo deviceInfo; + + if (logicalAddress == CecLogicalAddress::TV) { + _hidl_cb(Result::SUCCESS, deviceInfo); + if (physicalAddress) { + } + } + return Void(); +} + +Return<SendMessageResult> HdmiCec::sendMessage(const CecMessage& message) { + cec_message_t legacyMessage{ + .initiator = static_cast<cec_logical_address_t>(message.initiator), + .destination = static_cast<cec_logical_address_t>(message.destination), + .length = message.body.size(), + }; + for (size_t i = 0; i < message.body.size(); ++i) { + legacyMessage.body[i] = static_cast<unsigned char>(message.body[i]); + } + return static_cast<SendMessageResult>(mDevice->send_message(mDevice, &legacyMessage)); +} + +Return<void> HdmiCec::setCallback(const sp<IHdmiCecCallback>& callback) { + if (mCallback != nullptr) { + mCallback->unlinkToDeath(this); + mCallback = nullptr; + } + + if (callback != nullptr) { + mCallback = callback; + mCallback->linkToDeath(this, 0 /*cookie*/); + mDevice->register_event_callback(mDevice, eventCallback, nullptr); + } + return Void(); +} + +Return<void> HdmiCec::getPortInfo(getPortInfo_cb _hidl_cb) { + struct hdmi_port_info* legacyPorts; + int numPorts; + hidl_vec<HdmiPortInfo> portInfos; + mDevice->get_port_info(mDevice, &legacyPorts, &numPorts); + portInfos.resize(numPorts); + for (int i = 0; i < numPorts; ++i) { + portInfos[i] = {.type = static_cast<HdmiPortType>(legacyPorts[i].type), + .portId = static_cast<HdmiPortId>(legacyPorts[i].port_id), + .cecSupported = legacyPorts[i].cec_supported != 0, + .arcSupported = legacyPorts[i].arc_supported != 0, + .physicalAddress = legacyPorts[i].physical_address}; + } + _hidl_cb(portInfos); + return Void(); +} + +Return<void> HdmiCec::setOption(OptionKey key, bool value) { + mDevice->set_option(mDevice, static_cast<int>(key), value ? 1 : 0); + return Void(); +} + +Return<void> HdmiCec::setLanguage(const hidl_string& language) { + if (language.size() != 3) { + LOG(ERROR) << "Wrong language code: expected 3 letters, but it was " << language.size() + << "."; + return Void(); + } + const char* languageStr = language.c_str(); + int convertedLanguage = ((languageStr[0] & 0xFF) << 16) | ((languageStr[1] & 0xFF) << 8) | + (languageStr[2] & 0xFF); + mDevice->set_option(mDevice, HDMI_OPTION_SET_LANG, convertedLanguage); + return Void(); +} + +Return<void> HdmiCec::enableAudioReturnChannel(HdmiPortId portId, bool enable) { + mDevice->set_audio_return_channel(mDevice, portId, enable ? 1 : 0); + return Void(); +} + +Return<bool> HdmiCec::isConnected(HdmiPortId portId) { + return mDevice->is_connected(mDevice, portId) > 0; +} + +IHdmiCec* HIDL_FETCH_IHdmiCec(const char* hal) { + hdmi_cec_device_t* hdmi_cec_device; + int ret = 0; + const hw_module_t* hw_module = nullptr; + + ret = hw_get_module(HDMI_CEC_HARDWARE_MODULE_ID, &hw_module); + if (ret == 0) { + ret = hdmi_cec_open(hw_module, &hdmi_cec_device); + if (ret != 0) { + LOG(ERROR) << "hdmi_cec_open " << hal << " failed: " << ret; + } + } else { + LOG(ERROR) << "hw_get_module " << hal << " failed: " << ret; + } + + if (ret == 0) { + return new HdmiCec(hdmi_cec_device); + } else { + LOG(ERROR) << "Passthrough failed to load legacy HAL."; + return nullptr; + } +} + +} // namespace implementation +} // namespace V2_0 +} // namespace cec +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/tv/cec/2.0/default/HdmiCec.h b/tv/cec/2.0/default/HdmiCec.h new file mode 100644 index 000000000..ab5477089 --- /dev/null +++ b/tv/cec/2.0/default/HdmiCec.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HARDWARE_TV_CEC_V2_0_HDMICEC_H +#define ANDROID_HARDWARE_TV_CEC_V2_0_HDMICEC_H + +#include <algorithm> + +#include <android/hardware/tv/cec/2.0/IHdmiCec.h> +#include <hardware/hardware.h> +#include <hardware/hdmi_cec.h> +#include <hidl/Status.h> + +#include <hidl/MQDescriptor.h> +namespace android { +namespace hardware { +namespace tv { +namespace cec { +namespace V2_0 { +namespace implementation { + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::tv::cec::V2_0::CecLogicalAddress; +using ::android::hardware::tv::cec::V2_0::CecMessage; +using ::android::hardware::tv::cec::V2_0::CecPhysicalAddress; +using ::android::hardware::tv::cec::V2_0::HdmiPortId; +using ::android::hardware::tv::cec::V2_0::HdmiPortInfo; +using ::android::hardware::tv::cec::V2_0::IHdmiCec; +using ::android::hardware::tv::cec::V2_0::IHdmiCecCallback; +using ::android::hardware::tv::cec::V2_0::MaxLength; +using ::android::hardware::tv::cec::V2_0::OptionKey; +using ::android::hardware::tv::cec::V2_0::Result; +using ::android::hardware::tv::cec::V2_0::SendMessageResult; + +struct HdmiCec : public IHdmiCec, public hidl_death_recipient { + HdmiCec(hdmi_cec_device_t* device); + // Methods from ::android::hardware::tv::cec::V2_0::IHdmiCec follow. + Return<Result> addDeviceType(CecDeviceType deviceType) override; + Return<void> clearDeviceTypes() override; + Return<void> setAllDeviceTypes(CecAllDeviceTypes allDeviceTypes) override; + Return<void> setDeviceFeatures(CecDeviceType deviceType, + CecDeviceFeatures /* deviceFeatures */) override; + Return<void> setRcProfile(CecDeviceType deviceType, + const CecRcProfile& /* rcProfile */) override; + Return<void> readDeviceInfo(CecLogicalAddress logicalAddress, + CecPhysicalAddress physicalAddress, + const readDeviceInfo_cb _hidl_cb) override; + Return<SendMessageResult> sendMessage(const CecMessage& message) override; + Return<void> setCallback(const sp<IHdmiCecCallback>& callback) override; + Return<void> getPortInfo(getPortInfo_cb _hidl_cb) override; + Return<void> setOption(OptionKey key, bool value) override; + Return<void> setLanguage(const hidl_string& language) override; + Return<void> enableAudioReturnChannel(HdmiPortId portId, bool enable) override; + Return<bool> isConnected(HdmiPortId portId) override; + + static void eventCallback(const hdmi_event_t* event, void* /* arg */) { + if (mCallback != nullptr && event != nullptr) { + if (event->type == HDMI_EVENT_CEC_MESSAGE) { + size_t length = + std::min(event->cec.length, static_cast<size_t>(MaxLength::MESSAGE_BODY)); + CecMessage cecMessage{ + .initiator = static_cast<CecLogicalAddress>(event->cec.initiator), + .destination = static_cast<CecLogicalAddress>(event->cec.destination), + }; + cecMessage.body.resize(length); + for (size_t i = 0; i < length; ++i) { + cecMessage.body[i] = static_cast<uint8_t>(event->cec.body[i]); + } + mCallback->onCecMessage(cecMessage); + } else if (event->type == HDMI_EVENT_HOT_PLUG) { + HotplugEvent hotplugEvent{ + .connected = event->hotplug.connected > 0, + .portId = static_cast<HdmiPortId>(event->hotplug.port_id)}; + mCallback->onHotplugEvent(hotplugEvent); + } + } + } + + virtual void serviceDied(uint64_t /*cookie*/, + const wp<::android::hidl::base::V1_0::IBase>& /*who*/) { + setCallback(nullptr); + } + + private: + static sp<IHdmiCecCallback> mCallback; + const hdmi_cec_device_t* mDevice; +}; + +extern "C" IHdmiCec* HIDL_FETCH_IHdmiCec(const char* name); + +} // namespace implementation +} // namespace V2_0 +} // namespace cec +} // namespace tv +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_TV_CEC_V2_0_HDMICEC_H diff --git a/tv/cec/2.0/default/OWNERS b/tv/cec/2.0/default/OWNERS new file mode 100644 index 000000000..1b3d095f9 --- /dev/null +++ b/tv/cec/2.0/default/OWNERS @@ -0,0 +1,4 @@ +nchalko@google.com +amyjojo@google.com +shubang@google.com +quxiangfang@google.com diff --git a/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.rc b/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.rc new file mode 100644 index 000000000..1e8cd8052 --- /dev/null +++ b/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.rc @@ -0,0 +1,4 @@ +service vendor.cec-hal-2-0 /vendor/bin/hw/android.hardware.tv.cec@2.0-service + class hal + user system + group system diff --git a/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.xml b/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.xml new file mode 100644 index 000000000..61fb1bbf9 --- /dev/null +++ b/tv/cec/2.0/default/android.hardware.tv.cec@2.0-service.xml @@ -0,0 +1,11 @@ +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.tv.cec</name> + <transport>hwbinder</transport> + <version>2.0</version> + <interface> + <name>IHdmiCec</name> + <instance>default</instance> + </interface> + </hal> +</manifest> diff --git a/tv/cec/2.0/default/service.cpp b/tv/cec/2.0/default/service.cpp new file mode 100644 index 000000000..dacc38cc9 --- /dev/null +++ b/tv/cec/2.0/default/service.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.tv.cec@2.0-service" + +#include <android/hardware/tv/cec/2.0/IHdmiCec.h> +#include <hidl/LegacySupport.h> + +using android::hardware::defaultPassthroughServiceImplementation; +using android::hardware::tv::cec::V2_0::IHdmiCec; + +int main() { + return defaultPassthroughServiceImplementation<IHdmiCec>(); +} diff --git a/tv/cec/2.0/types.hal b/tv/cec/2.0/types.hal new file mode 100644 index 000000000..cad6c396e --- /dev/null +++ b/tv/cec/2.0/types.hal @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.tv.cec@2.0; + +import android.hidl.safe_union@1.0; + +/** + * CEC device type as specified in CEC Table 11-7 of the CEC spec 2.0b. + */ +enum CecDeviceType : int32_t { + INACTIVE = -1, + TV = 0, + RECORDER = 1, + TUNER = 3, + PLAYBACK = 4, + AUDIO_SYSTEM = 5, + PURE_CEC_SWITCH = 6, + PROCESSOR = 7, + MAX = PROCESSOR, +}; + +/** + * CEC logical address as specified in CEC Table 11-9 of the CEC spec 2.0b. + */ +enum CecLogicalAddress : int32_t { + TV = 0, + RECORDER_1 = 1, + RECORDER_2 = 2, + TUNER_1 = 3, + PLAYBACK_1 = 4, + AUDIO_SYSTEM = 5, + TUNER_2 = 6, + TUNER_3 = 7, + PLAYBACK_2 = 8, + RECORDER_3 = 9, + TUNER_4 = 10, + PLAYBACK_3 = 11, + BACKUP_1 = 12, // backup1 for Playback/Recording/Tuner/Processor device + BACKUP_2 = 13, // backup2 for Playback/Recording/Tuner/Processor device + SPECIFIC_USE = 14, + UNREGISTERED = 15, // as Initiator address + BROADCAST = 15, // as Destination address +}; + +/** + * HDMI CEC message types. + * + * The assigned values represent opcode used in CEC frame as specified in + * Section 11.10 of the CEC spec 2.0b on top of Section CEC 15 of the CEC + * Spec 1.4b. + */ +enum CecMessageType : int32_t { + FEATURE_ABORT = 0x00, + IMAGE_VIEW_ON = 0x04, + TUNER_STEP_INCREMENT = 0x05, + TUNER_STEP_DECREMENT = 0x06, + TUNER_DEVICE_STATUS = 0x07, + GIVE_TUNER_DEVICE_STATUS = 0x08, + RECORD_ON = 0x09, + RECORD_STATUS = 0x0A, + RECORD_OFF = 0x0B, + TEXT_VIEW_ON = 0x0D, + RECORD_TV_SCREEN = 0x0F, + GIVE_DECK_STATUS = 0x1A, + DECK_STATUS = 0x1B, + SET_MENU_LANGUAGE = 0x32, + CLEAR_ANALOG_TIMER = 0x33, + SET_ANALOG_TIMER = 0x34, + TIMER_STATUS = 0x35, + STANDBY = 0x36, + PLAY = 0x41, + DECK_CONTROL = 0x42, + TIMER_CLEARED_STATUS = 0x43, + USER_CONTROL_PRESSED = 0x44, + USER_CONTROL_RELEASED = 0x45, + GIVE_OSD_NAME = 0x46, + SET_OSD_NAME = 0x47, + SET_OSD_STRING = 0x64, + SET_TIMER_PROGRAM_TITLE = 0x67, + SYSTEM_AUDIO_MODE_REQUEST = 0x70, + GIVE_AUDIO_STATUS = 0x71, + SET_SYSTEM_AUDIO_MODE = 0x72, + REPORT_AUDIO_STATUS = 0x7A, + GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, + SYSTEM_AUDIO_MODE_STATUS = 0x7E, + ROUTING_CHANGE = 0x80, + ROUTING_INFORMATION = 0x81, + ACTIVE_SOURCE = 0x82, + GIVE_PHYSICAL_ADDRESS = 0x83, + REPORT_PHYSICAL_ADDRESS = 0x84, + REQUEST_ACTIVE_SOURCE = 0x85, + SET_STREAM_PATH = 0x86, + DEVICE_VENDOR_ID = 0x87, + VENDOR_COMMAND = 0x89, + VENDOR_REMOTE_BUTTON_DOWN = 0x8A, + VENDOR_REMOTE_BUTTON_UP = 0x8B, + GIVE_DEVICE_VENDOR_ID = 0x8C, + MENU_REQUEST = 0x8D, + MENU_STATUS = 0x8E, + GIVE_DEVICE_POWER_STATUS = 0x8F, + REPORT_POWER_STATUS = 0x90, + GET_MENU_LANGUAGE = 0x91, + SELECT_ANALOG_SERVICE = 0x92, + SELECT_DIGITAL_SERVICE = 0x93, + SET_DIGITAL_TIMER = 0x97, + CLEAR_DIGITAL_TIMER = 0x99, + SET_AUDIO_RATE = 0x9A, + INACTIVE_SOURCE = 0x9D, + CEC_VERSION = 0x9E, + GET_CEC_VERSION = 0x9F, + VENDOR_COMMAND_WITH_ID = 0xA0, + CLEAR_EXTERNAL_TIMER = 0xA1, + SET_EXTERNAL_TIMER = 0xA2, + REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3, + REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4, + GIVE_FEATURES = 0XA5, + REPORT_FEATURES = 0xA6, + REQUEST_CURRENT_LATENCY = 0xA7, + REPORT_CURRENT_LATENCY = 0xA8, + INITIATE_ARC = 0xC0, + REPORT_ARC_INITIATED = 0xC1, + REPORT_ARC_TERMINATED = 0xC2, + REQUEST_ARC_INITIATION = 0xC3, + REQUEST_ARC_TERMINATION = 0xC4, + TERMINATE_ARC = 0xC5, + ABORT = 0xFF, + POLLING_MESSAGE = 0xFFFFFF00, // used for cec polling message +}; + +/** + * Abort Reason as specified in CEC Table 29 of the CEC spec 1.4b. + */ +enum AbortReason : int32_t { + UNRECOGNIZED_MODE = 0, + NOT_IN_CORRECT_MODE = 1, + CANNOT_PROVIDE_SOURCE = 2, + INVALID_OPERAND = 3, + REFUSED = 4, + UNABLE_TO_DETERMINE = 5, +}; + +enum MaxLength : int32_t { + MESSAGE_BODY = 14, +}; + +struct CecMessage { + /** logical address of sender */ + CecLogicalAddress initiator; + + /** logical address of receiver */ + CecLogicalAddress destination; + + /** cec message type */ + CecMessageType cecMessageType; + + /** + * The maximum size of body is 14 (MaxLength::MESSAGE_BODY) as specified in + * the section 6 of the CEC Spec 1.4b. Overflowed data must be ignored. + */ + vec<uint8_t> body; +}; + +/** + * error code used for send_message. + */ +enum SendMessageResult : int32_t { + SUCCESS = 0, + NACK = 1, // not acknowledged + BUSY = 2, // bus is busy + FAIL = 3, +}; + +/** + * CEC All Device Type Value as specified in Table 11-30 of the CEC spec 2.0b. + */ +enum CecAllDeviceTypeValue : uint8_t { + RESERVED_DEVICE_2 = 1 << 0, + RESERVED_DEVICE_1 = 1 << 1, + CEC_SWITCH_DEVICE = 1 << 2, + AUDIO_DEVICE = 1 << 3, + PLAYBACK_DEVICE = 1 << 4, + TUNER_DEVICE = 1 << 5, + RECORDING_DEVICE = 1 << 6, + TV_DEVICE = 1 << 7, +}; + +/** + * CEC All Device Types + * + * It is a combination of all supported type from CecAllDeviceTypeValue. + * For example a record with tuner functionalitye, + * cecAllDeviceTypes = ((CecAllDeviceTypeValue::RECORDING_DEVICE) + * |(CecAllDeviceTypeValue::TUNER_DEVICE)) + */ +typedef bitfield<CecAllDeviceTypeValue> CecAllDeviceTypes; + +/** + * CEC Versions as specified in CEC Table 11-30 of the CEC spec 2.0b. + */ +enum CecVersion : int32_t { + V_1_3_A = 0x04, + V_1_4 = 0x05, // indicate CEC 1.4, 1.4a or 1.4b + V_2_0 = 0x06, +}; + +/** + * Device Feature + * + * It is specified in CEC Table 11-30 of the CEC spec 2.0b. As a uint32 there + * is room for future extensions aka DeviceFeature2 through DeviceFeature4. + */ +enum CecDeviceFeature : uint32_t { + RESERVED = 1 << 0, + SOURCE_SUPPORT_ARC_RX = 1 << 1, + SINK_SUPPORT_ARC_TX = 1 << 2, + SOURCE_SUPPORT_SET_AUDIO_RATE = 1 << 3, + SUPPORT_CONTROLLED_BY_DECK = 1 << 4, + TV_SUPPORT_SET_OSD_STRINGS = 1 << 5, + TV_SUPPORT_RECORD_TV_SCREEN = 1 << 6, +}; + +/** + * CEC Device Features + * + * It is a combination of all supported features from CecDeviceFeature. + * For example a TV with OSD and ARC capabilities, + * CecDeviceFeatures = ((CecDeviceFeature::TV_SUPPORT_SET_OSD_STRINGS) + * |(CecDeviceFeature::SINK_SUPPORT_ARC_TX)) + */ +typedef bitfield<CecDeviceFeature> CecDeviceFeatures; + +/** + * Remote Control Profile + * + * It is specified in CEC Table 11-30 of the CEC spec 2.0b. + */ +enum CecRcProfileId : uint8_t { + NONE = 0, // TV doesn’t support any of these profiles + RC_PROFILE_1 = 0x02, // minimalistic zapper (low button count) + RC_PROFILE_2 = 0x06, // intermediate between profile 1 and profile 3 + RC_PROFILE_3 = 0x0A, // typical TV remote + RC_PROFILE_4 = 0x0E, // extended form of profile 3 +}; + +/** + * Remote Control Profile Source + * + * It is specified in CEC Table 11-30 of the CEC spec 2.0b. + */ +enum CecRcProfileSource : uint8_t { + MEDIA_CONTEXT_SENSITIVE = 1 << 0, // source can handle UI command 0x11 + MEDIA_TO = 1 << 1, // source can handle UI command 0x10 + CONTENTS = 1 << 2, // source can handle UI command 0x0B + DEVICE_SETUP = 1 << 3, // source can handle UI command 0x0A + DEVICE_ROOT = 1 << 4, // source can handle UI command 0x09 + SOURCE_FLAG = 1 << 6, // Indicate the profile is for source +}; + +/** + * Remote Control Profile for either TV or Source. + */ +safe_union CecRcProfile1 { + /** CEC remote control profile for TV. */ + CecRcProfileId profileId; + + /* CEC remote control profile for source + * + * It is a combination of all supported profiles from CecRcProfileSource. + * For example a playback device support root menu and setup menu, + * profileSource = ((CecRcProfileSource::DEVICE_ROOT) + * |(CecRcProfileSource::DEVICE_SETUP) + * |(CecRcProfileSource::SOURCE_FLAG)) + */ + bitfield<CecRcProfileSource> profileSource; +}; + +/** + * CEC Remote Control Profiles + * + * CEC 2.0 only use one byte to represent Remote Control Profile. + */ +struct CecRcProfile { + CecRcProfile1 rcProfile1; +}; + +/** + * CEC device power states as specified in CEC Table 11-10 of the CEC spec 2.0b + */ +enum CecPowerState : int8_t { + ON = 0, + STANDBY = 1, + ON_TO_STANDBY = 2, + STANDBY_TO_ON = 4, + UNKNOWN = 0xFF, // some devices may not report power status +}; + +/** CEC physical address of device */ +typedef uint16_t CecPhysicalAddress; + +/** + * CEC device information + * + * It is initially built during addressing specified in CEC section 11.3 of + * the CEC spec 2.0b. It may be updated with cec devices's status changed. + */ +struct CecDeviceInfo { + /** CEC version which device supports */ + CecVersion version; + + /** CEC device primary type */ + CecDeviceType devceType; + + /** CEC all device types */ + CecAllDeviceTypes allDeviceTypes; + + /** CEC device features */ + CecDeviceFeatures deviceFeatures; + + /** CEC Device Remote Control Profile */ + CecRcProfile rcProfile; + + /** CEC Device Vendor ID */ + uint32_t vendorId; + + /** logical address of device */ + CecLogicalAddress logicalAddress; + + /** physical of device */ + CecPhysicalAddress physicalAddress; + + /** power status of device */ + CecPowerState powerState; +}; + +/** + * Topology Event Type. + */ +enum CecTopologyEventType : int32_t { + DEVICE_ADDED, + DEVICE_REMOVED, + DEVICE_UPDATED, +}; + +/** + * Topology Event. + */ +struct CecTopologyEvent { + CecTopologyEventType eventType; + CecLogicalAddress logicalAddress; + CecPhysicalAddress physicalAddress; + + /** true if the event is about the device which the system run on */ + bool isHostDevice; +}; + + +/** + * CEC UI Command Codes as specified in CEC Table 11-31 of the CEC spec 2.0b + */ +enum CecUICommandCodes : int32_t { + SELECT_OK = 0x00, + UP = 0x01, + DOWN = 0x02, + LEFT = 0x03, + RIGHT = 0x04, + RIGHT_UP = 0x05, + RIGHT_DOWN = 0x06, + LEFT_UP = 0x07, + LEFT_DOWN = 0x08, + DEVICE_ROOT_MENU = 0x09, + DEVICE_SETUP_MENU = 0x0A, + CONTENTS_MENU = 0x0B, + FAVORITE_MENU = 0x0C, + BACK = 0x0D, + MEDIA_TOP_MENU = 0x10, + MEDIA_CONTEXT_SENSITIVE_MENU = 0x11, + NUMBER_ENTRY_MODE = 0x1D, + NUMBER_11 = 0x1E, + NUMBER_12 = 0x1F, + NUMBER_0 = 0x20, // or NUMBER 10 + NUMBER_1 = 0x21, + NUMBER_2 = 0x22, + NUMBER_3 = 0x23, + NUMBER_4 = 0x24, + NUMBER_5 = 0x25, + NUMBER_6 = 0x26, + NUMBER_7 = 0x27, + NUMBER_8 = 0x28, + NUMBER_9 = 0x29, + DOT = 0x2A, + ENTER = 0x2B, + CLEAR = 0x2C, + NEXT_FAVORITE = 0x2F, + CHANNEL_UP = 0x30, + CHANNEL_DOWN = 0x31, + PREVIOUS_CHANNEL = 0x32, + SOUND_SELECT = 0x33, + INPUT_SELECT = 0x34, + DISPLAY_INFORMATION = 0x35, + HELP = 0x36, + PAGE_UP = 0x37, + PAGE_DOWN = 0x38, + POWER = 0x40, + VOLUME_UP = 0x41, + VOLUME_DOWN = 0x42, + MUTE = 0x43, + PLAY = 0x44, + STOP = 0x45, + PAUSE = 0x46, + RECORD = 0x47, + REWIND = 0x48, + FAST_FORWARD = 0x49, + EJECT = 0x4A, + SKIP_FORWARD = 0x4B, + SKIP_BACKWARD = 0x4C, + STOP_RECORD = 0x4D, + PAUSE_RECORD = 0x4E, + ANGLE = 0x50, + SUB_PICTURE = 0x51, + VIDEO_ON_DEMAND = 0x52, + ELECTRONIC_PROGRAM_GUIDE = 0x53, + TIMER_PROGRAMMING = 0x54, + INITIAL_CONFIGURATION = 0x55, + SELECT_BROADCAST_TYPE = 0x56, + SELECT_SOUND_PRESENTATION = 0x57, + AUDIO_DESCRIPTION = 0x58, + INTERNET = 0x59, + THREE_DIMENSIONAL_MODE = 0x5A, + PLAY_FUNCTION = 0x60, + PAUSE_PLAY_FUNCTION = 0x61, + RECORD_FUNCTION = 0x62, + PAUSE_RECORD_FUNCTION = 0x63, + STOP_FUNCTION = 0x64, + MUTE_FUNCTION = 0x65, + RESTORE_VOLUME_FUNCTION = 0x66, + TUNE_FUNCTION = 0x67, + SELECT_MEDIA_FUNCTION = 0x68, + SELECT_AV_INPUT_FUNCTION = 0x69, + SELECT_AUDIO_INPUT_FUNCTION = 0x6A, + POWER_TOGGLE_FUNCTION = 0x6B, + POWER_OFF_FUNCTION = 0x6C, + POWER_ON_FUNCTION = 0x6D, + F1 = 0x71, // BLUE + F2 = 0x72, // RED + F3 = 0x73, // GREEN + F4 = 0x74, // YELLOW + F5 = 0x75, + DATA = 0x76, +}; + +/** + * HDMI port type. + */ +enum HdmiPortType : int32_t { + INPUT = 0, + OUTPUT = 1, +}; + +/** + * Options used for IHdmiCec.setOption() + */ +enum OptionKey : int32_t { + /** + * When set to false, HAL does not wake up the system upon receiving <Image + * View On> or <Text View On>. Used when user changes the TV settings to + * disable the auto TV on functionality. + * Deprecated since <Image View On> and <Text View On> become mandatory + * featrues for CEC device. Use ENABLE_CEC OptionKey to disable CEC + * functionality instead. + * True by Default + */ + WAKEUP = 1, + + /** + * When set to false, all the CEC commands are discarded. if logical address + * is ever used, it shall be released. Used when user changes the TV + * settings to disable CEC functionality. + * True by default. + * + */ + ENABLE_CEC = 2, + + /** + * Setting this flag to false means Android system must stop handling CEC + * service and yield the control over to the microprocessor that is powered + * on through the standby mode.The microprocessor shall keep current logical + * and physical address. It shall response POLLING_MESSAGE, GIVE_FEATURES, + * GIVE_DEVICE_POWER_STATUS,GIVE_DEVICE_VENDOR_ID and GIVE_PHYSICAL_ADDRESS + * to allow other CEC devices to build CEC devices map specified in CEC + * section 11.3 of the CEC spec 2.0b. + * When set to true, the system must gain the control over, hence telling + * the microprocessor to start forwarding CEC messages to Android system. + * For example, this may be called when system goes in and out of + * standby mode to notify the microprocessor that it should start/stop + * handling CEC commands on behalf of the system. + * True by default. + */ + SYSTEM_CEC_CONTROL = 3, + + /* Option 4 not used */ +}; + +/** + * Hdmi port ID. + * + * It shall start from 1 which corresponds to HDMI "port 1". + */ +typedef uint32_t HdmiPortId; + +/** Hdmi hotplug event */ +struct HotplugEvent { + bool connected; + HdmiPortId portId; +}; + +/** + * HDMI port descriptor + */ +struct HdmiPortInfo { + HdmiPortType type; + HdmiPortId portId; + bool cecSupported; + bool arcSupported; + CecPhysicalAddress physicalAddress; +}; + +enum Result : int32_t { + SUCCESS = 0, + FAILURE_UNKNOWN = 1, + FAILURE_INVALID_ARGS = 2, + FAILURE_INVALID_STATE = 3, + FAILURE_NOT_SUPPORTED = 4, + FAILURE_BUSY = 5, +}; |