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