summaryrefslogtreecommitdiff
path: root/tv_input.cpp (plain)
blob: 7da87107cb95ae44079ce2be3641ac8e6b1da8b6
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#include <gralloc_priv.h>
31#include <gralloc_helper.h>
32#include <hardware/hardware.h>
33#include <hardware/aml_screen.h>
34#include <linux/videodev2.h>
35#include <android/native_window.h>
36/*****************************************************************************/
37
38#define LOGD(...) \
39{ \
40__android_log_print(ANDROID_LOG_DEBUG, "tv_input", __VA_ARGS__); }
41
42#ifndef container_of
43#define container_of(ptr, type, member) \
44 (type *)((char*)(ptr) - offsetof(type, member))
45#endif
46
47struct sideband_handle_t {
48 native_handle_t nativeHandle;
49 int identflag;
50 int usage;
51};
52
53typedef struct tv_input_private {
54 tv_input_device_t device;
55 const tv_input_callback_ops_t *callback;
56 void *callback_data;
57 aml_screen_device_t *mDev;
58 TvPlay *mpTv;
59 TvCallback *tvcallback;
60} tv_input_private_t;
61
62enum hdmi_port_id {
63 PORT_HDMI1 = 1,
64 PORT_HDMI3,
65 PORT_HDMI2,
66};
67
68static int getHdmiPort(tv_source_input_t source_input)
69{
70 int port = PORT_HDMI1;
71 switch (source_input) {
72 case SOURCE_HDMI1:
73 port = PORT_HDMI1;
74 break;
75 case SOURCE_HDMI2:
76 port = PORT_HDMI2;
77 break;
78 case SOURCE_HDMI3:
79 port = PORT_HDMI3;
80 break;
81 default:
82 break;
83 }
84 return port;
85}
86
87static int notify_ATV_device_available(tv_input_private_t *priv)
88{
89 tv_input_event_t event;
90 event.device_info.device_id = SOURCE_TV;
91 event.device_info.type = TV_INPUT_TYPE_TUNER;
92 event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE;
93 event.device_info.audio_type = AUDIO_DEVICE_NONE;
94 event.device_info.audio_address = NULL;
95 priv->callback->notify(&priv->device, &event, priv->callback_data);
96 return 0;
97}
98
99static int notify_ATV_stream_configurations_change(tv_input_private_t *priv)
100{
101 tv_input_event_t event;
102 event.device_info.device_id = SOURCE_TV;
103 event.device_info.type = TV_INPUT_TYPE_TUNER;
104 event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED;
105 event.device_info.audio_type = AUDIO_DEVICE_NONE;
106 event.device_info.audio_address = NULL;
107 priv->callback->notify(&priv->device, &event, priv->callback_data);
108 return 0;
109}
110
111static int notify_DTV_device_available(tv_input_private_t *priv)
112{
113 tv_input_event_t event;
114 event.device_info.device_id = SOURCE_DTV;
115 event.device_info.type = TV_INPUT_TYPE_TUNER;
116 event.type = TV_INPUT_EVENT_DEVICE_AVAILABLE;
117 event.device_info.audio_type = AUDIO_DEVICE_NONE;
118 event.device_info.audio_address = NULL;
119 priv->callback->notify(&priv->device, &event, priv->callback_data);
120 return 0;
121}
122
123static int notify_DTV_stream_configurations_change(tv_input_private_t *priv)
124{
125 tv_input_event_t event;
126 event.device_info.device_id = SOURCE_DTV;
127 event.device_info.type = TV_INPUT_TYPE_TUNER;
128 event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED;
129 event.device_info.audio_type = AUDIO_DEVICE_NONE;
130 event.device_info.audio_address = NULL;
131 priv->callback->notify(&priv->device, &event, priv->callback_data);
132 return 0;
133}
134
135void TvIputHal_ChannelConl(tv_input_private_t *priv, int ops_type, int device_id)
136{
137 if (priv->mpTv) {
138 if (ops_type) {
139 LOGD ( "%s, OpenSourceSwitchInput id = %d\n", __FUNCTION__, device_id );
140 priv->mpTv->StartTv();
141 priv->mpTv->SwitchSourceInput((tv_source_input_t) device_id);
142 } else if (priv->mpTv->GetCurrentSourceInput() == device_id) {
143 LOGD ( "%s, StopSourceSwitchInput id = %d\n", __FUNCTION__, device_id );
144 priv->mpTv->StopTv();
145 }
146 }
147}
148
149static int notify_AV_device_available(tv_input_private_t *priv, tv_source_input_t source_input, int type)
150{
151 tv_input_event_t event;
152 event.device_info.device_id = source_input;
153 event.device_info.type = TV_INPUT_TYPE_COMPONENT;
154 event.type = type;
155 event.device_info.audio_type = AUDIO_DEVICE_NONE;
156 event.device_info.audio_address = NULL;
157 priv->callback->notify(&priv->device, &event, priv->callback_data);
158 return 0;
159}
160
161static int notify_AV_stream_configurations_change(tv_input_private_t *priv, tv_source_input_t source_input)
162{
163 tv_input_event_t event;
164 event.device_info.device_id = source_input;
165 event.device_info.type = TV_INPUT_TYPE_COMPONENT;
166 event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED;
167 event.device_info.audio_type = AUDIO_DEVICE_NONE;
168 event.device_info.audio_address = NULL;
169 priv->callback->notify(&priv->device, &event, priv->callback_data);
170 return 0;
171}
172
173static int notify_HDMI_device_available(tv_input_private_t *priv, tv_source_input_t source_input, uint32_t port_id, int type)
174{
175 tv_input_event_t event;
176 event.device_info.device_id = source_input;
177 event.device_info.type = TV_INPUT_TYPE_HDMI;
178 event.type = type;
179 event.device_info.hdmi.port_id = port_id;
180 event.device_info.audio_type = AUDIO_DEVICE_NONE;
181 event.device_info.audio_address = NULL;
182 priv->callback->notify(&priv->device, &event, priv->callback_data);
183 return 0;
184}
185
186static int notify_HDMI_stream_configurations_change(tv_input_private_t *priv, tv_source_input_t source_input, uint32_t port_id)
187{
188 tv_input_event_t event;
189 event.device_info.device_id = source_input;
190 event.device_info.type = TV_INPUT_TYPE_HDMI;
191 event.type = TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED;
192 event.device_info.hdmi.port_id = port_id;
193 event.device_info.audio_type = AUDIO_DEVICE_NONE;
194 event.device_info.audio_address = NULL;
195 priv->callback->notify(&priv->device, &event, priv->callback_data);
196 return 0;
197}
198
199static int notify_TV_Input_Capture_Succeeded(tv_input_private_t *priv, int device_id, int stream_id, uint32_t seq)
200{
201 tv_input_event_t event;
202 event.type = TV_INPUT_EVENT_CAPTURE_SUCCEEDED;
203 event.capture_result.device_id = device_id;
204 event.capture_result.stream_id = stream_id;
205 event.capture_result.seq = seq;
206 priv->callback->notify(&priv->device, &event, priv->callback_data);
207 return 0;
208}
209
210static int notify_TV_Input_Capture_Fail(tv_input_private_t *priv, int device_id, int stream_id, uint32_t seq)
211{
212 tv_input_event_t event;
213 event.type = TV_INPUT_EVENT_CAPTURE_FAILED;
214 event.capture_result.device_id = device_id;
215 event.capture_result.stream_id = stream_id;
216 event.capture_result.seq = seq;
217 priv->callback->notify(&priv->device, &event, priv->callback_data);
218 return 0;
219}
220void TvCallback::onTvEvent (int32_t msgType, const Parcel &p)
221{
222 tv_input_private_t *priv = (tv_input_private_t *)(mPri);
223 switch (msgType) {
224 case SOURCE_CONNECT_CALLBACK: {
225 int source = p.readInt32();
226 int connectState = p.readInt32();
227 LOGD("TvCallback::onTvEvent source = %d, status = %d", source, connectState)
228
229 switch (source) {
230 case SOURCE_HDMI1:
231 case SOURCE_HDMI2:
232 case SOURCE_HDMI3: {
233 if (connectState == 1) {
234 notify_HDMI_device_available(priv, (tv_source_input_t)source, getHdmiPort((tv_source_input_t)source), TV_INPUT_EVENT_DEVICE_AVAILABLE);
235 notify_HDMI_stream_configurations_change(priv, (tv_source_input_t)source, getHdmiPort((tv_source_input_t)source));
236 } else {
237 notify_HDMI_device_available(priv, (tv_source_input_t)source, getHdmiPort((tv_source_input_t)source), TV_INPUT_EVENT_DEVICE_UNAVAILABLE);
238 }
239 }
240 break;
241
242 case SOURCE_AV1:
243 case SOURCE_AV2: {
244 if (connectState == 1) {
245 notify_AV_device_available(priv, (tv_source_input_t)source, TV_INPUT_EVENT_DEVICE_AVAILABLE);
246 notify_AV_stream_configurations_change(priv, (tv_source_input_t)source);
247 } else {
248 notify_AV_device_available(priv, (tv_source_input_t)source, TV_INPUT_EVENT_DEVICE_UNAVAILABLE);
249 }
250 }
251 break;
252
253 default:
254 break;
255 }
256 }
257 break;
258
259 default:
260 break;
261 }
262}
263
264#define NORMAL_STREAM_ID 1
265#define FRAME_CAPTURE_STREAM_ID 2
266static tv_stream_config_t mconfig[2];
267static int get_stream_configs(int dev_id, int *num_configurations, const tv_stream_config_t **configs)
268{
269 switch (dev_id) {
270 case SOURCE_TV:
271 mconfig[0].stream_id = NORMAL_STREAM_ID;
272 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
273 mconfig[0].max_video_width = 1920;
274 mconfig[0].max_video_height = 1080;
275 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
276 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
277 mconfig[1].max_video_width = 1920;
278 mconfig[1].max_video_height = 1080;
279 *num_configurations = 2;
280 *configs = mconfig;
281 break;
282 case SOURCE_DTV:
283 mconfig[0].stream_id = NORMAL_STREAM_ID;
284 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
285 mconfig[0].max_video_width = 1920;
286 mconfig[0].max_video_height = 1080;
287 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
288 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
289 mconfig[1].max_video_width = 1920;
290 mconfig[1].max_video_height = 1080;
291 *num_configurations = 2;
292 *configs = mconfig;
293 break;
294 case SOURCE_AV1:
295 case SOURCE_AV2:
296 mconfig[0].stream_id = NORMAL_STREAM_ID;
297 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
298 mconfig[0].max_video_width = 1920;
299 mconfig[0].max_video_height = 1080;
300 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
301 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
302 mconfig[1].max_video_width = 1920;
303 mconfig[1].max_video_height = 1080;
304 *num_configurations = 2;
305 *configs = mconfig;
306 break;
307 case SOURCE_HDMI1:
308 mconfig[0].stream_id = NORMAL_STREAM_ID;
309 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
310 mconfig[0].max_video_width = 1920;
311 mconfig[0].max_video_height = 1080;
312 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
313 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
314 mconfig[1].max_video_width = 1920;
315 mconfig[1].max_video_height = 1080;
316 *num_configurations = 2;
317 *configs = mconfig;
318 break;
319 case SOURCE_HDMI2:
320 mconfig[0].stream_id = NORMAL_STREAM_ID;
321 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
322 mconfig[0].max_video_width = 1920;
323 mconfig[0].max_video_height = 1080;
324 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
325 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
326 mconfig[1].max_video_width = 1920;
327 mconfig[1].max_video_height = 1080;
328 *num_configurations = 2;
329 *configs = mconfig;
330 break;
331 case SOURCE_HDMI3:
332 mconfig[0].stream_id = NORMAL_STREAM_ID;
333 mconfig[0].type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE ;
334 mconfig[0].max_video_width = 1920;
335 mconfig[0].max_video_height = 1080;
336 mconfig[1].stream_id = FRAME_CAPTURE_STREAM_ID;
337 mconfig[1].type = TV_STREAM_TYPE_BUFFER_PRODUCER ;
338 mconfig[1].max_video_width = 1920;
339 mconfig[1].max_video_height = 1080;
340 *num_configurations = 2;
341 *configs = mconfig;
342 break;
343 default:
344 break;
345 }
346 return 0;
347}
348
349static int get_tv_stream(tv_stream_t *stream)
350{
351 static struct sideband_handle_t *tvstream = NULL;
352 if (stream->stream_id == NORMAL_STREAM_ID) {
353 if ( !tvstream ) {
354 tvstream = (struct sideband_handle_t *)native_handle_create(0, 2);
355 if ( !tvstream ) {
356 return -EINVAL;
357 }
358 }
359 tvstream->identflag = 0xabcdcdef; //magic word
360 tvstream->usage = GRALLOC_USAGE_AML_VIDEO_OVERLAY;
361 stream->type = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE;
362 stream->sideband_stream_source_handle = (native_handle_t *)tvstream;
363 } else if (stream->stream_id == FRAME_CAPTURE_STREAM_ID) {
364 stream->type = TV_STREAM_TYPE_BUFFER_PRODUCER;
365 }
366 return 0;
367}
368
369static int tv_input_device_open(const struct hw_module_t *module,
370 const char *name, struct hw_device_t **device);
371
372static struct hw_module_methods_t tv_input_module_methods = {
373open:
374 tv_input_device_open
375};
376
377tv_input_module_t HAL_MODULE_INFO_SYM = {
378common:
379 {
380tag:
381 HARDWARE_MODULE_TAG,
382 version_major: 0,
383 version_minor: 1,
384id:
385 TV_INPUT_HARDWARE_MODULE_ID,
386name: "TVInput module"
387 ,
388author: "Amlogic"
389 ,
390methods:
391 &tv_input_module_methods,
392dso: NULL,
393reserved: {0},
394 }
395};
396
397/*****************************************************************************/
398static int tv_input_initialize(struct tv_input_device *dev,
399 const tv_input_callback_ops_t *callback, void *data)
400{
401 if (dev == NULL || callback == NULL) {
402 return -EINVAL;
403 }
404 tv_input_private_t *priv = (tv_input_private_t *)dev;
405 if (priv->callback != NULL) {
406 return -EEXIST;
407 }
408 priv->callback = callback;
409 priv->callback_data = data;
410 /* ATV_DEVICE_AVAILABLE */
411 notify_ATV_device_available(priv);
412 notify_ATV_stream_configurations_change(priv);
413 /* DTV_DEVICE_AVAILABLE */
414 notify_DTV_device_available(priv);
415 notify_DTV_stream_configurations_change(priv);
416
417 if (priv->mpTv->GetHdmiAvHotplugDetectOnoff()) {
418 /* AV1_DEVICE_AVAILABLE */
419 int status = priv->mpTv->GetSourceConnectStatus(SOURCE_AV1);
420 if (status == 1) { //IN
421 notify_AV_device_available(priv, SOURCE_AV1, TV_INPUT_EVENT_DEVICE_AVAILABLE);
422 notify_AV_stream_configurations_change(priv, SOURCE_AV1);
423 }
424
425 /* AV2_DEVICE_AVAILABLE */
426 status = priv->mpTv->GetSourceConnectStatus(SOURCE_AV2);
427 if (status == 1) { //IN
428 notify_AV_device_available(priv, SOURCE_AV2, TV_INPUT_EVENT_DEVICE_AVAILABLE);
429 notify_AV_stream_configurations_change(priv, SOURCE_AV2);
430 }
431
432 /* HDMI1_DEVICE_AVAILABLE */
433 status = priv->mpTv->GetSourceConnectStatus(SOURCE_HDMI1);
434 if (status == 1) { //IN
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 }
438
439 /* HDMI2_DEVICE_AVAILABLE */
440 status = priv->mpTv->GetSourceConnectStatus(SOURCE_HDMI2);
441 if (status == 1) { //IN
442 notify_HDMI_device_available(priv, SOURCE_HDMI2, getHdmiPort(SOURCE_HDMI2), TV_INPUT_EVENT_DEVICE_AVAILABLE);
443 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI2, getHdmiPort(SOURCE_HDMI2));
444 }
445
446 /* HDMI3_DEVICE_AVAILABLE */
447 status = priv->mpTv->GetSourceConnectStatus(SOURCE_HDMI3);
448 if (status == 1) { //IN
449 notify_HDMI_device_available(priv, SOURCE_HDMI3, getHdmiPort(SOURCE_HDMI3), TV_INPUT_EVENT_DEVICE_AVAILABLE);
450 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI3, getHdmiPort(SOURCE_HDMI3));
451 }
452
453 priv->mpTv->setTvObserver(priv->tvcallback);
454 } else {
455 /* AV1_DEVICE_AVAILABLE */
456 notify_AV_device_available(priv, SOURCE_AV1, TV_INPUT_EVENT_DEVICE_AVAILABLE);
457 notify_AV_stream_configurations_change(priv, SOURCE_AV1);
458 /* AV2_DEVICE_AVAILABLE */
459 notify_AV_device_available(priv, SOURCE_AV2, TV_INPUT_EVENT_DEVICE_AVAILABLE);
460 notify_AV_stream_configurations_change(priv, SOURCE_AV2);
461 /* HDMI1_DEVICE_AVAILABLE */
462 notify_HDMI_device_available(priv, SOURCE_HDMI1, getHdmiPort(SOURCE_HDMI1), TV_INPUT_EVENT_DEVICE_AVAILABLE);
463 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI1, getHdmiPort(SOURCE_HDMI1));
464 /* HDMI2_DEVICE_AVAILABLE */
465 notify_HDMI_device_available(priv, SOURCE_HDMI2, getHdmiPort(SOURCE_HDMI2), TV_INPUT_EVENT_DEVICE_AVAILABLE);
466 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI2, getHdmiPort(SOURCE_HDMI2));
467 /* HDMI3_DEVICE_AVAILABLE */
468 notify_HDMI_device_available(priv, SOURCE_HDMI3, getHdmiPort(SOURCE_HDMI3), TV_INPUT_EVENT_DEVICE_AVAILABLE);
469 notify_HDMI_stream_configurations_change(priv, SOURCE_HDMI3, getHdmiPort(SOURCE_HDMI3));
470 }
471 return 0;
472}
473
474static int tv_input_get_stream_configurations(const struct tv_input_device *dev __unused,
475 int device_id, int *num_configurations,
476 const tv_stream_config_t **configs)
477{
478 if (get_stream_configs(device_id, num_configurations, configs) == 0) {
479 return 0;
480 }
481 return -EINVAL;
482}
483
484static int tv_input_open_stream(struct tv_input_device *dev, int device_id,
485 tv_stream_t *stream)
486{
487 tv_input_private_t *priv = (tv_input_private_t *)dev;
488 if (priv) {
489 if (get_tv_stream(stream) != 0) {
490 return -EINVAL;
491 }
492 if (stream->stream_id == NORMAL_STREAM_ID) {
493 TvIputHal_ChannelConl(priv, 1, device_id);
494 return 0;
495 } else if (stream->stream_id == FRAME_CAPTURE_STREAM_ID) {
496 aml_screen_module_t* mModule;
497 if (hw_get_module(AML_SCREEN_HARDWARE_MODULE_ID,
498 (const hw_module_t **)&mModule) < 0) {
499 ALOGE("can not get screen source module");
500 } else {
501 mModule->common.methods->open((const hw_module_t *)mModule,
502 AML_SCREEN_SOURCE, (struct hw_device_t**)&(priv->mDev));
503 //do test here, we can use ops of mDev to operate vdin source
504 }
505
506 if (priv->mDev) {
507 int mCustomW = stream->buffer_producer.width;
508 int mCustomH = stream->buffer_producer.height;
509 mBufferSize = mCustomW * mCustomH * 3/2;
510
511 priv->mDev->ops.set_format(priv->mDev, mCustomW, mCustomH, V4L2_PIX_FMT_NV21);
512 priv->mDev->ops.set_port_type(priv->mDev, (int)0x4000); //TVIN_PORT_HDMI0 = 0x4000
513 priv->mDev->ops.start_v4l2_device(priv->mDev);
514 }
515 return 0;
516 }
517 }
518 return -EINVAL;
519}
520
521static int tv_input_close_stream(struct tv_input_device *dev, int device_id,
522 int stream_id)
523{
524 tv_input_private_t *priv = (tv_input_private_t *)dev;
525 if (stream_id == NORMAL_STREAM_ID) {
526 TvIputHal_ChannelConl(priv, 0, device_id);
527 return 0;
528 } else if (stream_id == FRAME_CAPTURE_STREAM_ID) {
529 if (priv->mDev) {
530 priv->mDev->ops.stop_v4l2_device(priv->mDev);
531 }
532 return 0;
533 }
534 return -EINVAL;
535}
536
537static int tv_input_request_capture(
538 struct tv_input_device *dev __unused, int device_id __unused,
539 int stream_id __unused, buffer_handle_t* buffer __unused, uint32_t seq __unused)
540{
541 tv_input_private_t *priv = (tv_input_private_t *)dev;
542 int index;
543 aml_screen_buffer_info_t buff_info;
544 int mFrameWidth , mFrameHeight ;
545 int ret;
546 long *src = NULL;
547 unsigned char *dest = NULL;
548 ANativeWindowBuffer *buf;
549 if (priv->mDev) {
550 ret = priv->mDev->ops.aquire_buffer(priv->mDev, &buff_info);
551 if (ret != 0 || (buff_info.buffer_mem == 0)) {
552 LOGD("Get V4l2 buffer failed");
553 notify_TV_Input_Capture_Fail(priv,device_id,stream_id,--seq);
554 return -EWOULDBLOCK;
555 }
556 src = (long *)buff_info.buffer_mem;
557 buf = container_of(buffer, ANativeWindowBuffer, handle);
558 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
559 graphicBuffer->lock(SCREENSOURCE_GRALLOC_USAGE, (void **)&dest);
560 if (dest == NULL) {
561 LOGD("Invalid Gralloc Handle");
562 return -EWOULDBLOCK;
563 }
564 memcpy(dest, src, mBufferSize);
565 graphicBuffer->unlock();
566 graphicBuffer.clear();
567 priv->mDev->ops.release_buffer(priv->mDev, src);
568
569 notify_TV_Input_Capture_Succeeded(priv,device_id,stream_id,seq);
570 return 0;
571 }
572 return -EWOULDBLOCK;
573}
574
575static int tv_input_cancel_capture(struct tv_input_device *, int, int, uint32_t)
576{
577 return -EINVAL;
578}
579
580/*****************************************************************************/
581
582static int tv_input_device_close(struct hw_device_t *dev)
583{
584 tv_input_private_t *priv = (tv_input_private_t *)dev;
585 if (priv) {
586 if (priv->mpTv) {
587 delete priv->mpTv;
588 }
589 if (priv->mDev) {
590 delete priv->mDev;
591 }
592 free(priv);
593 }
594 return 0;
595}
596
597/*****************************************************************************/
598
599static int tv_input_device_open(const struct hw_module_t *module,
600 const char *name, struct hw_device_t **device)
601{
602 int status = -EINVAL;
603 if (!strcmp(name, TV_INPUT_DEFAULT_DEVICE)) {
604 tv_input_private_t *dev = (tv_input_private_t *)malloc(sizeof(*dev));
605
606 /* initialize our state here */
607 memset(dev, 0, sizeof(*dev));
608 dev->mpTv = new TvPlay();
609 dev->tvcallback = new TvCallback(dev);
610 /* initialize the procs */
611 dev->device.common.tag = HARDWARE_DEVICE_TAG;
612 dev->device.common.version = TV_INPUT_DEVICE_API_VERSION_0_1;
613 dev->device.common.module = const_cast<hw_module_t *>(module);
614 dev->device.common.close = tv_input_device_close;
615
616 dev->device.initialize = tv_input_initialize;
617 dev->device.get_stream_configurations =
618 tv_input_get_stream_configurations;
619 dev->device.open_stream = tv_input_open_stream;
620 dev->device.close_stream = tv_input_close_stream;
621 dev->device.request_capture = tv_input_request_capture;
622 dev->device.cancel_capture = tv_input_cancel_capture;
623
624 *device = &dev->device.common;
625 status = 0;
626 }
627 return status;
628}
629