summaryrefslogtreecommitdiff
path: root/tv_input.cpp (plain)
blob: 9eb47818963bd7ac2bed176903a8030856b32304
1/*
2 * Copyright 2014 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 "TvInput"
18#include <fcntl.h>
19#include <errno.h>
20
21#include <cutils/log.h>
22#include <cutils/native_handle.h>
23
24#include <hardware/tv_input.h>
25#include "tvapi/android/tv/CTv.h"
26#include "tv_callback.h"
27#include "tvapi/android/include/tvcmd.h"
28#include <ui/GraphicBufferMapper.h>
29#include <ui/GraphicBuffer.h>
30/*****************************************************************************/
31
32#define LOGD(...) \
33{ \
34__android_log_print(ANDROID_LOG_DEBUG, "tv_input", __VA_ARGS__); }
35
36#ifndef container_of
37#define container_of(ptr, type, member) ({ \
38 const typeof(((type *) 0)->member) *__mptr = (ptr); \
39 (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
40#endif
41
42struct sideband_handle_t {
43 native_handle_t nativeHandle;
44 int identflag;
45 int usage;
46};
47
48typedef struct tv_input_private {
49 tv_input_device_t device;
50 const tv_input_callback_ops_t *callback;
51 void *callback_data;
52 CTv *mpTv;
53 TvCallback *tvcallback;
54} tv_input_private_t;
55
56
57static int notify_ATV_device_available(tv_input_private_t *priv)
58{
59 tv_input_event_t event;
60 event.device_info.device_id = SOURCE_TV;
61 event.device_info.type = TV_INPUT_TYPE_TUNER;
62 event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE;
63 event.device_info.audio_type = AUDIO_DEVICE_NONE;
64 event.device_info.audio_address = NULL;
65 priv->callback->notify(&priv->device, &event, priv->callback_data);
66 return 0;
67}
68
69static int notify_ATV_stream_configurations_change(tv_input_private_t *priv)
70{
71 tv_input_event_t event;
72 event.device_info.device_id = SOURCE_TV;
73 event.device_info.type = TV_INPUT_TYPE_TUNER;
74 event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED;
75 event.device_info.audio_type = AUDIO_DEVICE_NONE;
76 event.device_info.audio_address = NULL;
77 priv->callback->notify(&priv->device, &event, priv->callback_data);
78 return 0;
79}
80
81static int notify_DTV_device_available(tv_input_private_t *priv)
82{
83 tv_input_event_t event;
84 event.device_info.device_id = SOURCE_DTV;
85 event.device_info.type = TV_INPUT_TYPE_TUNER;
86 event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE;
87 event.device_info.audio_type = AUDIO_DEVICE_NONE;
88 event.device_info.audio_address = NULL;
89 priv->callback->notify(&priv->device, &event, priv->callback_data);
90 return 0;
91}
92
93static int notify_DTV_stream_configurations_change(tv_input_private_t *priv)
94{
95 tv_input_event_t event;
96 event.device_info.device_id = SOURCE_DTV;
97 event.device_info.type = TV_INPUT_TYPE_TUNER;
98 event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED;
99 event.device_info.audio_type = AUDIO_DEVICE_NONE;
100 event.device_info.audio_address = NULL;
101 priv->callback->notify(&priv->device, &event, priv->callback_data);
102 return 0;
103}
104
105void TvIputHal_ChannelConl(tv_input_private_t *priv, int ops_type, int device_id)
106{
107 if (priv->mpTv) {
108 if (ops_type) {
109 LOGD ( "%s\, OpenSourceSwitchInput id = %d\n", __FUNCTION__, device_id );
110 priv->mpTv->StartTv();
111 priv->mpTv->SwitchSourceInput((tv_source_input_t) device_id);
112 } else {
113 if (priv->mpTv->GetCurrentSourceInput() == device_id) {
114 LOGD ( "%s\, StopSourceSwitchInput id = %d\n", __FUNCTION__, device_id );
115 priv->mpTv->StopTv();
116 }
117 }
118 }
119}
120
121static int notify_AV_device_available(tv_input_private_t *priv, tv_source_input_t source_input, int type)
122{
123 tv_input_event_t event;
124 event.device_info.device_id = source_input;
125 event.device_info.type = TV_INPUT_TYPE_COMPONENT;
126 event.type = type;
127 event.device_info.audio_type = AUDIO_DEVICE_NONE;
128 event.device_info.audio_address = NULL;
129 priv->callback->notify(&priv->device, &event, priv->callback_data);
130 return 0;
131}
132
133static int notify_AV_stream_configurations_change(tv_input_private_t *priv, tv_source_input_t source_input)
134{
135 tv_input_event_t event;
136 event.device_info.device_id = source_input;
137 event.device_info.type = TV_INPUT_TYPE_COMPONENT;
138 event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED;
139 event.device_info.audio_type = AUDIO_DEVICE_NONE;
140 event.device_info.audio_address = NULL;
141 priv->callback->notify(&priv->device, &event, priv->callback_data);
142 return 0;
143}
144
145static int notify_HDMI_device_available(tv_input_private_t *priv, tv_source_input_t source_input, uint32_t port_id, int type)
146{
147 tv_input_event_t event;
148 event.device_info.device_id = source_input;
149 event.device_info.type = TV_INPUT_TYPE_HDMI;
150 event.type = type;
151 event.device_info.hdmi.port_id = port_id;
152 event.device_info.audio_type = AUDIO_DEVICE_NONE;
153 event.device_info.audio_address = NULL;
154 priv->callback->notify(&priv->device, &event, priv->callback_data);
155 return 0;
156}
157
158static int notify_HDMI_stream_configurations_change(tv_input_private_t *priv, tv_source_input_t source_input, uint32_t port_id)
159{
160 tv_input_event_t event;
161 event.device_info.device_id = source_input;
162 event.device_info.type = TV_INPUT_TYPE_HDMI;
163 event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED;
164 event.device_info.hdmi.port_id = port_id;
165 event.device_info.audio_type = AUDIO_DEVICE_NONE;
166 event.device_info.audio_address = NULL;
167 priv->callback->notify(&priv->device, &event, priv->callback_data);
168 return 0;
169}
170
171
172void TvCallback::onTvEvent (int32_t msgType, const Parcel &p)
173{
174 tv_input_private_t *priv = (tv_input_private_t *)(mPri);
175 switch (msgType) {
176 case SOURCE_CONNECT_CALLBACK: {
177 int source = p.readInt32();
178 int connectState = p.readInt32();
179 LOGD("TvCallback::onTvEvent source = %d, status = %d", source, connectState)
180 if ( connectState == 1) {
181 switch (source) {
182 case SOURCE_HDMI1:
183 case SOURCE_HDMI2:
184 case SOURCE_HDMI3: {
185 notify_HDMI_device_available(priv, (tv_source_input_t)source, 1, TV_INPUT_EVENT_DEVICE_AVAILABLE);
186 notify_HDMI_stream_configurations_change(priv, (tv_source_input_t)source, 1);
187 break;
188 }
189 case SOURCE_AV1:
190 case SOURCE_AV2: {
191 notify_AV_device_available(priv, (tv_source_input_t)source, TV_INPUT_EVENT_DEVICE_AVAILABLE);
192 notify_AV_stream_configurations_change(priv, (tv_source_input_t)source);
193 break;
194 }
195 default:
196 break;
197 }
198 } else {//out
199 switch (source) {
200 case SOURCE_HDMI1:
201 case SOURCE_HDMI2:
202 case SOURCE_HDMI3: {
203 notify_HDMI_device_available(priv, (tv_source_input_t)source, 1, TV_INPUT_EVENT_DEVICE_UNAVAILABLE);
204 break;
205 }
206 case SOURCE_AV1:
207 case SOURCE_AV2: {
208 notify_AV_device_available(priv, (tv_source_input_t)source, TV_INPUT_EVENT_DEVICE_UNAVAILABLE);
209 break;
210 }
211 default:
212 break;
213 }
214 }
215 //tv_input_event_t event;
216
217 break;
218 }
219 default:
220 break;
221 }
222}
223
224#define NORMAL_STREAM_ID 1
225#define FRAME_CAPTURE_STREAM_ID 2
226static tv_stream_config_t mconfig[2];
227static int get_stream_configs(int dev_id, int *num_configurations, const tv_stream_config_t **configs)
228{
229 switch (dev_id) {
230 case SOURCE_TV:
231 mconfig[0].stream_id = NORMAL_STREAM_ID;
232 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
233 mconfig[0].max_video_width = 1920;
234 mconfig[0].max_video_height = 1080;
235 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
236 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
237 mconfig[1].max_video_width = 1920;
238 mconfig[1].max_video_height = 1080;
239 *num_configurations = 2;
240 *configs = mconfig;
241 break;
242 case SOURCE_DTV:
243 mconfig[0].stream_id = NORMAL_STREAM_ID;
244 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
245 mconfig[0].max_video_width = 1920;
246 mconfig[0].max_video_height = 1080;
247 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
248 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
249 mconfig[1].max_video_width = 1920;
250 mconfig[1].max_video_height = 1080;
251 *num_configurations = 2;
252 *configs = mconfig;
253 break;
254 case SOURCE_AV1:
255 case SOURCE_AV2:
256 mconfig[0].stream_id = NORMAL_STREAM_ID;
257 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
258 mconfig[0].max_video_width = 1920;
259 mconfig[0].max_video_height = 1080;
260 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
261 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
262 mconfig[1].max_video_width = 1920;
263 mconfig[1].max_video_height = 1080;
264 *num_configurations = 2;
265 *configs = mconfig;
266 break;
267 case SOURCE_HDMI1:
268 mconfig[0].stream_id = NORMAL_STREAM_ID;
269 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
270 mconfig[0].max_video_width = 1920;
271 mconfig[0].max_video_height = 1080;
272 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
273 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
274 mconfig[1].max_video_width = 1920;
275 mconfig[1].max_video_height = 1080;
276 *num_configurations = 2;
277 *configs = mconfig;
278 break;
279 case SOURCE_HDMI2:
280 mconfig[0].stream_id = NORMAL_STREAM_ID;
281 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
282 mconfig[0].max_video_width = 1920;
283 mconfig[0].max_video_height = 1080;
284 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
285 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
286 mconfig[1].max_video_width = 1920;
287 mconfig[1].max_video_height = 1080;
288 *num_configurations = 2;
289 *configs = mconfig;
290 break;
291 case SOURCE_HDMI3:
292 mconfig[0].stream_id = NORMAL_STREAM_ID;
293 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
294 mconfig[0].max_video_width = 1920;
295 mconfig[0].max_video_height = 1080;
296 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
297 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
298 mconfig[1].max_video_width = 1920;
299 mconfig[1].max_video_height = 1080;
300 *num_configurations = 2;
301 *configs = mconfig;
302 break;
303 default:
304 break;
305 }
306 return 0;
307}
308
309static int get_tv_stream(tv_stream_t *stream)
310{
311 static struct sideband_handle_t *tvstream = NULL;
312 if (stream->stream_id == NORMAL_STREAM_ID) {
313 if ( !tvstream ) {
314 tvstream = (struct sideband_handle_t *)native_handle_create(0, 2);
315 if ( !tvstream ) {
316 return -EINVAL;
317 }
318 }
319 tvstream->identflag = 0xabcdcdef; //magic word
320 tvstream->usage = GRALLOC_USAGE_AML_VIDEO_OVERLAY;
321 stream->type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE;
322 stream->sideband_stream_source_handle = (native_handle_t *)tvstream;
323 } else if (stream->stream_id == NORMAL_STREAM_ID) {
324 stream->type = TV_STREAM_TYPE_BUFFER_PRODUCER;
325 }
326 return 0;
327}
328
329static int tv_input_device_open(const struct hw_module_t *module,
330 const char *name, struct hw_device_t **device);
331
332static struct hw_module_methods_t tv_input_module_methods = {
333open:
334 tv_input_device_open
335};
336
337tv_input_module_t HAL_MODULE_INFO_SYM = {
338common:
339 {
340tag:
341 HARDWARE_MODULE_TAG,
342 version_major: 0,
343 version_minor: 1,
344id:
345 TV_INPUT_HARDWARE_MODULE_ID,
346name: "TVInput module"
347 ,
348author: "Amlogic"
349 ,
350methods:
351 &tv_input_module_methods,
352 }
353};
354
355/*****************************************************************************/
356
357static int tv_input_initialize(struct tv_input_device *dev,
358 const tv_input_callback_ops_t *callback, void *data)
359{
360 if (dev == NULL || callback == NULL) {
361 return -EINVAL;
362 }
363 tv_input_private_t *priv = (tv_input_private_t *)dev;
364 if (priv->callback != NULL) {
365 return -EEXIST;
366 }
367 priv->callback = callback;
368 priv->callback_data = data;
369 /* ATV_DEVICE_AVAILABLE */
370 notify_ATV_device_available(priv);
371 notify_ATV_stream_configurations_change(priv);
372 /* DTV_DEVICE_AVAILABLE */
373 notify_DTV_device_available(priv);
374 notify_DTV_stream_configurations_change(priv);
375
376 if (priv->mpTv->GetHdmiAvHotplugDetectOnoff()) {
377 /* AV1_DEVICE_AVAILABLE */
378 int status = priv->mpTv->GetSourceConnectStatus(SOURCE_AV1);
379 if (status == 1) { //IN
380 notify_AV_device_available(priv, SOURCE_AV1, TV_INPUT_EVENT_DEVICE_AVAILABLE);
381 notify_AV_stream_configurations_change(priv, SOURCE_AV1);
382 }
383
384 /* AV2_DEVICE_AVAILABLE */
385 status = priv->mpTv->GetSourceConnectStatus(SOURCE_AV2);
386 if (status == 1) { //IN
387 notify_AV_device_available(priv, SOURCE_AV2, TV_INPUT_EVENT_DEVICE_AVAILABLE);
388 notify_AV_stream_configurations_change(priv, SOURCE_AV2);
389 }
390
391 /* HDMI1_DEVICE_AVAILABLE */
392 status = priv->mpTv->GetSourceConnectStatus(SOURCE_HDMI1);
393 if (status == 1) { //IN
394 notify_HDMI_device_available(priv, SOURCE_HDMI1, 1, TV_INPUT_EVENT_DEVICE_AVAILABLE);
395 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI1, 0);
396 }
397
398 /* HDMI2_DEVICE_AVAILABLE */
399 status = priv->mpTv->GetSourceConnectStatus(SOURCE_HDMI2);
400 if (status == 1) { //IN
401 notify_HDMI_device_available(priv, SOURCE_HDMI2, 1, TV_INPUT_EVENT_DEVICE_AVAILABLE);
402 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI2, 1);
403 }
404
405 /* HDMI3_DEVICE_AVAILABLE */
406 status = priv->mpTv->GetSourceConnectStatus(SOURCE_HDMI3);
407 if (status == 1) { //IN
408 notify_HDMI_device_available(priv, SOURCE_HDMI3, 2, TV_INPUT_EVENT_DEVICE_AVAILABLE);
409 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI3, 2);
410 }
411
412 priv->mpTv->setTvObserver(priv->tvcallback);
413 } else {
414 /* AV1_DEVICE_AVAILABLE */
415 notify_AV_device_available(priv, SOURCE_AV1, TV_INPUT_EVENT_DEVICE_AVAILABLE);
416 notify_AV_stream_configurations_change(priv, SOURCE_AV1);
417 /* AV2_DEVICE_AVAILABLE */
418 notify_AV_device_available(priv, SOURCE_AV2, TV_INPUT_EVENT_DEVICE_AVAILABLE);
419 notify_AV_stream_configurations_change(priv, SOURCE_AV2);
420 /* HDMI1_DEVICE_AVAILABLE */
421 notify_HDMI_device_available(priv, SOURCE_HDMI1, 1, TV_INPUT_EVENT_DEVICE_AVAILABLE);
422 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI1, 0);
423 /* HDMI2_DEVICE_AVAILABLE */
424 notify_HDMI_device_available(priv, SOURCE_HDMI2, 1, TV_INPUT_EVENT_DEVICE_AVAILABLE);
425 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI2, 1);
426 /* HDMI3_DEVICE_AVAILABLE */
427 notify_HDMI_device_available(priv, SOURCE_HDMI3, 2, TV_INPUT_EVENT_DEVICE_AVAILABLE);
428 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI3, 2);
429 }
430 return 0;
431}
432
433static int tv_input_get_stream_configurations(const struct tv_input_device *dev,
434 int device_id, int *num_configurations,
435 const tv_stream_config_t **configs)
436{
437 if (get_stream_configs(device_id, num_configurations, configs) == 0) {
438 return 0;
439 }
440 return -EINVAL;
441}
442
443static int tv_input_open_stream(struct tv_input_device *dev, int device_id,
444 tv_stream_t *stream)
445{
446 tv_input_private_t *priv = (tv_input_private_t *)dev;
447 if (priv) {
448 if (get_tv_stream(stream) != 0) {
449 return -EINVAL;
450 }
451 if (stream->stream_id == NORMAL_STREAM_ID) {
452 TvIputHal_ChannelConl(priv, 1, device_id);
453 return 0;
454 } else if (stream->stream_id == FRAME_CAPTURE_STREAM_ID) {
455 return 0;
456 }
457 }
458 return -EINVAL;
459}
460
461static int tv_input_close_stream(struct tv_input_device *dev, int device_id,
462 int stream_id)
463{
464 tv_input_private_t *priv = (tv_input_private_t *)dev;
465 if (stream_id == NORMAL_STREAM_ID) {
466 TvIputHal_ChannelConl(priv, 0, device_id);
467 return 0;
468 } else if (stream_id == FRAME_CAPTURE_STREAM_ID) {
469 return 0;
470 }
471 return -EINVAL;
472}
473
474static int tv_input_request_capture(
475 struct tv_input_device *dev, int device_id, int stream_id, buffer_handle_t buffer, uint32_t seq)
476{
477 return -EINVAL;
478}
479
480static int tv_input_cancel_capture(struct tv_input_device *, int, int, uint32_t)
481{
482 return -EINVAL;
483}
484
485/*****************************************************************************/
486
487static int tv_input_device_close(struct hw_device_t *dev)
488{
489 tv_input_private_t *priv = (tv_input_private_t *)dev;
490 if (priv) {
491 if (priv->mpTv) {
492 delete priv->mpTv;
493 }
494 free(priv);
495 }
496 return 0;
497}
498
499/*****************************************************************************/
500
501static int tv_input_device_open(const struct hw_module_t *module,
502 const char *name, struct hw_device_t **device)
503{
504 int status = -EINVAL;
505 if (!strcmp(name, TV_INPUT_DEFAULT_DEVICE)) {
506 tv_input_private_t *dev = (tv_input_private_t *)malloc(sizeof(*dev));
507
508 /* initialize our state here */
509 memset(dev, 0, sizeof(*dev));
510 dev->mpTv = new CTv();
511 dev->tvcallback = new TvCallback(dev);
512 /* initialize the procs */
513 dev->device.common.tag = HARDWARE_DEVICE_TAG;
514 dev->device.common.version = TV_INPUT_DEVICE_API_VERSION_0_1;
515 dev->device.common.module = const_cast<hw_module_t *>(module);
516 dev->device.common.close = tv_input_device_close;
517
518 dev->device.initialize = tv_input_initialize;
519 dev->device.get_stream_configurations =
520 tv_input_get_stream_configurations;
521 dev->device.open_stream = tv_input_open_stream;
522 dev->device.close_stream = tv_input_close_stream;
523 dev->device.request_capture = tv_input_request_capture;
524 dev->device.cancel_capture = tv_input_cancel_capture;
525
526 *device = &dev->device.common;
527 status = 0;
528 }
529 return status;
530}
531