1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "android.hardware.tv.cec@1.0-impl"
18 #include <android-base/logging.h>
19 
20 #include <hardware/hardware.h>
21 #include <hardware/hdmi_cec.h>
22 #include "HdmiCec.h"
23 
24 namespace android {
25 namespace hardware {
26 namespace tv {
27 namespace cec {
28 namespace V1_0 {
29 namespace implementation {
30 
31 static_assert(CEC_DEVICE_INACTIVE == static_cast<int>(CecDeviceType::INACTIVE),
32         "CecDeviceType::INACTIVE must match legacy value.");
33 static_assert(CEC_DEVICE_TV == static_cast<int>(CecDeviceType::TV),
34         "CecDeviceType::TV must match legacy value.");
35 static_assert(CEC_DEVICE_RECORDER == static_cast<int>(CecDeviceType::RECORDER),
36         "CecDeviceType::RECORDER must match legacy value.");
37 static_assert(CEC_DEVICE_TUNER == static_cast<int>(CecDeviceType::TUNER),
38         "CecDeviceType::TUNER must match legacy value.");
39 static_assert(CEC_DEVICE_PLAYBACK == static_cast<int>(CecDeviceType::PLAYBACK),
40         "CecDeviceType::PLAYBACK must match legacy value.");
41 static_assert(CEC_DEVICE_AUDIO_SYSTEM == static_cast<int>(CecDeviceType::AUDIO_SYSTEM),
42         "CecDeviceType::AUDIO_SYSTEM must match legacy value.");
43 static_assert(CEC_DEVICE_MAX == static_cast<int>(CecDeviceType::MAX),
44         "CecDeviceType::MAX must match legacy value.");
45 
46 static_assert(CEC_ADDR_TV == static_cast<int>(CecLogicalAddress::TV),
47         "CecLogicalAddress::TV must match legacy value.");
48 static_assert(CEC_ADDR_RECORDER_1 == static_cast<int>(CecLogicalAddress::RECORDER_1),
49         "CecLogicalAddress::RECORDER_1 must match legacy value.");
50 static_assert(CEC_ADDR_RECORDER_2 == static_cast<int>(CecLogicalAddress::RECORDER_2),
51         "CecLogicalAddress::RECORDER_2 must match legacy value.");
52 static_assert(CEC_ADDR_TUNER_1 == static_cast<int>(CecLogicalAddress::TUNER_1),
53         "CecLogicalAddress::TUNER_1 must match legacy value.");
54 static_assert(CEC_ADDR_PLAYBACK_1 == static_cast<int>(CecLogicalAddress::PLAYBACK_1),
55         "CecLogicalAddress::PLAYBACK_1 must match legacy value.");
56 static_assert(CEC_ADDR_AUDIO_SYSTEM == static_cast<int>(CecLogicalAddress::AUDIO_SYSTEM),
57         "CecLogicalAddress::AUDIO_SYSTEM must match legacy value.");
58 static_assert(CEC_ADDR_TUNER_2 == static_cast<int>(CecLogicalAddress::TUNER_2),
59         "CecLogicalAddress::TUNER_2 must match legacy value.");
60 static_assert(CEC_ADDR_TUNER_3 == static_cast<int>(CecLogicalAddress::TUNER_3),
61         "CecLogicalAddress::TUNER_3 must match legacy value.");
62 static_assert(CEC_ADDR_PLAYBACK_2 == static_cast<int>(CecLogicalAddress::PLAYBACK_2),
63         "CecLogicalAddress::PLAYBACK_2 must match legacy value.");
64 static_assert(CEC_ADDR_RECORDER_3 == static_cast<int>(CecLogicalAddress::RECORDER_3),
65         "CecLogicalAddress::RECORDER_3 must match legacy value.");
66 static_assert(CEC_ADDR_TUNER_4 == static_cast<int>(CecLogicalAddress::TUNER_4),
67         "CecLogicalAddress::TUNER_4 must match legacy value.");
68 static_assert(CEC_ADDR_PLAYBACK_3 == static_cast<int>(CecLogicalAddress::PLAYBACK_3),
69         "CecLogicalAddress::PLAYBACK_3 must match legacy value.");
70 static_assert(CEC_ADDR_FREE_USE == static_cast<int>(CecLogicalAddress::FREE_USE),
71         "CecLogicalAddress::FREE_USE must match legacy value.");
72 static_assert(CEC_ADDR_UNREGISTERED == static_cast<int>(CecLogicalAddress::UNREGISTERED),
73         "CecLogicalAddress::UNREGISTERED must match legacy value.");
74 static_assert(CEC_ADDR_BROADCAST == static_cast<int>(CecLogicalAddress::BROADCAST),
75         "CecLogicalAddress::BROADCAST must match legacy value.");
76 
77 static_assert(CEC_MESSAGE_FEATURE_ABORT == static_cast<int>(CecMessageType::FEATURE_ABORT),
78         "CecMessageType::FEATURE_ABORT must match legacy value.");
79 static_assert(CEC_MESSAGE_IMAGE_VIEW_ON == static_cast<int>(CecMessageType::IMAGE_VIEW_ON),
80         "CecMessageType::IMAGE_VIEW_ON must match legacy value.");
81 static_assert(CEC_MESSAGE_TUNER_STEP_INCREMENT == static_cast<int>(
82         CecMessageType::TUNER_STEP_INCREMENT),
83         "CecMessageType::TUNER_STEP_INCREMENT must match legacy value.");
84 static_assert(CEC_MESSAGE_TUNER_STEP_DECREMENT == static_cast<int>(
85         CecMessageType::TUNER_STEP_DECREMENT),
86         "CecMessageType::TUNER_STEP_DECREMENT must match legacy value.");
87 static_assert(CEC_MESSAGE_TUNER_DEVICE_STATUS == static_cast<int>(
88         CecMessageType::TUNER_DEVICE_STATUS),
89         "CecMessageType::TUNER_DEVICE_STATUS must match legacy value.");
90 static_assert(CEC_MESSAGE_GIVE_TUNER_DEVICE_STATUS == static_cast<int>(
91         CecMessageType::GIVE_TUNER_DEVICE_STATUS),
92         "CecMessageType::GIVE_TUNER_DEVICE_STATUS must match legacy value.");
93 static_assert(CEC_MESSAGE_RECORD_ON == static_cast<int>(CecMessageType::RECORD_ON),
94         "CecMessageType::RECORD_ON must match legacy value.");
95 static_assert(CEC_MESSAGE_RECORD_STATUS == static_cast<int>(CecMessageType::RECORD_STATUS),
96         "CecMessageType::RECORD_STATUS must match legacy value.");
97 static_assert(CEC_MESSAGE_RECORD_OFF == static_cast<int>(CecMessageType::RECORD_OFF),
98         "CecMessageType::RECORD_OFF must match legacy value.");
99 static_assert(CEC_MESSAGE_TEXT_VIEW_ON == static_cast<int>(CecMessageType::TEXT_VIEW_ON),
100         "CecMessageType::TEXT_VIEW_ON must match legacy value.");
101 static_assert(CEC_MESSAGE_RECORD_TV_SCREEN == static_cast<int>(CecMessageType::RECORD_TV_SCREEN),
102         "CecMessageType::RECORD_TV_SCREEN must match legacy value.");
103 static_assert(CEC_MESSAGE_GIVE_DECK_STATUS == static_cast<int>(CecMessageType::GIVE_DECK_STATUS),
104         "CecMessageType::GIVE_DECK_STATUS must match legacy value.");
105 static_assert(CEC_MESSAGE_STANDBY == static_cast<int>(CecMessageType::STANDBY),
106         "CecMessageType::STANDBY must match legacy value.");
107 static_assert(CEC_MESSAGE_PLAY == static_cast<int>(CecMessageType::PLAY),
108         "CecMessageType::PLAY must match legacy value.");
109 static_assert(CEC_MESSAGE_DECK_CONTROL == static_cast<int>(CecMessageType::DECK_CONTROL),
110         "CecMessageType::DECK_CONTROL must match legacy value.");
111 static_assert(CEC_MESSAGE_TIMER_CLEARED_STATUS == static_cast<int>(
112         CecMessageType::TIMER_CLEARED_STATUS),
113         "CecMessageType::TIMER_CLEARED_STATUS must match legacy value.");
114 static_assert(CEC_MESSAGE_USER_CONTROL_PRESSED == static_cast<int>(
115         CecMessageType::USER_CONTROL_PRESSED),
116         "CecMessageType::USER_CONTROL_PRESSED must match legacy value.");
117 static_assert(CEC_MESSAGE_USER_CONTROL_RELEASED == static_cast<int>(
118         CecMessageType::USER_CONTROL_RELEASED),
119         "CecMessageType::USER_CONTROL_RELEASED must match legacy value.");
120 static_assert(CEC_MESSAGE_GIVE_OSD_NAME == static_cast<int>(CecMessageType::GIVE_OSD_NAME),
121         "CecMessageType::GIVE_OSD_NAME must match legacy value.");
122 static_assert(CEC_MESSAGE_SET_OSD_NAME == static_cast<int>(CecMessageType::SET_OSD_NAME),
123         "CecMessageType::SET_OSD_NAME must match legacy value.");
124 static_assert(CEC_MESSAGE_SYSTEM_AUDIO_MODE_REQUEST == static_cast<int>(
125         CecMessageType::SYSTEM_AUDIO_MODE_REQUEST),
126         "CecMessageType::SYSTEM_AUDIO_MODE_REQUEST must match legacy value.");
127 static_assert(CEC_MESSAGE_GIVE_AUDIO_STATUS == static_cast<int>(CecMessageType::GIVE_AUDIO_STATUS),
128         "CecMessageType::GIVE_AUDIO_STATUS must match legacy value.");
129 static_assert(CEC_MESSAGE_SET_SYSTEM_AUDIO_MODE == static_cast<int>(
130         CecMessageType::SET_SYSTEM_AUDIO_MODE),
131         "CecMessageType::SET_SYSTEM_AUDIO_MODE must match legacy value.");
132 static_assert(CEC_MESSAGE_REPORT_AUDIO_STATUS == static_cast<int>(
133         CecMessageType::REPORT_AUDIO_STATUS),
134         "CecMessageType::REPORT_AUDIO_STATUS must match legacy value.");
135 static_assert(CEC_MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS == static_cast<int>(
136         CecMessageType::GIVE_SYSTEM_AUDIO_MODE_STATUS),
137         "CecMessageType::GIVE_SYSTEM_AUDIO_MODE_STATUS must match legacy value.");
138 static_assert(CEC_MESSAGE_SYSTEM_AUDIO_MODE_STATUS == static_cast<int>(
139         CecMessageType::SYSTEM_AUDIO_MODE_STATUS),
140         "CecMessageType::SYSTEM_AUDIO_MODE_STATUS must match legacy value.");
141 static_assert(CEC_MESSAGE_ROUTING_CHANGE == static_cast<int>(CecMessageType::ROUTING_CHANGE),
142         "CecMessageType::ROUTING_CHANGE must match legacy value.");
143 static_assert(CEC_MESSAGE_ROUTING_INFORMATION == static_cast<int>(
144         CecMessageType::ROUTING_INFORMATION),
145         "CecMessageType::ROUTING_INFORMATION must match legacy value.");
146 static_assert(CEC_MESSAGE_ACTIVE_SOURCE == static_cast<int>(CecMessageType::ACTIVE_SOURCE),
147         "CecMessageType::ACTIVE_SOURCE must match legacy value.");
148 static_assert(CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS == static_cast<int>(
149         CecMessageType::GIVE_PHYSICAL_ADDRESS),
150         "CecMessageType::GIVE_PHYSICAL_ADDRESS must match legacy value.");
151 static_assert(CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS == static_cast<int>(
152         CecMessageType::REPORT_PHYSICAL_ADDRESS),
153         "CecMessageType::REPORT_PHYSICAL_ADDRESS must match legacy value.");
154 static_assert(CEC_MESSAGE_REQUEST_ACTIVE_SOURCE == static_cast<int>(
155         CecMessageType::REQUEST_ACTIVE_SOURCE),
156         "CecMessageType::REQUEST_ACTIVE_SOURCE must match legacy value.");
157 static_assert(CEC_MESSAGE_SET_STREAM_PATH == static_cast<int>(CecMessageType::SET_STREAM_PATH),
158         "CecMessageType::SET_STREAM_PATH must match legacy value.");
159 static_assert(CEC_MESSAGE_DEVICE_VENDOR_ID == static_cast<int>(CecMessageType::DEVICE_VENDOR_ID),
160         "CecMessageType::DEVICE_VENDOR_ID must match legacy value.");
161 static_assert(CEC_MESSAGE_VENDOR_COMMAND == static_cast<int>(CecMessageType::VENDOR_COMMAND),
162         "CecMessageType::VENDOR_COMMAND must match legacy value.");
163 static_assert(CEC_MESSAGE_VENDOR_REMOTE_BUTTON_DOWN == static_cast<int>(
164         CecMessageType::VENDOR_REMOTE_BUTTON_DOWN),
165         "CecMessageType::VENDOR_REMOTE_BUTTON_DOWN must match legacy value.");
166 static_assert(CEC_MESSAGE_VENDOR_REMOTE_BUTTON_UP == static_cast<int>(
167         CecMessageType::VENDOR_REMOTE_BUTTON_UP),
168         "CecMessageType::VENDOR_REMOTE_BUTTON_UP must match legacy value.");
169 static_assert(CEC_MESSAGE_GIVE_DEVICE_VENDOR_ID == static_cast<int>(
170         CecMessageType::GIVE_DEVICE_VENDOR_ID),
171         "CecMessageType::GIVE_DEVICE_VENDOR_ID must match legacy value.");
172 static_assert(CEC_MESSAGE_MENU_REQUEST == static_cast<int>(CecMessageType::MENU_REQUEST),
173         "CecMessageType::MENU_REQUEST must match legacy value.");
174 static_assert(CEC_MESSAGE_MENU_STATUS == static_cast<int>(CecMessageType::MENU_STATUS),
175         "CecMessageType::MENU_STATUS must match legacy value.");
176 static_assert(CEC_MESSAGE_GIVE_DEVICE_POWER_STATUS == static_cast<int>(
177         CecMessageType::GIVE_DEVICE_POWER_STATUS),
178         "CecMessageType::GIVE_DEVICE_POWER_STATUS must match legacy value.");
179 static_assert(CEC_MESSAGE_REPORT_POWER_STATUS == static_cast<int>(
180         CecMessageType::REPORT_POWER_STATUS),
181         "CecMessageType::REPORT_POWER_STATUS must match legacy value.");
182 static_assert(CEC_MESSAGE_GET_MENU_LANGUAGE == static_cast<int>(CecMessageType::GET_MENU_LANGUAGE),
183         "CecMessageType::GET_MENU_LANGUAGE must match legacy value.");
184 static_assert(CEC_MESSAGE_SELECT_ANALOG_SERVICE == static_cast<int>(
185         CecMessageType::SELECT_ANALOG_SERVICE),
186         "CecMessageType::SELECT_ANALOG_SERVICE must match legacy value.");
187 static_assert(CEC_MESSAGE_SELECT_DIGITAL_SERVICE == static_cast<int>(
188         CecMessageType::SELECT_DIGITAL_SERVICE),
189         "CecMessageType::SELECT_DIGITAL_SERVICE must match legacy value.");
190 static_assert(CEC_MESSAGE_SET_DIGITAL_TIMER == static_cast<int>(CecMessageType::SET_DIGITAL_TIMER),
191         "CecMessageType::SET_DIGITAL_TIMER must match legacy value.");
192 static_assert(CEC_MESSAGE_CLEAR_DIGITAL_TIMER == static_cast<int>(
193         CecMessageType::CLEAR_DIGITAL_TIMER),
194         "CecMessageType::CLEAR_DIGITAL_TIMER must match legacy value.");
195 static_assert(CEC_MESSAGE_SET_AUDIO_RATE == static_cast<int>(CecMessageType::SET_AUDIO_RATE),
196         "CecMessageType::SET_AUDIO_RATE must match legacy value.");
197 static_assert(CEC_MESSAGE_INACTIVE_SOURCE == static_cast<int>(CecMessageType::INACTIVE_SOURCE),
198         "CecMessageType::INACTIVE_SOURCE must match legacy value.");
199 static_assert(CEC_MESSAGE_CEC_VERSION == static_cast<int>(CecMessageType::CEC_VERSION),
200         "CecMessageType::CEC_VERSION must match legacy value.");
201 static_assert(CEC_MESSAGE_GET_CEC_VERSION == static_cast<int>(CecMessageType::GET_CEC_VERSION),
202         "CecMessageType::GET_CEC_VERSION must match legacy value.");
203 static_assert(CEC_MESSAGE_VENDOR_COMMAND_WITH_ID == static_cast<int>(
204         CecMessageType::VENDOR_COMMAND_WITH_ID),
205         "CecMessageType::VENDOR_COMMAND_WITH_ID must match legacy value.");
206 static_assert(CEC_MESSAGE_CLEAR_EXTERNAL_TIMER == static_cast<int>(
207         CecMessageType::CLEAR_EXTERNAL_TIMER),
208         "CecMessageType::CLEAR_EXTERNAL_TIMER must match legacy value.");
209 static_assert(CEC_MESSAGE_SET_EXTERNAL_TIMER == static_cast<int>(
210         CecMessageType::SET_EXTERNAL_TIMER),
211         "CecMessageType::SET_EXTERNAL_TIMER must match legacy value.");
212 static_assert(CEC_MESSAGE_INITIATE_ARC == static_cast<int>(CecMessageType::INITIATE_ARC),
213         "CecMessageType::INITIATE_ARC must match legacy value.");
214 static_assert(CEC_MESSAGE_REPORT_ARC_INITIATED == static_cast<int>(
215         CecMessageType::REPORT_ARC_INITIATED),
216         "CecMessageType::REPORT_ARC_INITIATED must match legacy value.");
217 static_assert(CEC_MESSAGE_REPORT_ARC_TERMINATED == static_cast<int>(
218         CecMessageType::REPORT_ARC_TERMINATED),
219         "CecMessageType::REPORT_ARC_TERMINATED must match legacy value.");
220 static_assert(CEC_MESSAGE_REQUEST_ARC_INITIATION == static_cast<int>(
221         CecMessageType::REQUEST_ARC_INITIATION),
222         "CecMessageType::REQUEST_ARC_INITIATION must match legacy value.");
223 static_assert(CEC_MESSAGE_REQUEST_ARC_TERMINATION == static_cast<int>(
224         CecMessageType::REQUEST_ARC_TERMINATION),
225         "CecMessageType::REQUEST_ARC_TERMINATION must match legacy value.");
226 static_assert(CEC_MESSAGE_TERMINATE_ARC == static_cast<int>(CecMessageType::TERMINATE_ARC),
227         "CecMessageType::TERMINATE_ARC must match legacy value.");
228 static_assert(CEC_MESSAGE_ABORT == static_cast<int>(CecMessageType::ABORT),
229         "CecMessageType::ABORT must match legacy value.");
230 
231 static_assert(ABORT_UNRECOGNIZED_MODE == static_cast<int>(AbortReason::UNRECOGNIZED_MODE),
232         "AbortReason::UNRECOGNIZED_MODE must match legacy value.");
233 static_assert(ABORT_NOT_IN_CORRECT_MODE == static_cast<int>(AbortReason::NOT_IN_CORRECT_MODE),
234         "AbortReason::NOT_IN_CORRECT_MODE must match legacy value.");
235 static_assert(ABORT_CANNOT_PROVIDE_SOURCE == static_cast<int>(AbortReason::CANNOT_PROVIDE_SOURCE),
236         "AbortReason::CANNOT_PROVIDE_SOURCE must match legacy value.");
237 static_assert(ABORT_INVALID_OPERAND == static_cast<int>(AbortReason::INVALID_OPERAND),
238         "AbortReason::INVALID_OPERAND must match legacy value.");
239 static_assert(ABORT_REFUSED == static_cast<int>(AbortReason::REFUSED),
240         "AbortReason::REFUSED must match legacy value.");
241 static_assert(ABORT_UNABLE_TO_DETERMINE == static_cast<int>(AbortReason::UNABLE_TO_DETERMINE),
242         "AbortReason::UNABLE_TO_DETERMINE must match legacy value.");
243 
244 static_assert(HDMI_RESULT_SUCCESS == static_cast<int>(SendMessageResult::SUCCESS),
245         "SendMessageResult::SUCCESS must match legacy value.");
246 static_assert(HDMI_RESULT_NACK == static_cast<int>(SendMessageResult::NACK),
247         "SendMessageResult::NACK must match legacy value.");
248 static_assert(HDMI_RESULT_BUSY == static_cast<int>(SendMessageResult::BUSY),
249         "SendMessageResult::BUSY must match legacy value.");
250 static_assert(HDMI_RESULT_FAIL == static_cast<int>(SendMessageResult::FAIL),
251         "SendMessageResult::FAIL must match legacy value.");
252 
253 static_assert(HDMI_INPUT == static_cast<int>(HdmiPortType::INPUT),
254         "HdmiPortType::INPUT must match legacy value.");
255 static_assert(HDMI_OUTPUT == static_cast<int>(HdmiPortType::OUTPUT),
256         "HdmiPortType::OUTPUT must match legacy value.");
257 
258 static_assert(HDMI_OPTION_WAKEUP == static_cast<int>(OptionKey::WAKEUP),
259         "OptionKey::WAKEUP must match legacy value.");
260 static_assert(HDMI_OPTION_ENABLE_CEC == static_cast<int>(OptionKey::ENABLE_CEC),
261         "OptionKey::ENABLE_CEC must match legacy value.");
262 static_assert(HDMI_OPTION_SYSTEM_CEC_CONTROL == static_cast<int>(OptionKey::SYSTEM_CEC_CONTROL),
263         "OptionKey::SYSTEM_CEC_CONTROL must match legacy value.");
264 
265 sp<IHdmiCecCallback> HdmiCec::mCallback = nullptr;
266 
HdmiCec(hdmi_cec_device_t * device)267 HdmiCec::HdmiCec(hdmi_cec_device_t* device) : mDevice(device) {}
268 
269 // Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
addLogicalAddress(CecLogicalAddress addr)270 Return<Result> HdmiCec::addLogicalAddress(CecLogicalAddress addr) {
271     int ret = mDevice->add_logical_address(mDevice, static_cast<cec_logical_address_t>(addr));
272     switch (ret) {
273         case 0:
274             return Result::SUCCESS;
275         case -EINVAL:
276             return Result::FAILURE_INVALID_ARGS;
277         case -ENOTSUP:
278             return Result::FAILURE_NOT_SUPPORTED;
279         case -EBUSY:
280             return Result::FAILURE_BUSY;
281         default:
282             return Result::FAILURE_UNKNOWN;
283     }
284 }
285 
clearLogicalAddress()286 Return<void> HdmiCec::clearLogicalAddress() {
287     mDevice->clear_logical_address(mDevice);
288     return Void();
289 }
290 
getPhysicalAddress(getPhysicalAddress_cb _hidl_cb)291 Return<void> HdmiCec::getPhysicalAddress(getPhysicalAddress_cb _hidl_cb) {
292     uint16_t addr;
293     int ret = mDevice->get_physical_address(mDevice, &addr);
294     switch (ret) {
295         case 0:
296             _hidl_cb(Result::SUCCESS, addr);
297             break;
298         case -EBADF:
299             _hidl_cb(Result::FAILURE_INVALID_STATE, addr);
300             break;
301         default:
302             _hidl_cb(Result::FAILURE_UNKNOWN, addr);
303             break;
304     }
305     return Void();
306 }
307 
sendMessage(const CecMessage & message)308 Return<SendMessageResult> HdmiCec::sendMessage(const CecMessage& message) {
309     cec_message_t legacyMessage {
310         .initiator = static_cast<cec_logical_address_t>(message.initiator),
311         .destination = static_cast<cec_logical_address_t>(message.destination),
312         .length = message.body.size(),
313     };
314     for (size_t i = 0; i < message.body.size(); ++i) {
315         legacyMessage.body[i] = static_cast<unsigned char>(message.body[i]);
316     }
317     return static_cast<SendMessageResult>(mDevice->send_message(mDevice, &legacyMessage));
318 }
319 
setCallback(const sp<IHdmiCecCallback> & callback)320 Return<void> HdmiCec::setCallback(const sp<IHdmiCecCallback>& callback) {
321     if (mCallback != nullptr) {
322         mCallback->unlinkToDeath(this);
323         mCallback = nullptr;
324     }
325 
326     if (callback != nullptr) {
327         mCallback = callback;
328         mCallback->linkToDeath(this, 0 /*cookie*/);
329         mDevice->register_event_callback(mDevice, eventCallback, nullptr);
330     }
331     return Void();
332 }
333 
getCecVersion()334 Return<int32_t> HdmiCec::getCecVersion() {
335     int version;
336     mDevice->get_version(mDevice, &version);
337     return static_cast<int32_t>(version);
338 }
339 
getVendorId()340 Return<uint32_t> HdmiCec::getVendorId() {
341     uint32_t vendor_id;
342     mDevice->get_vendor_id(mDevice, &vendor_id);
343     return vendor_id;
344 }
345 
getPortInfo(getPortInfo_cb _hidl_cb)346 Return<void> HdmiCec::getPortInfo(getPortInfo_cb _hidl_cb) {
347     struct hdmi_port_info* legacyPorts;
348     int numPorts;
349     hidl_vec<HdmiPortInfo> portInfos;
350     mDevice->get_port_info(mDevice, &legacyPorts, &numPorts);
351     portInfos.resize(numPorts);
352     for (int i = 0; i < numPorts; ++i) {
353         portInfos[i] = {
354             .type = static_cast<HdmiPortType>(legacyPorts[i].type),
355             .portId = static_cast<uint32_t>(legacyPorts[i].port_id),
356             .cecSupported = legacyPorts[i].cec_supported != 0,
357             .arcSupported = legacyPorts[i].arc_supported != 0,
358             .physicalAddress = legacyPorts[i].physical_address
359         };
360     }
361     _hidl_cb(portInfos);
362     return Void();
363 }
364 
setOption(OptionKey key,bool value)365 Return<void> HdmiCec::setOption(OptionKey key, bool value) {
366     mDevice->set_option(mDevice, static_cast<int>(key), value ? 1 : 0);
367     return Void();
368 }
369 
setLanguage(const hidl_string & language)370 Return<void> HdmiCec::setLanguage(const hidl_string& language) {
371     if (language.size() != 3) {
372         LOG(ERROR) << "Wrong language code: expected 3 letters, but it was " << language.size()
373                 << ".";
374         return Void();
375     }
376     const char *languageStr = language.c_str();
377     int convertedLanguage = ((languageStr[0] & 0xFF) << 16)
378             | ((languageStr[1] & 0xFF) << 8)
379             | (languageStr[2] & 0xFF);
380     mDevice->set_option(mDevice, HDMI_OPTION_SET_LANG, convertedLanguage);
381     return Void();
382 }
383 
enableAudioReturnChannel(int32_t portId,bool enable)384 Return<void> HdmiCec::enableAudioReturnChannel(int32_t portId, bool enable) {
385     mDevice->set_audio_return_channel(mDevice, portId, enable ? 1 : 0);
386     return Void();
387 }
388 
isConnected(int32_t portId)389 Return<bool> HdmiCec::isConnected(int32_t portId) {
390     return mDevice->is_connected(mDevice, portId) > 0;
391 }
392 
393 
HIDL_FETCH_IHdmiCec(const char * hal)394 IHdmiCec* HIDL_FETCH_IHdmiCec(const char* hal) {
395     hdmi_cec_device_t* hdmi_cec_device;
396     int ret = 0;
397     const hw_module_t* hw_module = nullptr;
398 
399     ret = hw_get_module (HDMI_CEC_HARDWARE_MODULE_ID, &hw_module);
400     if (ret == 0) {
401         ret = hdmi_cec_open (hw_module, &hdmi_cec_device);
402         if (ret != 0) {
403             LOG(ERROR) << "hdmi_cec_open " << hal << " failed: " << ret;
404         }
405     } else {
406         LOG(ERROR) << "hw_get_module " << hal << " failed: " << ret;
407     }
408 
409     if (ret == 0) {
410         return new HdmiCec(hdmi_cec_device);
411     } else {
412         LOG(ERROR) << "Passthrough failed to load legacy HAL.";
413         return nullptr;
414     }
415 }
416 
417 }  // namespace implementation
418 }  // namespace V1_0
419 }  // namespace cec
420 }  // namespace tv
421 }  // namespace hardware
422 }  // namespace android
423