rcconsole: fix for escape codes split into multiple reads
[openblackhole/openblackhole-enigma2.git] / lib / driver / rcconsole.cpp
1 #include <lib/base/init.h>
2 #include <lib/base/init_num.h>
3 #include <lib/base/eerror.h>
4 #include <lib/driver/rcconsole.h>
5 #include <stdio.h>
6 #include <fcntl.h>
7
8 eRCConsoleDriver::eRCConsoleDriver(const char *filename): eRCDriver(eRCInput::getInstance()), m_escape(false)
9 {
10         handle=open(filename, O_RDONLY|O_NONBLOCK);
11         if (handle<0)
12         {
13                 eDebug("failed to open %s", filename);
14                 sn=0;
15         } else
16         {
17                 sn=eSocketNotifier::create(eApp, handle, eSocketNotifier::Read);
18                 CONNECT(sn->activated, eRCConsoleDriver::keyPressed);
19         }
20         
21                 /* set console mode */
22         struct termios t;
23         tcgetattr(handle, &t);
24         ot = t;
25         t.c_lflag &= ~(ECHO | ICANON | ECHOK | ECHOE | ECHONL);
26         tcsetattr(handle, TCSANOW,&t);
27 }
28
29 eRCConsoleDriver::~eRCConsoleDriver()
30 {
31         tcsetattr(handle,TCSANOW, &ot);
32         if (handle>=0)
33                 close(handle);
34 }
35
36 void eRCConsoleDriver::keyPressed(int)
37 {
38         unsigned char data[16];
39         unsigned char *d = data;
40         int num = read(handle, data, 16);
41         unsigned char code;
42         
43         int km = input->getKeyboardMode();
44
45         if (km == eRCInput::kmNone)
46                 return;
47
48         while (num--)
49         {
50                 code = *d++;
51 //              eDebug("console code %02x\n", code);
52                 if (km == eRCInput::kmAscii) {
53                         if (m_escape) {
54                                 if (code != '[')
55                                         m_escape = false;
56                                 continue;
57                         }
58
59                         if (code == 27) // escape code
60                                 m_escape = true;
61
62                         if ((code < 32) ||      // control characters
63                             (code == 0x7e) ||   // mute, einfg, entf
64                             (code == 0x7f))     // backspace
65                                 continue;
66                 }
67
68                 for (std::list<eRCDevice*>::iterator i(listeners.begin()); i!=listeners.end(); ++i)
69                 {
70 //                      eDebug("ascii %02x", code);
71                         (*i)->handleCode(code);
72                 }
73         }
74 }
75
76 void eRCConsole::handleCode(long code)
77 {
78         input->keyPressed(eRCKey(this, code, eRCKey::flagAscii));
79 }
80
81 eRCConsole::eRCConsole(eRCDriver *driver)
82                         : eRCDevice("Console", driver)
83 {
84 }
85
86 const char *eRCConsole::getDescription() const
87 {
88         return "Console";
89 }
90
91 const char *eRCConsole::getKeyDescription(const eRCKey &key) const
92 {
93         return 0;
94 }
95
96 int eRCConsole::getKeyCompatibleCode(const eRCKey &key) const
97 {
98         return key.code;
99 }
100
101 class eRCConsoleInit
102 {
103         eRCConsoleDriver driver;
104         eRCConsole device;
105 public:
106         eRCConsoleInit(): driver("/dev/vc/0"), device(&driver)
107         {
108         }
109 };
110
111 eAutoInitP0<eRCConsoleInit> init_rcconsole(eAutoInitNumbers::rc+1, "Console RC Driver");