libcec: disable debug
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos.git] / libcec / libcec.c
CommitLineData
5763fb39
T
1/*
2 * Copyright@ Samsung Electronics Co. LTD
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#include <stdio.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include <sys/ioctl.h>
22#include <unistd.h>
23#include <stdlib.h>
24#include <cutils/log.h>
25
26/* drv. header */
27#include "cec.h"
28
29#include "libcec.h"
30
400322e1 31//#define CEC_DEBUG 0
5763fb39
T
32
33/**
34 * @def CEC_DEVICE_NAME
35 * Defines simbolic name of the CEC device.
36 */
37#define CEC_DEVICE_NAME "/dev/CEC"
38
39static struct {
40 enum CECDeviceType devtype;
41 unsigned char laddr;
42} laddresses[] = {
43 { CEC_DEVICE_RECODER, 1 },
44 { CEC_DEVICE_RECODER, 2 },
45 { CEC_DEVICE_TUNER, 3 },
46 { CEC_DEVICE_PLAYER, 4 },
47 { CEC_DEVICE_AUDIO, 5 },
48 { CEC_DEVICE_TUNER, 6 },
49 { CEC_DEVICE_TUNER, 7 },
50 { CEC_DEVICE_PLAYER, 8 },
51 { CEC_DEVICE_RECODER, 9 },
52 { CEC_DEVICE_TUNER, 10 },
53 { CEC_DEVICE_PLAYER, 11 },
54};
55
56static int CECSetLogicalAddr(unsigned int laddr);
57
58#ifdef CEC_DEBUG
59inline static void CECPrintFrame(unsigned char *buffer, unsigned int size);
60#endif
61
62static int fd = -1;
63
64/**
65 * Open device driver and assign CEC file descriptor.
66 *
67 * @return If success to assign CEC file descriptor, return fd; otherwise, return -1.
68 */
69int CECOpen()
70{
71 if (fd != -1)
72 CECClose();
73
74 if ((fd = open(CEC_DEVICE_NAME, O_RDWR)) < 0) {
75 ALOGE("Can't open %s!\n", CEC_DEVICE_NAME);
76 return -1;
77 }
78
79 return fd;
80}
81
82/**
83 * Close CEC file descriptor.
84 *
85 * @return If success to close CEC file descriptor, return 1; otherwise, return 0.
86 */
87int CECClose()
88{
89 int res = 1;
90
91 if (fd != -1) {
92 if (close(fd) != 0) {
93 ALOGE("close() failed!\n");
94 res = 0;
95 }
96 fd = -1;
97 }
98
99 return res;
100}
101
102/**
103 * Allocate logical address.
104 *
105 * @param paddr [in] CEC device physical address.
106 * @param devtype [in] CEC device type.
107 *
108 * @return new logical address, or 0 if an error occured.
109 */
110int CECAllocLogicalAddress(int paddr, enum CECDeviceType devtype)
111{
112 unsigned char laddr = CEC_LADDR_UNREGISTERED;
113 size_t i = 0;
114
115 if (fd == -1) {
116 ALOGE("open device first!\n");
117 return 0;
118 }
119
120 if (CECSetLogicalAddr(laddr) < 0) {
121 ALOGE("CECSetLogicalAddr() failed!\n");
122 return 0;
123 }
124
125 if (paddr == CEC_NOT_VALID_PHYSICAL_ADDRESS)
126 return CEC_LADDR_UNREGISTERED;
127
128 /* send "Polling Message" */
129 while (i < sizeof(laddresses) / sizeof(laddresses[0])) {
130 if (laddresses[i].devtype == devtype) {
131 unsigned char _laddr = laddresses[i].laddr;
132 unsigned char message = ((_laddr << 4) | _laddr);
133 if (CECSendMessage(&message, 1) != 1) {
134 laddr = _laddr;
135 break;
136 }
137 }
138 i++;
139 }
140
141 if (laddr == CEC_LADDR_UNREGISTERED) {
142 ALOGE("All LA addresses in use!!!\n");
143 return CEC_LADDR_UNREGISTERED;
144 }
145
146 if (CECSetLogicalAddr(laddr) < 0) {
147 ALOGE("CECSetLogicalAddr() failed!\n");
148 return 0;
149 }
150
151 /* broadcast "Report Physical Address" */
152 unsigned char buffer[5];
153 buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST;
154 buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS;
155 buffer[2] = (paddr >> 8) & 0xFF;
156 buffer[3] = paddr & 0xFF;
157 buffer[4] = devtype;
158
159 if (CECSendMessage(buffer, 5) != 5) {
160 ALOGE("CECSendMessage() failed!\n");
161 return 0;
162 }
163
164 return laddr;
165}
166
167/**
168 * Send CEC message.
169 *
170 * @param *buffer [in] pointer to buffer address where message located.
171 * @param size [in] message size.
172 *
173 * @return number of bytes written, or 0 if an error occured.
174 */
175int CECSendMessage(unsigned char *buffer, int size)
176{
177 if (fd == -1) {
178 ALOGE("open device first!\n");
179 return 0;
180 }
181
182 if (size > CEC_MAX_FRAME_SIZE) {
183 ALOGE("size should not exceed %d\n", CEC_MAX_FRAME_SIZE);
184 return 0;
185 }
186
187#if CEC_DEBUG
188 ALOGI("CECSendMessage() : ");
189 CECPrintFrame(buffer, size);
190#endif
191
192 return write(fd, buffer, size);
193}
194
195/**
196 * Receive CEC message.
197 *
198 * @param *buffer [in] pointer to buffer address where message will be stored.
199 * @param size [in] buffer size.
200 * @param timeout [in] timeout in microseconds.
201 *
202 * @return number of bytes received, or 0 if an error occured.
203 */
204int CECReceiveMessage(unsigned char *buffer, int size, long timeout)
205{
206 int bytes = 0;
207 fd_set rfds;
208 struct timeval tv;
209 int retval;
210
211 if (fd == -1) {
212 ALOGE("open device first!\n");
213 return 0;
214 }
215
216 tv.tv_sec = 0;
217 tv.tv_usec = timeout;
218
219 FD_ZERO(&rfds);
220 FD_SET(fd, &rfds);
221
222 retval = select(fd + 1, &rfds, NULL, NULL, &tv);
223
224 if (retval == -1) {
225 return 0;
226 } else if (retval) {
227 bytes = read(fd, buffer, size);
228#if CEC_DEBUG
229 ALOGI("CECReceiveMessage() : size(%d)", bytes);
230 if(bytes > 0)
231 CECPrintFrame(buffer, bytes);
232#endif
233 }
234
235 return bytes;
236}
237
238/**
239 * Set CEC logical address.
240 *
241 * @return 1 if success, otherwise, return 0.
242 */
243int CECSetLogicalAddr(unsigned int laddr)
244{
245 if (ioctl(fd, CEC_IOC_SETLADDR, &laddr)) {
246 ALOGE("ioctl(CEC_IOC_SETLA) failed!\n");
247 return 0;
248 }
249
250 return 1;
251}
252
253#if CEC_DEBUG
254/**
255 * Print CEC frame.
256 */
257void CECPrintFrame(unsigned char *buffer, unsigned int size)
258{
259 if (size > 0) {
260 size_t i;
261 ALOGI("fsize: %d ", size);
262 ALOGI("frame: ");
263 for (i = 0; i < size; i++)
264 ALOGI("0x%02x ", buffer[i]);
265
266 ALOGI("\n");
267 }
268}
269#endif
270
271/**
272 * Check CEC message.
273 *
274 * @param opcode [in] pointer to buffer address where message will be stored.
275 * @param lsrc [in] buffer size.
276 *
277 * @return 1 if message should be ignored, otherwise, return 0.
278 */
279//TODO: not finished
280int CECIgnoreMessage(unsigned char opcode, unsigned char lsrc)
281{
282 int retval = 0;
283
284 /* if a message coming from address 15 (unregistered) */
285 if (lsrc == CEC_LADDR_UNREGISTERED) {
286 switch (opcode) {
287 case CEC_OPCODE_DECK_CONTROL:
288 case CEC_OPCODE_PLAY:
289 retval = 1;
290 default:
291 break;
292 }
293 }
294
295 return retval;
296}
297
298/**
299 * Check CEC message.
300 *
301 * @param opcode [in] pointer to buffer address where message will be stored.
302 * @param size [in] message size.
303 *
304 * @return 0 if message should be ignored, otherwise, return 1.
305 */
306//TODO: not finished
307int CECCheckMessageSize(unsigned char opcode, int size)
308{
309 int retval = 1;
310
311 switch (opcode) {
312 case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
313 if (size != 1)
314 retval = 0;
315 break;
316 case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
317 if (size != 2)
318 retval = 0;
319 break;
320 case CEC_OPCODE_PLAY:
321 case CEC_OPCODE_DECK_CONTROL:
322 case CEC_OPCODE_SET_MENU_LANGUAGE:
323 case CEC_OPCODE_ACTIVE_SOURCE:
324 case CEC_OPCODE_ROUTING_INFORMATION:
325 case CEC_OPCODE_SET_STREAM_PATH:
326 if (size != 3)
327 retval = 0;
328 break;
329 case CEC_OPCODE_FEATURE_ABORT:
330 case CEC_OPCODE_DEVICE_VENDOR_ID:
331 case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
332 if (size != 4)
333 retval = 0;
334 break;
335 case CEC_OPCODE_ROUTING_CHANGE:
336 if (size != 5)
337 retval = 0;
338 break;
339 /* CDC - 1.4 */
340 case 0xf8:
341 if (!(size > 5 && size <= 16))
342 retval = 0;
343 break;
344 default:
345 break;
346 }
347
348 return retval;
349}
350
351/**
352 * Check CEC message.
353 *
354 * @param opcode [in] pointer to buffer address where message will be stored.
355 * @param broadcast [in] broadcast/direct message.
356 *
357 * @return 0 if message should be ignored, otherwise, return 1.
358 */
359//TODO: not finished
360int CECCheckMessageMode(unsigned char opcode, int broadcast)
361{
362 int retval = 1;
363
364 switch (opcode) {
365 case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
366 case CEC_OPCODE_SET_MENU_LANGUAGE:
367 case CEC_OPCODE_ACTIVE_SOURCE:
368 if (!broadcast)
369 retval = 0;
370 break;
371 case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
372 case CEC_OPCODE_DECK_CONTROL:
373 case CEC_OPCODE_PLAY:
374 case CEC_OPCODE_FEATURE_ABORT:
375 case CEC_OPCODE_ABORT:
376 if (broadcast)
377 retval = 0;
378 break;
379 default:
380 break;
381 }
382
383 return retval;
384}