trunk 20080912
[gitenigma.git] / lib / driver / rc.cpp
blobcd56a1cbf6960bc092f632946ac1316a6df17c28
1 #include <lib/driver/rc.h>
3 #include <config.h>
4 #include <asm/types.h>
5 #include <stdio.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <linux/input.h>
10 #include <lib/system/init.h>
11 #include <lib/system/init_num.h>
12 #include <lib/system/econfig.h>
13 #include <lib/base/eerror.h>
16 * note on the enigma input layer:
17 * the enigma input layer (rc*) supports n different devices which
18 * all have completely different interfaces, mapped down to 32bit +
19 * make/break/release codes mapped down (via xml files) to "actions".
20 * this was necessary to support multiple remote controls with proprietary
21 * interfaces. now everybody is using input devices, and thus adding
22 * another input layer seems to be a bit overkill. BUT:
23 * image a remote control with two hundred buttons. each and every function
24 * in enigma can be bound to a button. no need to use them twice.
25 * for example, you would have KEY_MENU assigned to a menu for setup etc.,
26 * but no audio and video settings, since you have special keys for that,
27 * and you don't want to display a big menu with entries that are available
28 * with another single key.
29 * then image a remote control with ten buttons. do you really want to waste
30 * KEY_MENU for a simple menu? you need the audio/video settings there too.
31 * take this just as a (bad) example. another (better) example might be front-
32 * button-keys. usually you have KEY_UP, KEY_DOWN, KEY_POWER. you don't want
33 * them to behave like the remote-control-KEY_UP, KEY_DOWN and KEY_POWER,
34 * don't you?
35 * so here we can map same keys of different input devices to different
36 * actions. have fun.
39 int eRCDevice::getKeyCompatibleCode(const eRCKey &) const
41 return -1;
44 eRCDevice::eRCDevice(const eString &id, eRCDriver *driver): driver(driver), id(id)
46 input=driver->getInput();
47 driver->addCodeListener(this);
48 eRCInput::getInstance()->addDevice(id, this);
51 eRCDevice::~eRCDevice()
53 driver->removeCodeListener(this);
54 eRCInput::getInstance()->removeDevice(id.c_str());
57 eRCDriver::eRCDriver(eRCInput *input): input(input), enabled(1)
61 eRCDriver::~eRCDriver()
63 for (std::list<eRCDevice*>::iterator i=listeners.begin(); i!=listeners.end(); ++i)
64 delete *i;
67 eRCConfig::eRCConfig()
69 reload();
72 eRCConfig::~eRCConfig()
74 save();
77 void eRCConfig::set( int delay, int repeat )
79 rdelay = delay;
80 rrate = repeat;
83 void eRCConfig::reload()
85 bool mustStore=false;
86 rdelay=500;
87 rrate=100;
88 if ( eConfig::getInstance()->getKey("/ezap/rc/repeatRate", rrate) )
89 mustStore=true;
90 if ( eConfig::getInstance()->getKey("/ezap/rc/repeatDelay", rdelay) )
91 mustStore=true;
92 if ( mustStore )
93 save();
96 void eRCConfig::save()
98 eConfig::getInstance()->setKey("/ezap/rc/repeatRate", rrate);
99 eConfig::getInstance()->setKey("/ezap/rc/repeatDelay", rdelay);
102 eRCInput *eRCInput::instance;
104 eRCInput::eRCInput()
106 ASSERT( !instance);
107 instance=this;
108 handle = -1;
109 locked = 0;
110 keyboardMode = kmNone;
111 loadKeyboardMapping();
114 eRCInput::~eRCInput()
118 void eRCInput::close()
122 bool eRCInput::open()
124 return false;
127 int eRCInput::lock()
129 if ( !locked )
131 locked=1;
132 for ( std::map<eString,eRCDevice*,lstr>::iterator it( devices.begin() );
133 it != devices.end(); ++it)
135 it->second->getDriver()->flushBuffer();
136 it->second->getDriver()->lock();
139 return handle;
142 void eRCInput::unlock()
144 if (locked)
146 for ( std::map<eString,eRCDevice*,lstr>::iterator it( devices.begin() );
147 it != devices.end(); ++it)
149 it->second->getDriver()->flushBuffer();
150 it->second->getDriver()->unlock();
152 locked=0;
156 void eRCInput::setFile(int newh)
158 handle=newh;
161 void eRCInput::addDevice(const eString &id, eRCDevice *dev)
163 devices.insert(std::pair<eString,eRCDevice*>(id, dev));
166 void eRCInput::removeDevice(const eString &id)
168 devices.erase(id.c_str());
171 void eRCInput::loadKeyboardMapping()
173 char *current_map=0;
174 if ( eConfig::getInstance()->getKey("/ezap/keyboard/mapping", current_map) )
175 current_map = strdup(DATADIR "/keymaps/eng.kmap");
176 if ( system(eString().sprintf("busybox loadkmap < %s", current_map).c_str()) >> 8 )
177 eDebug("load keyboard mapping failed");
178 free(current_map);
181 eRCDevice *eRCInput::getDevice(const eString &id)
183 std::map<eString,eRCDevice*>::iterator i=devices.find(id);
184 if (i == devices.end())
186 eDebug("failed, possible choices are:");
187 for (std::map<eString,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i)
188 eDebug("%s", i->first.c_str());
189 return 0;
191 return i->second;
194 void eRCInput::setKeyboardMode(int mode)
196 for ( std::map<eString, eRCDevice*, eRCInput::lstr>::iterator it( devices.begin() )
197 ;it != devices.end(); ++it)
199 eString tmp = it->first;
200 tmp.upper();
201 if ( !!strstr(tmp.c_str(), "KEYBOARD") )
203 keyboardMode = mode;
204 break;
209 std::map<eString,eRCDevice*,eRCInput::lstr> &eRCInput::getDevices()
211 return devices;
214 eAutoInitP0<eRCInput> init_rcinput(eAutoInitNumbers::rc, "RC Input layer");
216 #if HAVE_DVB_API_VERSION < 3
217 eRCShortDriver::eRCShortDriver(const char *filename): eRCDriver(eRCInput::getInstance())
219 handle=open(filename, O_RDONLY|O_NONBLOCK);
220 if (handle<0)
222 eDebug("failed to open %s", filename);
223 sn=0;
224 } else
226 sn=new eSocketNotifier(eApp, handle, eSocketNotifier::Read);
227 CONNECT(sn->activated, eRCShortDriver::keyPressed);
228 eRCInput::getInstance()->setFile(handle);
229 flushBuffer();
233 eRCShortDriver::~eRCShortDriver()
235 if (handle>=0)
236 close(handle);
237 if (sn)
238 delete sn;
241 void eRCShortDriver::keyPressed(int)
243 __u16 rccode;
244 while (1)
246 if (read(handle, &rccode, 2)!=2)
247 break;
248 if (enabled)
249 for (std::list<eRCDevice*>::iterator i(listeners.begin()); i!=listeners.end(); ++i)
250 (*i)->handleCode(rccode);
254 #endif
256 eRCInputEventDriver::eRCInputEventDriver(const char *filename): eRCDriver(eRCInput::getInstance())
258 handle=open(filename, O_RDONLY|O_NONBLOCK);
260 if (handle<0)
262 eDebug("failed to open %s", filename);
263 sn=0;
265 else
267 sn=new eSocketNotifier(eApp, handle, eSocketNotifier::Read);
268 CONNECT(sn->activated, eRCInputEventDriver::keyPressed);
269 eRCInput::getInstance()->setFile(handle);
270 flushBuffer();
274 eRCInputEventDriver::~eRCInputEventDriver()
276 if (handle>=0)
277 close(handle);
278 delete sn;
281 void eRCInputEventDriver::keyPressed(int)
283 struct input_event ev;
284 while (1)
286 if (read(handle, &ev, sizeof(struct input_event))!=sizeof(struct input_event))
287 break;
289 if (enabled)
290 for (std::list<eRCDevice*>::iterator i(listeners.begin()); i!=listeners.end(); ++i)
291 (*i)->handleCode((int)&ev);
295 eString eRCInputEventDriver::getDeviceName()
297 char name[128]="";
299 if (handle >= 0)
300 ::ioctl(handle, EVIOCGNAME(128), name);
302 return name;