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.input (at) 1.0-service" 18 #include <android-base/logging.h> 19 20 #include "TvInput.h" 21 22 namespace android { 23 namespace hardware { 24 namespace tv { 25 namespace input { 26 namespace V1_0 { 27 namespace implementation { 28 29 static_assert(TV_INPUT_TYPE_OTHER_HARDWARE == static_cast<int>(TvInputType::OTHER), 30 "TvInputType::OTHER must match legacy value."); 31 static_assert(TV_INPUT_TYPE_TUNER == static_cast<int>(TvInputType::TUNER), 32 "TvInputType::TUNER must match legacy value."); 33 static_assert(TV_INPUT_TYPE_COMPOSITE == static_cast<int>(TvInputType::COMPOSITE), 34 "TvInputType::COMPOSITE must match legacy value."); 35 static_assert(TV_INPUT_TYPE_SVIDEO == static_cast<int>(TvInputType::SVIDEO), 36 "TvInputType::SVIDEO must match legacy value."); 37 static_assert(TV_INPUT_TYPE_SCART == static_cast<int>(TvInputType::SCART), 38 "TvInputType::SCART must match legacy value."); 39 static_assert(TV_INPUT_TYPE_COMPONENT == static_cast<int>(TvInputType::COMPONENT), 40 "TvInputType::COMPONENT must match legacy value."); 41 static_assert(TV_INPUT_TYPE_VGA == static_cast<int>(TvInputType::VGA), 42 "TvInputType::VGA must match legacy value."); 43 static_assert(TV_INPUT_TYPE_DVI == static_cast<int>(TvInputType::DVI), 44 "TvInputType::DVI must match legacy value."); 45 static_assert(TV_INPUT_TYPE_HDMI == static_cast<int>(TvInputType::HDMI), 46 "TvInputType::HDMI must match legacy value."); 47 static_assert(TV_INPUT_TYPE_DISPLAY_PORT == static_cast<int>(TvInputType::DISPLAY_PORT), 48 "TvInputType::DISPLAY_PORT must match legacy value."); 49 50 static_assert(TV_INPUT_EVENT_DEVICE_AVAILABLE == static_cast<int>( 51 TvInputEventType::DEVICE_AVAILABLE), 52 "TvInputEventType::DEVICE_AVAILABLE must match legacy value."); 53 static_assert(TV_INPUT_EVENT_DEVICE_UNAVAILABLE == static_cast<int>( 54 TvInputEventType::DEVICE_UNAVAILABLE), 55 "TvInputEventType::DEVICE_UNAVAILABLE must match legacy value."); 56 static_assert(TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED == static_cast<int>( 57 TvInputEventType::STREAM_CONFIGURATIONS_CHANGED), 58 "TvInputEventType::STREAM_CONFIGURATIONS_CHANGED must match legacy value."); 59 60 sp<ITvInputCallback> TvInput::mCallback = nullptr; 61 62 TvInput::TvInput(tv_input_device_t* device) : mDevice(device) { 63 mCallbackOps.notify = &TvInput::notify; 64 } 65 66 TvInput::~TvInput() { 67 if (mDevice != nullptr) { 68 free(mDevice); 69 } 70 } 71 72 // Methods from ::android::hardware::tv_input::V1_0::ITvInput follow. 73 Return<void> TvInput::setCallback(const sp<ITvInputCallback>& callback) { 74 mCallback = callback; 75 if (mCallback != nullptr) { 76 mDevice->initialize(mDevice, &mCallbackOps, nullptr); 77 } 78 return Void(); 79 } 80 81 Return<void> TvInput::getStreamConfigurations(int32_t deviceId, getStreamConfigurations_cb cb) { 82 int32_t configCount = 0; 83 const tv_stream_config_t* configs = nullptr; 84 int ret = mDevice->get_stream_configurations(mDevice, deviceId, &configCount, &configs); 85 Result res = Result::UNKNOWN; 86 hidl_vec<TvStreamConfig> tvStreamConfigs; 87 if (ret == 0) { 88 res = Result::OK; 89 tvStreamConfigs.resize(getSupportedConfigCount(configCount, configs)); 90 int32_t pos = 0; 91 for (int32_t i = 0; i < configCount; ++i) { 92 if (isSupportedStreamType(configs[i].type)) { 93 tvStreamConfigs[pos].streamId = configs[i].stream_id; 94 tvStreamConfigs[pos].maxVideoWidth = configs[i].max_video_width; 95 tvStreamConfigs[pos].maxVideoHeight = configs[i].max_video_height; 96 ++pos; 97 } 98 } 99 } else if (ret == -EINVAL) { 100 res = Result::INVALID_ARGUMENTS; 101 } 102 cb(res, tvStreamConfigs); 103 return Void(); 104 } 105 106 Return<void> TvInput::openStream(int32_t deviceId, int32_t streamId, openStream_cb cb) { 107 tv_stream_t stream; 108 stream.stream_id = streamId; 109 int ret = mDevice->open_stream(mDevice, deviceId, &stream); 110 Result res = Result::UNKNOWN; 111 native_handle_t* sidebandStream = nullptr; 112 if (ret == 0) { 113 if (isSupportedStreamType(stream.type)) { 114 res = Result::OK; 115 sidebandStream = stream.sideband_stream_source_handle; 116 } 117 } else { 118 if (ret == -EBUSY) { 119 res = Result::NO_RESOURCE; 120 } else if (ret == -EEXIST) { 121 res = Result::INVALID_STATE; 122 } else if (ret == -EINVAL) { 123 res = Result::INVALID_ARGUMENTS; 124 } 125 } 126 cb(res, sidebandStream); 127 return Void(); 128 } 129 130 Return<Result> TvInput::closeStream(int32_t deviceId, int32_t streamId) { 131 int ret = mDevice->close_stream(mDevice, deviceId, streamId); 132 Result res = Result::UNKNOWN; 133 if (ret == 0) { 134 res = Result::OK; 135 } else if (ret == -ENOENT) { 136 res = Result::INVALID_STATE; 137 } else if (ret == -EINVAL) { 138 res = Result::INVALID_ARGUMENTS; 139 } 140 return res; 141 } 142 143 // static 144 void TvInput::notify(struct tv_input_device* __unused, tv_input_event_t* event, 145 void* __unused) { 146 if (mCallback != nullptr && event != nullptr) { 147 // Capturing is no longer supported. 148 if (event->type >= TV_INPUT_EVENT_CAPTURE_SUCCEEDED) { 149 return; 150 } 151 TvInputEvent tvInputEvent; 152 tvInputEvent.type = static_cast<TvInputEventType>(event->type); 153 tvInputEvent.deviceInfo.deviceId = event->device_info.device_id; 154 tvInputEvent.deviceInfo.type = static_cast<TvInputType>( 155 event->device_info.type); 156 tvInputEvent.deviceInfo.portId = event->device_info.hdmi.port_id; 157 tvInputEvent.deviceInfo.cableConnectionStatus = CableConnectionStatus::UNKNOWN; 158 // TODO: Ensure the legacy audio type code is the same once audio HAL default 159 // implementation is ready. 160 tvInputEvent.deviceInfo.audioType = static_cast<AudioDevice>( 161 event->device_info.audio_type); 162 memset(tvInputEvent.deviceInfo.audioAddress.data(), 0, 163 tvInputEvent.deviceInfo.audioAddress.size()); 164 const char* address = event->device_info.audio_address; 165 if (address != nullptr) { 166 size_t size = strlen(address); 167 if (size > tvInputEvent.deviceInfo.audioAddress.size()) { 168 LOG(ERROR) << "Audio address is too long. Address:" << address << ""; 169 return; 170 } 171 for (size_t i = 0; i < size; ++i) { 172 tvInputEvent.deviceInfo.audioAddress[i] = 173 static_cast<uint8_t>(event->device_info.audio_address[i]); 174 } 175 } 176 mCallback->notify(tvInputEvent); 177 } 178 } 179 180 // static 181 uint32_t TvInput::getSupportedConfigCount(uint32_t configCount, 182 const tv_stream_config_t* configs) { 183 uint32_t supportedConfigCount = 0; 184 for (uint32_t i = 0; i < configCount; ++i) { 185 if (isSupportedStreamType(configs[i].type)) { 186 supportedConfigCount++; 187 } 188 } 189 return supportedConfigCount; 190 } 191 192 // static 193 bool TvInput::isSupportedStreamType(int type) { 194 // Buffer producer type is no longer supported. 195 return type != TV_STREAM_TYPE_BUFFER_PRODUCER; 196 } 197 198 ITvInput* HIDL_FETCH_ITvInput(const char* /* name */) { 199 int ret = 0; 200 const hw_module_t* hw_module = nullptr; 201 tv_input_device_t* input_device; 202 ret = hw_get_module(TV_INPUT_HARDWARE_MODULE_ID, &hw_module); 203 if (ret == 0 && hw_module->methods->open != nullptr) { 204 ret = hw_module->methods->open(hw_module, TV_INPUT_DEFAULT_DEVICE, 205 reinterpret_cast<hw_device_t**>(&input_device)); 206 if (ret == 0) { 207 return new TvInput(input_device); 208 } 209 else { 210 LOG(ERROR) << "Passthrough failed to load legacy HAL."; 211 return nullptr; 212 } 213 } 214 else { 215 LOG(ERROR) << "hw_get_module " << TV_INPUT_HARDWARE_MODULE_ID 216 << " failed: " << ret; 217 return nullptr; 218 } 219 } 220 221 } // namespace implementation 222 } // namespace V1_0 223 } // namespace input 224 } // namespace tv 225 } // namespace hardware 226 } // namespace android 227