tizen 2.3 release
[framework/system/deviced.git] / src / hdmi-cec / libcec.c
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 <linux/input.h>
25 #include <linux/uinput.h>
26 #include <errno.h>
27 /* drv. header */
28 #include "cec.h"
29 #include "libcec.h"
30 #include "core/log.h"
31
32 #define CEC_DEBUG 1
33
34 #define CEC_KEY_RELEASED 0
35 #define CEC_KEY_PRESSED 1
36 /**
37  * @def CEC_DEVICE_NAME
38  * Defines simbolic name of the CEC device.
39  */
40 #define CEC_DEVICE_NAME         "/dev/cec0"
41
42 static struct {
43         enum CECDeviceType devtype;
44         unsigned char laddr;
45 } laddresses[] = {
46         { CEC_DEVICE_RECODER, 1  },
47         { CEC_DEVICE_RECODER, 2  },
48         { CEC_DEVICE_TUNER,   3  },
49         { CEC_DEVICE_PLAYER,  4  },
50         { CEC_DEVICE_AUDIO,   5  },
51         { CEC_DEVICE_TUNER,   6  },
52         { CEC_DEVICE_TUNER,   7  },
53         { CEC_DEVICE_PLAYER,  8  },
54         { CEC_DEVICE_RECODER, 9  },
55         { CEC_DEVICE_TUNER,   10 },
56         { CEC_DEVICE_PLAYER,  11 },
57 };
58
59 static struct {
60         char *key_name;
61         unsigned char cec_id;
62         unsigned char opcode;
63         unsigned int ui_id;
64 } supportkeys[] = {
65         {"Connect",     0x40,   CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_F6},
66         {"Connect",     0x40,   CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_F6},
67         {"Enter",       0x0,    CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_ENTER},
68         {"Enter",       0x0,    CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_ENTER},
69         {"Up",          0x1,    CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_UP},
70         {"Up",          0x1,    CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_UP},
71         {"Down",        0x2,    CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_DOWN},
72         {"Down",        0x2,    CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_DOWN},
73         {"Left",        0x3,    CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_LEFT},
74         {"Left",        0x3,    CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_LEFT},
75         {"Right",       0x4,    CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_RIGHT},
76         {"Right",       0x4,    CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_RIGHT},
77         {"Exit",        0xD,    CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_MENU},
78         {"Exit",        0xD,    CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_MENU},
79         {"Clear",       0x2C,   CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_BACK},
80         {"Clear",       0x2C,   CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_BACK},
81         {"Clear2",      0x91,   CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN,   KEY_BACK},/* samsung key*/
82         {"Play",        0x24,   CEC_OPCODE_PLAY,                        KEY_PLAY},
83         {"Play",        0x44,   CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_PLAY},
84         {"Play",        0x44,   CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_PLAY},
85         {"Stop",        0x3,    CEC_OPCODE_DECK_CONTROL,                KEY_STOP},
86         {"Stop",        0x45,   CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_STOP},
87         {"Stop",        0x45,   CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_STOP},
88         {"Pause",       0x25,   CEC_OPCODE_PLAY,                        KEY_PAUSECD},
89         {"Pause",       0x46,   CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_PAUSECD},
90         {"Pause",       0x46,   CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_PAUSECD},
91         {"Rewind",      0x48,   CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_REWIND},
92         {"Rewind",      0x48,   CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_REWIND},
93         {"FastForward", 0x49,   CEC_OPCODE_USER_CONTROL_PRESSED,        KEY_FASTFORWARD},
94         {"FastForward", 0x49,   CEC_OPCODE_USER_CONTROL_RELEASED,       KEY_FASTFORWARD},
95         {"TV Standby",  0x36,   CEC_OPCODE_STANDBY,                     KEY_HOMEPAGE},
96         {"TV Routing Change", 0x80, CEC_OPCODE_ROUTING_CHANGE,          KEY_HOMEPAGE},
97 };
98
99 static int CECSetLogicalAddr(unsigned int laddr);
100
101 #ifdef CEC_DEBUG
102 inline static void CECPrintFrame(unsigned char *buffer, unsigned int size);
103 #endif
104
105 static int fd = -1;
106 static int key_fd = -1;
107 /**
108  * Open device driver and assign CEC file descriptor.
109  *
110  * @return  If success to assign CEC file descriptor, return fd; otherwise, return -1.
111  */
112 int CECOpen()
113 {
114         if (fd != -1)
115                 CECClose();
116
117         if ((fd = open(CEC_DEVICE_NAME, O_RDWR)) < 0) {
118                 _E("Can't open %s!\n", CEC_DEVICE_NAME);
119                 return -1;
120         }
121
122         return fd;
123 }
124
125 /**
126  * Close CEC file descriptor.
127  *
128  * @return  If success to close CEC file descriptor, return 1; otherwise, return 0.
129  */
130 int CECClose()
131 {
132         int res = 1;
133
134         if (fd != -1) {
135                 if (close(fd) != 0) {
136                         _E("close() failed!\n");
137                         res = 0;
138                 }
139                 fd = -1;
140         }
141
142         return res;
143 }
144
145 /**
146  * Allocate logical address.
147  *
148  * @param paddr   [in] CEC device physical address.
149  * @param devtype [in] CEC device type.
150  *
151  * @return new logical address, or 0 if an error occured.
152  */
153 int CECAllocLogicalAddress(int paddr, enum CECDeviceType devtype)
154 {
155         unsigned char laddr = CEC_LADDR_UNREGISTERED;
156         int i = 0;
157
158         _I("physical %x type %d", paddr, devtype);
159         if (fd == -1) {
160                 _E("open device first!\n");
161                 return 0;
162         }
163
164         if (CECSetLogicalAddr(laddr) < 0) {
165                 _E("CECSetLogicalAddr() failed!\n");
166                 return 0;
167         }
168
169         if (paddr == CEC_NOT_VALID_PHYSICAL_ADDRESS)
170                 return CEC_LADDR_UNREGISTERED;
171
172         /* send "Polling Message" */
173         while (i < sizeof(laddresses) / sizeof(laddresses[0])) {
174                 if (laddresses[i].devtype == devtype) {
175                         unsigned char _laddr = laddresses[i].laddr;
176                         unsigned char message = ((_laddr << 4) | _laddr);
177                         if (CECSendMessage(&message, 1) != 1) {
178                                 laddr = _laddr;
179                                 _I("find logical address %x %d", laddresses[i].laddr, laddresses[i].devtype);
180                                 break;
181                         }
182                 }
183                 i++;
184         }
185
186         if (laddr == CEC_LADDR_UNREGISTERED) {
187                 _E("All LA addresses in use!!!\n");
188                 return CEC_LADDR_UNREGISTERED;
189         }
190
191         if (CECSetLogicalAddr(laddr) < 0) {
192                 _E("CECSetLogicalAddr() failed!\n");
193                 return 0;
194         }
195
196         /* broadcast "Report Physical Address" */
197         unsigned char buffer[5];
198         buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST;
199         buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS;
200         buffer[2] = (paddr >> 8) & 0xFF;
201         buffer[3] = paddr & 0xFF;
202         buffer[4] = devtype;
203
204         if (CECSendMessage(buffer, 5) != 5) {
205                 _E("CECSendMessage() failed!\n");
206                 return 0;
207         }
208
209         return laddr;
210 }
211
212 /**
213  * Send CEC message.
214  *
215  * @param *buffer   [in] pointer to buffer address where message located.
216  * @param size      [in] message size.
217  *
218  * @return number of bytes written, or 0 if an error occured.
219  */
220 int CECSendMessage(unsigned char *buffer, int size)
221 {
222         if (fd == -1) {
223                 _E("open device first!\n");
224                 return 0;
225         }
226
227         if (size > CEC_MAX_FRAME_SIZE) {
228                 _E("size should not exceed %d\n", CEC_MAX_FRAME_SIZE);
229                 return 0;
230         }
231
232 #if CEC_DEBUG
233         _I("CECSendMessage() : size(%d)", size);
234         CECPrintFrame(buffer, size);
235 #else
236         _I("CEC send : 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", 
237         buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7],
238         buffer[8], buffer[9], buffer[10], buffer[11], buffer[12], buffer[13], buffer[14], buffer[15] );
239 #endif
240         return write(fd, buffer, size);
241 }
242
243 /**
244  * Receive CEC message.
245  *
246  * @param *buffer   [in] pointer to buffer address where message will be stored.
247  * @param size      [in] buffer size.
248  * @param timeout   [in] timeout in microseconds.
249  *
250  * @return number of bytes received, or 0 if an error occured.
251  */
252 int CECReceiveMessage(unsigned char *buffer, int size, long timeout)
253 {
254         int bytes = 0;
255         fd_set rfds;
256         struct timeval tv;
257         int retval;
258
259         if (fd == -1) {
260                 _E("open device first!\n");
261                 return 0;
262         }
263
264         tv.tv_sec = 0;
265         tv.tv_usec = timeout;
266
267         FD_ZERO(&rfds);
268         FD_SET(fd, &rfds);
269
270         retval = select(fd + 1, &rfds, NULL, NULL, &tv);
271
272         if (retval == -1) {
273                 _E("fail");
274                 return 0;
275         } else if (retval) {
276                 bytes = read(fd, buffer, size);
277 #if CEC_DEBUG
278                 _I("CECReceiveMessage() : size(%d)", bytes);
279                 if(bytes > 0)
280                         CECPrintFrame(buffer, bytes);
281 #endif
282         }
283
284         return bytes;
285 }
286
287 /**
288  * Set CEC logical address.
289  *
290  * @return 1 if success, otherwise, return 0.
291  */
292 int CECSetLogicalAddr(unsigned int laddr)
293 {
294         if (ioctl(fd, CEC_IOC_SETLADDR, &laddr)) {
295                 _E("ioctl(CEC_IOC_SETLA) failed!\n");
296                 return 0;
297         }
298
299         return 1;
300 }
301
302 int init_input_key_fd(void)
303 {
304         struct uinput_user_dev uidev;
305         int key_idx = sizeof(supportkeys)/sizeof(supportkeys[0]);
306
307         if (key_fd < 0) {
308                 key_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
309                 if(key_fd < 0) {
310                         _E("open failed");
311                         return -1;
312                 }
313                 memset(&uidev, 0, sizeof(uidev));
314                 snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "cec-input");
315                 uidev.id.bustype = BUS_USB;
316                 uidev.id.version = 1;
317                 uidev.id.vendor = 1;
318                 uidev.id.product = 1;
319                 ioctl(key_fd, UI_SET_EVBIT, EV_KEY);
320
321                 while (--key_idx >= 0) {
322                         if (CEC_OPCODE_USER_CONTROL_PRESSED == supportkeys[key_idx].opcode ||
323                             CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN == supportkeys[key_idx].opcode) {
324                                 ioctl (key_fd, UI_SET_KEYBIT, supportkeys[key_idx].ui_id);
325                                 _I("register key %s key(%d)",
326                                         supportkeys[key_idx].key_name,
327                                         supportkeys[key_idx].ui_id);
328                         }
329                 }
330                 write (key_fd, &uidev, sizeof(uidev)); 
331                 ioctl(key_fd, UI_DEV_CREATE);
332         }
333         return 0;
334 }
335
336 static int input_key_event(unsigned char opcode, unsigned int key)
337 {
338         struct input_event ev;
339         int ret;
340
341         if (opcode != CEC_OPCODE_USER_CONTROL_PRESSED &&
342             opcode != CEC_OPCODE_USER_CONTROL_RELEASED &&
343             opcode != CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN &&
344             opcode != CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP) {
345                 _E("unregister key event opcode(0x%X) key(%d)", opcode, key);
346                 return -1;      
347         }
348         memset(&ev, 0, sizeof(ev));
349         ev.type = EV_KEY;
350         ev.code = key;
351         if (opcode == CEC_OPCODE_USER_CONTROL_PRESSED ||
352             opcode == CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN)
353                 ev.value = CEC_KEY_PRESSED;
354         else
355                 ev.value = CEC_KEY_RELEASED;
356         ret = write(key_fd, &ev, sizeof(ev));
357         return ret;
358 }
359
360 /**
361  * report cec key.
362  *
363  * @return 1 if success, otherwise, return 0.
364  */
365 int CECReportKey(unsigned int key)
366 {
367         int key_idx = sizeof(supportkeys)/sizeof(supportkeys[0]);
368
369         while (--key_idx >= 0) {
370                 if (key == supportkeys[key_idx].ui_id) {
371                         _I("%s %d", supportkeys[key_idx].key_name, key);
372                         break;
373                 }
374         }
375 //      if (ioctl(fd, CEC_IOC_HANDLEKEY, &key)) {
376                 _E("ioctl(CEC_IOC_HANDLEKEY) failed!");
377                 return 0;
378 //      }
379
380         return 1;
381 }
382
383 #if CEC_DEBUG
384 /**
385  * Print CEC frame.
386  */
387 void CECPrintFrame(unsigned char *buffer, unsigned int size)
388 {
389         if (size > 0) {
390                 int i;
391                 _I("fsize: %d ", size);
392                 _I("frame: ");
393                 for (i = 0; i < size; i++)
394                         _I("0x%02x ", buffer[i]);
395
396                 _I("\n");
397         }
398 }
399 #endif
400
401 /**
402  * Check CEC message.
403  *
404  * @param opcode   [in] pointer to buffer address where message will be stored.
405  * @param lsrc     [in] buffer size.
406  *
407  * @return 1 if message should be ignored, otherwise, return 0.
408  */
409 //TODO: not finished
410 int CECIgnoreMessage(unsigned char opcode, unsigned char lsrc)
411 {
412         int retval = 0;
413
414         /* if a message coming from address 15 (unregistered) */
415         if (lsrc == CEC_LADDR_UNREGISTERED) {
416                 switch (opcode) {
417                 case CEC_OPCODE_DECK_CONTROL:
418                 case CEC_OPCODE_PLAY:
419                         retval = 1;
420                 default:
421                         break;
422                 }
423         }
424
425         return retval;
426 }
427
428 /**
429  * Check CEC message.
430  *
431  * @param opcode   [in] pointer to buffer address where message will be stored.
432  * @param size     [in] message size.
433  *
434  * @return 0 if message should be ignored, otherwise, return 1.
435  */
436 //TODO: not finished
437 int CECCheckMessageSize(unsigned char opcode, int size)
438 {
439         int retval = 1;
440
441         switch (opcode) {
442         case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
443         case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
444         case CEC_OPCODE_IMAGE_VIEW_ON:
445         case CEC_OPCODE_TEXT_VIEW_ON:
446                 if (size != 2)
447                         retval = 0;
448                 break;
449         case CEC_OPCODE_PLAY:
450         case CEC_OPCODE_DECK_CONTROL:
451         case CEC_OPCODE_SET_MENU_LANGUAGE:
452         case CEC_OPCODE_ACTIVE_SOURCE:
453         case CEC_OPCODE_ROUTING_INFORMATION:
454                 if (size != 3)
455                         retval = 0;
456                 break;
457         case CEC_OPCODE_SET_STREAM_PATH:
458                 if (size != 4)
459                         retval = 0;
460                 break;
461         case CEC_OPCODE_FEATURE_ABORT:
462         case CEC_OPCODE_DEVICE_VENDOR_ID:
463         case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
464                 if (size != 4)
465                         retval = 0;
466                 break;
467         case CEC_OPCODE_ROUTING_CHANGE:
468                 if (size != 6)
469                         retval = 0;
470                 break;
471         /* CDC - 1.4 */
472         case 0xf8:
473                 if (!(size > 5 && size <= 16))
474                         retval = 0;
475                 break;
476         default:
477                 break;
478         }
479
480         return retval;
481 }
482
483 /**
484  * Check CEC message.
485  *
486  * @param opcode    [in] pointer to buffer address where message will be stored.
487  * @param broadcast [in] broadcast/direct message.
488  *
489  * @return 0 if message should be ignored, otherwise, return 1.
490  */
491 //TODO: not finished
492 int CECCheckMessageMode(unsigned char opcode, int broadcast)
493 {
494         int retval = 1;
495
496         switch (opcode) {
497         case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
498         case CEC_OPCODE_SET_MENU_LANGUAGE:
499         case CEC_OPCODE_ACTIVE_SOURCE:
500                 if (!broadcast)
501                         retval = 0;
502                 break;
503         case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
504         case CEC_OPCODE_DECK_CONTROL:
505         case CEC_OPCODE_PLAY:
506         case CEC_OPCODE_USER_CONTROL_PRESSED:
507         case CEC_OPCODE_FEATURE_ABORT:
508         case CEC_OPCODE_ABORT:
509                 if (broadcast)
510                         retval = 0;
511                 break;
512         default:
513                 break;
514         }
515
516         return retval;
517 }
518
519 /**
520  * handle key message.
521  *
522  * @param opcode        [in] opcode.
523  * @param key           [in] received key
524  *
525  */
526 void CECHandleKey(unsigned char opcode, unsigned char key)
527 {
528         int ret;
529         int key_idx = sizeof(supportkeys)/sizeof(supportkeys[0]);
530
531         while (--key_idx >= 0) {
532                 if (opcode == supportkeys[key_idx].opcode &&
533                     key == supportkeys[key_idx].cec_id)
534                 break;
535         }
536
537         if (key_idx >= 0) {
538                 /* key is valid */
539                 _I("[CEC] %s(opcode 0x%X,key 0x%X(key code %d)",
540                 supportkeys[key_idx].key_name, (int)opcode, (int)key, supportkeys[key_idx].ui_id);
541                 ret = input_key_event(supportkeys[key_idx].opcode, supportkeys[key_idx].ui_id);
542                 if (ret < 0)
543                         _E("ioctl(CEC_IOC_HANDLEKEY) failed! (fd %d %d: err[%s])", key_fd, ret, strerror(errno));
544         } else {
545                 _E("[CEC] 0x%X 0x%X is not supported key\n", opcode, key);
546         }
547 }
548
549 /**
550  * process CEC OneTouchPlay
551  *
552  * OneTouchPlay is disabled at normal case
553  * Enable : "adb shell setprop persist.hdmi.onetouch_enabled 1"
554  * send Text View On
555  * send Active source
556  */
557 void CECOneTouchPlay(unsigned char *buffer, int laddr, int paddr)
558 {
559         int size = 0;
560         unsigned char ldst = buffer[0] >> 4;
561         unsigned char opcode = buffer[1];
562
563         buffer[0] = (laddr << 4) | ldst;
564         buffer[1] = CEC_OPCODE_TEXT_VIEW_ON;
565         size = 2;
566         _I("Tx : [CEC_OPCODE_TEXT_VIEW_ON]");
567
568         if (size > 0) {
569                 if (CECSendMessage(buffer, size) != size)
570                         _E("CECSendMessage() failed!!!");
571         }
572         usleep(500000);
573
574         buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST;
575         buffer[1] = CEC_OPCODE_ACTIVE_SOURCE;
576         buffer[2] = (paddr >> 8) & 0xFF;
577         buffer[3] = paddr & 0xFF;
578         size = 4;
579         _I("Tx : [CEC_OPCODE_ACTIVE_SOURCE]");
580         if (size > 0) {
581                 if (CECSendMessage(buffer, size) != size)
582                         _E("CECSendMessage() failed!!!");
583         }
584 }
585
586 /**
587  * process CEC message.
588  *
589  * @param buffer    [in/out] pointer to buffer address where message will be stored.
590  * @param laddr         [in] logical address
591  * @param paddr         [in] physical address
592  *
593  * @return return size of CEC message to send.
594  */
595 int CECProcessOpcode(unsigned char *buffer, int laddr, int paddr, int raddr)
596 {
597         int size = 0;
598         unsigned char ldst = buffer[0] >> 4;
599         unsigned char opcode = buffer[1];
600
601         switch (opcode) {
602         case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
603                 /* responce with "Report Physical Address" */
604                 buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST;
605                 buffer[1] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS;
606                 buffer[2] = (paddr >> 8) & 0xFF;
607                 buffer[3] = paddr & 0xFF;
608                 buffer[4] = CEC_DEVICE_PLAYER;
609                 size = 5;
610                 break;
611         case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
612                 _I("[CEC_OPCODE_REQUEST_ACTIVE_SOURCE 0x%X]", opcode);
613                 if( raddr != paddr ) {
614                         _I("Not Currently active source  r:0x0%x  p:0x0%x", raddr, paddr);
615                         break;
616                 }
617                 buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST;
618                 buffer[1] = CEC_OPCODE_ACTIVE_SOURCE;
619                 buffer[2] = (paddr >> 8) & 0xFF;
620                 buffer[3] = paddr & 0xFF;
621                 size = 4;
622                 _I("Tx : [CEC_OPCODE_ACTIVE_SOURCE 0x%X]", CEC_OPCODE_ACTIVE_SOURCE);
623                 break;
624         case CEC_OPCODE_IMAGE_VIEW_ON:
625         case CEC_OPCODE_TEXT_VIEW_ON:
626                 _I("[CEC_OPCODE_IMAGE_VIEW_ON 0x%X]", opcode);
627                 buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST;
628                 buffer[1] = CEC_OPCODE_ACTIVE_SOURCE;
629                 buffer[2] = (paddr >> 8) & 0xFF;
630                 buffer[3] = paddr & 0xFF;
631                 size = 4;
632                 _I("Tx : [CEC_OPCODE_ACTIVE_SOURCE 0x%X]", CEC_OPCODE_ACTIVE_SOURCE);
633                 break;
634         case CEC_OPCODE_SET_STREAM_PATH:  //11.2.2-3 test
635                 _I("[CEC_OPCODE_SET_STREAM_PATH 0x%X]", opcode);
636                 buffer[0] = (laddr << 4) | CEC_MSG_BROADCAST;
637                 buffer[1] = CEC_OPCODE_ACTIVE_SOURCE;
638 #if 1
639                 buffer[2] = (paddr >> 8) & 0xFF;
640                 buffer[3] = paddr & 0xFF;
641 #endif
642                 size = 4;
643                 _I("Tx : [CEC_OPCODE_ACTIVE_SOURCE 0x%X]", CEC_OPCODE_ACTIVE_SOURCE);
644                 CECReportKey(KEY_HOMEPAGE);
645                 break;
646         case CEC_OPCODE_MENU_REQUEST:
647                 _I("[CEC_OPCODE_MENU_REQUEST 0x%X]", opcode);
648                 buffer[0] = (laddr << 4) | ldst;
649                 buffer[1] = CEC_OPCODE_MENU_STATUS;
650                 buffer[2] = 0x0;/*active*/
651                 size = 3;
652                 _I("Tx : [CEC_OPCODE_MENU_STATUS 0x%X]", CEC_OPCODE_MENU_STATUS);
653                 break;
654         case CEC_OPCODE_GET_DEVICE_VENDOR_ID:
655                 _I("[CEC_OPCODE_GET_DEVICE_VENDOR_ID 0x%X]", opcode);
656                 buffer[0] = (laddr << 4) | ldst;
657                 buffer[1] = CEC_OPCODE_DEVICE_VENDOR_ID;
658                 buffer[2] = 0x00;
659                 buffer[3] = 0x00;
660                 buffer[4] = 0xF0;
661                 size = 5;
662                 _I("Tx : [CEC_OPCODE_GET_DEVICE_VENDOR_ID 0x%X]", CEC_OPCODE_DEVICE_VENDOR_ID);
663                 break;
664         case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
665                 _I("[CEC_OPCODE_VENDOR_COMMAND_WITH_ID 0x%X] : %2X%2X%2X", opcode,
666                 buffer[2], buffer[3], buffer[4]);
667                 break;
668                 case CEC_OPCODE_GET_CEC_VERSION:
669                 buffer[0] = (laddr << 4) | ldst;
670                 buffer[1] = CEC_OPCODE_CEC_VERSION;
671                 buffer[2] = 0x05;
672                 size = 3;
673                 _I("Tx : [CEC_OPCODE_CEC_VERSION 0x%X] : 0x%X", CEC_OPCODE_CEC_VERSION, buffer[2]);
674                 break;
675         case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
676                 _I("[CEC_OPCODE_GIVE_DEVICE_POWER_STATUS 0x%X]", opcode);
677                 buffer[0] = (laddr << 4) | ldst;
678                 buffer[1] = CEC_OPCODE_REPORT_POWER_STATUS;
679                 buffer[2] = 0x0;
680                 size = 3;
681                 _I("Tx : [CEC_OPCODE_REPORT_POWER_STATUS 0x%X]", CEC_OPCODE_REPORT_POWER_STATUS);
682                 break;
683         case CEC_OPCODE_REPORT_POWER_STATUS:
684                 _I("[CEC_OPCODE_REPORT_POWER_STATUS 0x%X]", opcode);
685                 CECOneTouchPlay(buffer, laddr, paddr);
686                 break;
687         case CEC_OPCODE_STANDBY:
688                 _I("CEC_OPCODE_STANDBY 0x%X", opcode);
689                 CECHandleKey(opcode, buffer[1]);
690                 break;
691         case CEC_OPCODE_ROUTING_CHANGE:
692                 _I("CEC_OPCODE_ROUTING_CHANGE 0x%X r:0x0%x  p:0x0%x", opcode, raddr, paddr);
693                 if(paddr != raddr) {
694                         CECHandleKey(opcode, buffer[1]);
695                         _I("CEC_OPCODE_ROUTING_CHANGE Send HomeKey");
696                 }
697                 break;
698         case CEC_OPCODE_GIVE_OSD_NAME:
699                 _I("CEC_OPCODE_GIVE_OSD_NAME 0x%X", opcode);
700                 buffer[0] = (laddr << 4) | ldst;
701                 buffer[1] = CEC_OPCODE_SET_OSD_NAME;
702                 buffer[2] = 'T';
703                 buffer[3] = 'i';
704                 buffer[4] = 'z';
705                 buffer[5] = 'e';
706                 buffer[6] = 'n';
707                 buffer[7] = 'G';
708                 buffer[8] = 'a';
709                 buffer[9] = 't';
710                 buffer[10] = 'e';
711                 buffer[11] = 'w';
712                 buffer[12] = 'a';
713                 buffer[13] = 'y';
714                 size = 14;
715                 _I("Tx : [CEC_OPCODE_SET_OSD_NAME 0x%X]", CEC_OPCODE_SET_OSD_NAME);
716                 break;
717         case CEC_OPCODE_USER_CONTROL_PRESSED:
718         case CEC_OPCODE_USER_CONTROL_RELEASED:
719         case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
720         case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
721         case CEC_OPCODE_DECK_CONTROL:
722         case CEC_OPCODE_PLAY:
723                 CECHandleKey(opcode, buffer[2]);
724                 break;
725         case CEC_OPCODE_ABORT:
726         case CEC_OPCODE_FEATURE_ABORT:
727         default:
728                 /* send "Feature Abort" */
729                 buffer[0] = (laddr << 4) | ldst;
730                 buffer[1] = CEC_OPCODE_FEATURE_ABORT;
731                 buffer[2] = CEC_OPCODE_ABORT;
732                 buffer[3] = 0x04; // "refused"
733                 size = 4;
734                 break;
735         }
736
737         return size;
738 }