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 | |
42 | struct sideband_handle_t { |
43 | native_handle_t nativeHandle; |
44 | int identflag; |
45 | int usage; |
46 | }; |
47 | |
48 | typedef 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 | enum hdmi_port_id { |
57 | PORT_HDMI1 = 1, |
58 | PORT_HDMI3, |
59 | PORT_HDMI2, |
60 | }; |
61 | |
62 | static 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 | |
81 | static 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 | |
93 | static 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 | |
105 | static 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 | |
117 | static 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 | |
129 | void 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 | |
143 | static 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 | |
155 | static 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 | |
167 | static 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 | |
180 | static 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 | |
193 | void 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 |
239 | static tv_stream_config_t mconfig[2]; |
240 | static 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 | |
322 | static 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 | |
342 | static int tv_input_device_open(const struct hw_module_t *module, |
343 | const char *name, struct hw_device_t **device); |
344 | |
345 | static struct hw_module_methods_t tv_input_module_methods = { |
346 | open: |
347 | tv_input_device_open |
348 | }; |
349 | |
350 | tv_input_module_t HAL_MODULE_INFO_SYM = { |
351 | common: |
352 | { |
353 | tag: |
354 | HARDWARE_MODULE_TAG, |
355 | version_major: 0, |
356 | version_minor: 1, |
357 | id: |
358 | TV_INPUT_HARDWARE_MODULE_ID, |
359 | name: "TVInput module" |
360 | , |
361 | author: "Amlogic" |
362 | , |
363 | methods: |
364 | &tv_input_module_methods, |
365 | dso: NULL, |
366 | reserved: {0}, |
367 | } |
368 | }; |
369 | |
370 | /*****************************************************************************/ |
371 | static 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 | |
447 | static 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 | |
457 | static 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 | |
475 | static 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 | |
488 | static 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 | |
495 | static int tv_input_cancel_capture(struct tv_input_device *, int, int, uint32_t) |
496 | { |
497 | return -EINVAL; |
498 | } |
499 | |
500 | /*****************************************************************************/ |
501 | |
502 | static 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 | |
516 | static 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 |