Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] Generic input device / event support for VDR?



Has anyone tried to add support for the generic input device / event interface to control VDR? This page for details of the input driver support http://linuxconsole.sourceforge.net/input/input.html

The DVB card drivers send the commands from the IR remote to the event layer and today these have to be translated into virutal key presses for them to be picked up by VDR.

A new driver could be added to VDR to pick up these event directly, without needing to go via the keyboard interface. This has the added bonus that VDR doesn't need to be on the current tty to pick up the events. Allowing you to change channels etc while using X or doing something completely different on the terminal.

It also allows the control device to be a joystick, gamepad or anything else supported by the input layer. In theory this makes the keyboard driver redundant (although I think only linux-2.6 forces the keyboard to go via the input layer).

I attached a driver which works for me. It is surprisingly easy to link the event interface to VDR, most of the code is debug information taken from the evtest.c example program which I used as a starting point.

Compile with "make REMOTE=EVENT" to activate this new input method & remove your remote.conf file to get VDR to learn the new keys (assuming you've already got your device generating input events).

Jon
diff -Nurw vdr-1.2.3/input_event.c vdr-ip2/input_event.c
--- vdr-1.2.3/input_event.c	1970-01-01 01:00:00.000000000 +0100
+++ vdr-ip2/input_event.c	2003-08-28 22:56:55.000000000 +0100
@@ -0,0 +1,171 @@
+/*
+ * input_event.h: Remote control based on Input event interface
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#include "input_event.h"
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#define REPEATLIMIT  20 // ms
+#define REPEATDELAY 350 // ms
+#define KEYPRESSDELAY 150 // ms
+
+#define EVENT_DEV "/dev/input/event0"
+
+
+char *events[EV_MAX + 1] = { "Reset", "Key", "Relative", "Absolute", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, "LED", "Sound", NULL, "Repeat", "ForceFeedback", NULL, "ForceFeedbackStatus"};
+char *keys[KEY_MAX + 1] = { "Reserved", "Esc", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "Minus", "Equal", "Backspace",
+"Tab", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "LeftBrace", "RightBrace", "Enter", "LeftControl", "A", "S", "D", "F", "G",
+"H", "J", "K", "L", "Semicolon", "Apostrophe", "Grave", "LeftShift", "BackSlash", "Z", "X", "C", "V", "B", "N", "M", "Comma", "Dot",
+"Slash", "RightShift", "KPAsterisk", "LeftAlt", "Space", "CapsLock", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
+"NumLock", "ScrollLock", "KP7", "KP8", "KP9", "KPMinus", "KP4", "KP5", "KP6", "KPPlus", "KP1", "KP2", "KP3", "KP0", "KPDot", "103rd",
+"F13", "102nd", "F11", "F12", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "KPEnter", "RightCtrl", "KPSlash", "SysRq",
+"RightAlt", "LineFeed", "Home", "Up", "PageUp", "Left", "Right", "End", "Down", "PageDown", "Insert", "Delete", "Macro", "Mute",
+"VolumeDown", "VolumeUp", "Power", "KPEqual", "KPPlusMinus", "Pause", "F21", "F22", "F23", "F24", "KPComma", "LeftMeta", "RightMeta",
+"Compose", "Stop", "Again", "Props", "Undo", "Front", "Copy", "Open", "Paste", "Find", "Cut", "Help", "Menu", "Calc", "Setup",
+"Sleep", "WakeUp", "File", "SendFile", "DeleteFile", "X-fer", "Prog1", "Prog2", "WWW", "MSDOS", "Coffee", "Direction",
+"CycleWindows", "Mail", "Bookmarks", "Computer", "Back", "Forward", "CloseCD", "EjectCD", "EjectCloseCD", "NextSong", "PlayPause",
+"PreviousSong", "StopCD", "Record", "Rewind", "Phone", "ISOKey", "Config", "HomePage", "Refresh", "Exit", "Move", "Edit", "ScrollUp",
+"ScrollDown", "KPLeftParenthesis", "KPRightParenthesis",
+"International1", "International2", "International3", "International4", "International5",
+"International6", "International7", "International8", "International9",
+"Language1", "Language2", "Language3", "Language4", "Language5", "Language6", "Language7", "Language8", "Language9",
+NULL, 
+"PlayCD", "PauseCD", "Prog3", "Prog4", "Suspend", "Close",
+NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+"Btn0", "Btn1", "Btn2", "Btn3", "Btn4", "Btn5", "Btn6", "Btn7", "Btn8", "Btn9",
+NULL, NULL,  NULL, NULL, NULL, NULL,
+"LeftBtn", "RightBtn", "MiddleBtn", "SideBtn", "ExtraBtn", "ForwardBtn", "BackBtn",
+NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+"Trigger", "ThumbBtn", "ThumbBtn2", "TopBtn", "TopBtn2", "PinkieBtn",
+"BaseBtn", "BaseBtn2", "BaseBtn3", "BaseBtn4", "BaseBtn5", "BaseBtn6",
+NULL, NULL, NULL, "BtnDead",
+"BtnA", "BtnB", "BtnC", "BtnX", "BtnY", "BtnZ", "BtnTL", "BtnTR", "BtnTL2", "BtnTR2", "BtnSelect", "BtnStart", "BtnMode",
+"BtnThumbL", "BtnThumbR", NULL,
+"ToolPen", "ToolRubber", "ToolBrush", "ToolPencil", "ToolAirbrush", "ToolFinger", "ToolMouse", "ToolLens", NULL, NULL,
+"Touch", "Stylus", "Stylus2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
+"Ok", "Select", "Goto", "Clear", "Power2", "Option", "Info", "Time", "Vendor",
+"Archive", "Program", "Channel", "Favorites", "EPG", "PVR", "MHP", "Language",
+"Title", "Subtitle", "Angle", "Zoom", "Mode", "Keyboard", "Screen", "PC", "TV",
+"TV2", "VCR", "VCR2", "Sat", "Sat2", "CD", "Tape", "Radio", "Tuner", "Player", 
+"Text", "DVD", "Aux", "MP3", "Audio", "Video", "Directory", "List", "Memo",
+"Calendar", "Red", "Green", "Yellow", "Blue", "ChannelUp", "ChannelDown", 
+"First", "Last", "AB", "Play", "Restart", "Slow", "Shuffle", "FastForward", 
+"Previous", "Next", "Digits", "Teen", "Twen", "Break" };
+
+char *absval[5] = { "Value", "Min  ", "Max  ", "Fuzz ", "Flat " };
+char *relatives[REL_MAX + 1] = { "X", "Y", "Z", NULL, NULL, NULL, "HWheel", "Dial", "Wheel" };
+char *absolutes[ABS_MAX + 1] = { "X", "Y", "Z", "Rx", "Ry", "Rz", "Throttle", "Rudder", "Wheel", "Gas", "Brake",
+NULL, NULL, NULL, NULL, NULL,
+"Hat0X", "Hat0Y", "Hat1X", "Hat1Y", "Hat2X", "Hat2Y", "Hat3X", "Hat 3Y", "Pressure", "Distance", "XTilt", "YTilt"};
+char *leds[LED_MAX + 1] = { "NumLock", "CapsLock", "ScrollLock", "Compose", "Kana", "Sleep", "Suspend", "Mute" };
+char *repeats[REP_MAX + 1] = { "Delay", "Period" };
+char *sounds[SND_MAX + 1] = { "Bell", "Click" };
+
+char **names[EV_MAX + 1] = { events, keys, relatives, absolutes, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, leds, sounds, NULL, repeats, NULL, NULL, NULL };
+
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define OFF(x)  ((x)%BITS_PER_LONG)
+#define BIT(x)  (1UL<<OFF(x))
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define test_bit(bit, array)	((array[LONG(bit)] >> OFF(bit)) & 1)
+
+
+cEventRemote::cEventRemote(char *DeviceName)
+:cRemote("EVENT")
+{
+  int version;
+  unsigned short id[4];
+  char name[256]="Unknown";
+  
+  if ((fd = open(DeviceName, O_RDONLY)) < 0) {
+    LOG_ERROR_STR(DeviceName);
+    return;
+  }
+  
+  if (ioctl(fd, EVIOCGVERSION, &version)) {
+    LOG_ERROR_STR(DeviceName);
+    return;
+  }
+  
+  isyslog("Input driver version is %d.%d.%d\n",
+	  version >> 16, (version >> 8) & 0xff, version & 0xff);
+  
+  ioctl(fd, EVIOCGID, id);
+  isyslog("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n",
+	  id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]);
+  
+  ioctl(fd, EVIOCGNAME(sizeof(name)), name);
+  isyslog("Input device name: \"%s\"\n", name);
+  
+  Start();
+}
+
+cEventRemote::~cEventRemote()
+{
+  Cancel();
+}
+
+bool cEventRemote::Ready(void)
+{
+  return fd >= 0;
+}
+
+void cEventRemote::Action(void)
+{
+  dsyslog("EVENT remote control thread started (pid=%d)", getpid());
+
+  struct input_event ev[64];
+  int timeout = -1;
+
+  for (; fd >= 0;) {
+
+      LOCK_THREAD;
+
+      bool ready = cFile::FileReady(fd, timeout);
+      int ret = ready ? safe_read(fd, (char *)ev, sizeof(*ev)) : -1;
+
+      if (ready && ret <= 0 ) {
+         esyslog("%s: ERROR Event connection lost", __FILE__);
+         close(fd);
+         fd = -1;
+         break;
+      }
+
+      if (ready && (ret < (int) sizeof(struct input_event))) {
+	esyslog("%s: error reading input", __FILE__);
+	close(fd);
+	fd = -1;
+	break;
+      }
+
+      if (ready) {
+	int i;
+	for (i = 0; i < ret / sizeof(struct input_event); i++) {
+	  int code    = ev[i].code;
+	  int type    = ev[i].type;
+	  int value   = ev[i].value;
+	  int repeat  = ( value == 2 ) ? 1 :0;
+	  int release = ( value == 0 ) ? 1 :0;
+	  
+	  dsyslog("Event: %s - %d (%s), value %d\n, relese = %d, repeat = %d",
+		  events[type] ? events[type] : "?",
+		  code,
+		  names[type] ? (names[type][code] ? names[type][code] : "?") : "?",
+		  value, release, repeat);
+	  
+	  Put(ev[i].code, repeat, release);
+	}
+      }
+  }
+}
diff -Nurw vdr-1.2.3/input_event.h vdr-ip2/input_event.h
--- vdr-1.2.3/input_event.h	1970-01-01 01:00:00.000000000 +0100
+++ vdr-ip2/input_event.h	2003-08-28 22:56:55.000000000 +0100
@@ -0,0 +1,27 @@
+/*
+ * input_event.h: Remote control based on Input event interface
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ */
+
+#ifndef __EVINP_H
+#define __EVINP_H
+
+#include <linux/input.h>
+#include "remote.h"
+#include "thread.h"
+
+class cEventRemote : public cRemote, private cThread {
+private:
+  enum { LIRC_KEY_BUF = 30, LIRC_BUFFER_SIZE = 128 };
+  int fd;
+  virtual void Action(void);
+public:
+  cEventRemote(char *DeviceName);
+  virtual ~cEventRemote();
+  virtual bool Ready(void);
+  };
+
+#endif //__LIRC_H
diff -Nurw vdr-1.2.3/Makefile vdr-ip2/Makefile
--- vdr-1.2.3/Makefile	2003-08-19 20:24:39.000000000 +0100
+++ vdr-ip2/Makefile	2003-08-28 22:56:55.000000000 +0100
@@ -37,7 +37,7 @@
        dvbplayer.o dvbspu.o eit.o eitscan.o font.o i18n.o interface.o keys.o\
        lirc.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o rcu.o\
        receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sources.o\
-       spu.o status.o svdrp.o thread.o timers.o tools.o transfer.o vdr.o videodir.o
+       spu.o status.o svdrp.o thread.o timers.o tools.o transfer.o vdr.o videodir.o input_event.o
 
 OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
 FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
diff -Nurw vdr-1.2.3/vdr.c vdr-ip2/vdr.c
--- vdr-1.2.3/vdr.c	2003-08-19 20:24:39.000000000 +0100
+++ vdr-ip2/vdr.c	2003-08-28 22:56:55.000000000 +0100
@@ -43,6 +43,7 @@
 #include "interface.h"
 #include "keys.h"
 #include "lirc.h"
+#include "input_event.h"
 #include "menu.h"
 #include "osd.h"
 #include "plugin.h"
@@ -412,7 +413,10 @@
   new cRcuRemote("/dev/ttyS1");
 #elif defined(REMOTE_LIRC)
   new cLircRemote("/dev/lircd");
+#elif defined(REMOTE_EVENT)
+  new cEventRemote("/dev/input/event0");
 #endif
+
 #if defined(REMOTE_KBD)
   if (!DaemonMode && HasStdin)
      new cKbdRemote;

Home | Main Index | Thread Index