lib/driver/rc.cpp,rcinput.cpp: only do EVIOCGRAB when event bit 0x1E is set in event...
[enigma2.git] / lib / driver / rc.cpp
1 #include <lib/driver/rc.h>
2
3 #include <asm/types.h>
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <linux/input.h>
8
9 #include <lib/base/init.h>
10 #include <lib/base/init_num.h>
11 #include <lib/base/eerror.h>
12
13 /*
14  *  note on the enigma input layer:
15  *  the enigma input layer (rc*) supports n different devices which
16  *  all have completely different interfaces, mapped down to 32bit + 
17  *  make/break/release codes mapped down (via xml files) to "actions".
18  *  this was necessary to support multiple remote controls with proprietary
19  *  interfaces. now everybody is using input devices, and thus adding
20  *  another input layer seems to be a bit overkill. BUT:
21  *  image a remote control with two hundred buttons. each and every function
22  *  in enigma can be bound to a button. no need to use them twice. 
23  *  for example, you would have KEY_MENU assigned to a menu for setup etc.,
24  *  but no audio and video settings, since you have special keys for that,
25  *  and you don't want to display a big menu with entries that are available
26  *  with another single key.
27  *  then image a remote control with ten buttons. do you really want to waste
28  *  KEY_MENU for a simple menu? you need the audio/video settings there too.
29  *  take this just as a (bad) example. another (better) example might be front-
30  *  button-keys. usually you have KEY_UP, KEY_DOWN, KEY_POWER. you don't want
31  *  them to behave like the remote-control-KEY_UP, KEY_DOWN and KEY_POWER,
32  *  don't you? 
33  *  so here we can map same keys of different input devices to different 
34  *  actions. have fun.
35  */
36
37 eRCDevice::eRCDevice(std::string id, eRCDriver *driver): driver(driver), id(id)
38 {
39         input=driver->getInput();
40         driver->addCodeListener(this);
41         eRCInput::getInstance()->addDevice(id, this);
42 }
43
44 eRCDevice::~eRCDevice()
45 {
46         driver->removeCodeListener(this);
47         eRCInput::getInstance()->removeDevice(id.c_str());
48 }
49
50 eRCDriver::eRCDriver(eRCInput *input): input(input), enabled(1)
51 {
52 }
53
54 eRCDriver::~eRCDriver()
55 {
56         for (std::list<eRCDevice*>::iterator i=listeners.begin(); i!=listeners.end(); ++i)
57                 delete *i;
58 }
59
60 void eRCShortDriver::keyPressed(int)
61 {
62         __u16 rccode;
63         while (1)
64         {
65                 if (read(handle, &rccode, 2)!=2)
66                         break;
67                 if (enabled && !input->islocked())
68                         for (std::list<eRCDevice*>::iterator i(listeners.begin()); i!=listeners.end(); ++i)
69                                 (*i)->handleCode(rccode);
70         }
71 }
72
73 eRCShortDriver::eRCShortDriver(const char *filename): eRCDriver(eRCInput::getInstance())
74 {
75         handle=open(filename, O_RDONLY|O_NONBLOCK);
76         if (handle<0)
77         {
78                 eDebug("failed to open %s", filename);
79                 sn=0;
80         } else
81         {
82                 sn=eSocketNotifier::create(eApp, handle, eSocketNotifier::Read);
83                 CONNECT(sn->activated, eRCShortDriver::keyPressed);
84         }
85 }
86
87 eRCShortDriver::~eRCShortDriver()
88 {
89         if (handle>=0)
90                 close(handle);
91 }
92
93 void eRCInputEventDriver::keyPressed(int)
94 {
95         struct input_event ev;
96         while (1)
97         {
98                 if (read(handle, &ev, sizeof(struct input_event))!=sizeof(struct input_event))
99                         break;
100                 if (enabled && !input->islocked())
101                         for (std::list<eRCDevice*>::iterator i(listeners.begin()); i!=listeners.end(); ++i)
102                                 (*i)->handleCode((long)&ev);
103         }
104 }
105
106 eRCInputEventDriver::eRCInputEventDriver(const char *filename): eRCDriver(eRCInput::getInstance())
107 {
108         handle=open(filename, O_RDONLY|O_NONBLOCK);
109         if (handle<0)
110         {
111                 eDebug("failed to open %s", filename);
112                 sn=0;
113         } else
114         {
115                 sn=eSocketNotifier::create(eApp, handle, eSocketNotifier::Read);
116                 CONNECT(sn->activated, eRCInputEventDriver::keyPressed);
117         }
118 }
119
120 std::string eRCInputEventDriver::getDeviceName()
121 {
122         char name[128]="";
123         if (handle >= 0)
124                 ::ioctl(handle, EVIOCGNAME(128), name);
125         return name;
126 }
127
128 void eRCInputEventDriver::setExclusive(bool b)
129 {
130         if (handle >= 0)
131         {
132                 long evbits;
133                 int grab = b;
134                 if (::ioctl(handle, EVIOCGBIT(0, EV_MAX+1), &evbits) < 0)
135                         perror("EVIOCGBIT");
136                 else if ((evbits & (1 << 0x1E)) && ::ioctl(handle, EVIOCGRAB, grab) < 0)
137                         perror("EVIOCGRAB");
138         }
139 }
140
141 eRCInputEventDriver::~eRCInputEventDriver()
142 {
143         if (handle>=0)
144                 close(handle);
145 }
146
147 eRCConfig::eRCConfig()
148 {
149         reload();
150 }
151
152 eRCConfig::~eRCConfig()
153 {
154         save();
155 }
156
157 void eRCConfig::set( int delay, int repeat )
158 {
159         rdelay = delay;
160         rrate = repeat;
161 }
162
163 void eRCConfig::reload()
164 {
165         rdelay=500;
166         rrate=100;
167 }
168
169 void eRCConfig::save()
170 {
171 }
172
173 eRCInput *eRCInput::instance;
174
175 eRCInput::eRCInput()
176 {
177         ASSERT( !instance);
178         instance=this;
179         locked = 0;
180         keyboardMode = kmNone;
181 }
182
183 eRCInput::~eRCInput()
184 {
185 }
186
187 void eRCInput::close()
188 {
189 }
190
191 bool eRCInput::open()
192 {
193         return false;
194 }
195
196 void eRCInput::lock()
197 {
198         locked=1;
199         for (std::map<std::string,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i)
200                 i->second->setExclusive(false);
201 }
202
203 void eRCInput::unlock()
204 {
205         locked=0;
206         for (std::map<std::string,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i)
207                 i->second->setExclusive(true);
208 }
209
210 void eRCInput::addDevice(const std::string &id, eRCDevice *dev)
211 {
212         devices.insert(std::pair<std::string,eRCDevice*>(id, dev));
213 }
214
215 void eRCInput::removeDevice(const std::string &id)
216 {
217         devices.erase(id);
218 }
219
220 eRCDevice *eRCInput::getDevice(const std::string &id)
221 {
222         std::map<std::string,eRCDevice*>::iterator i=devices.find(id);
223         if (i == devices.end())
224         {
225                 eDebug("failed, possible choices are:");
226                 for (std::map<std::string,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i)
227                         eDebug("%s", i->first.c_str());
228                 return 0;
229         }
230         return i->second;
231 }
232
233 std::map<std::string,eRCDevice*,eRCInput::lstr> &eRCInput::getDevices()
234 {
235         return devices;
236 }
237
238 eAutoInitP0<eRCInput> init_rcinput(eAutoInitNumbers::rc, "RC Input layer");