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