]> git.mxchange.org Git - flightgear.git/blobdiff - src/Input/FGLinuxEventInput.cxx
MSVC9 fix
[flightgear.git] / src / Input / FGLinuxEventInput.cxx
index 9d7b804ce243d880f55314d1fbe92769c4b3269f..183c7b3ab805c319b84bee27b0c3de372d611ac6 100644 (file)
@@ -198,6 +198,34 @@ static struct EventTypes {
 
 };
 
+static struct enbet {
+  unsigned type;
+  const char * name;
+} EVENT_NAMES_BY_EVENT_TYPE[] = {
+  { EV_SYN, "syn" },
+  { EV_KEY, "button" },
+  { EV_REL, "rel" },
+  { EV_ABS, "abs" },
+  { EV_MSC, "msc" },
+  { EV_SW, "button" },
+  { EV_LED, "led" },
+  { EV_SND, "snd" },
+  { EV_REP, "rep" },
+  { EV_FF, "ff" },
+  { EV_PWR, "pwr" },
+  { EV_FF_STATUS, "ff-status" }
+};
+
+
+class EventNameByEventType : public map<unsigned,const char*> {
+public:
+  EventNameByEventType() {
+    for( unsigned i = 0; i < sizeof(EVENT_NAMES_BY_EVENT_TYPE)/sizeof(EVENT_NAMES_BY_EVENT_TYPE[0]); i++ )
+      (*this)[EVENT_NAMES_BY_EVENT_TYPE[i].type] = EVENT_NAMES_BY_EVENT_TYPE[i].name;
+  }
+};
+static EventNameByEventType EVENT_NAME_BY_EVENT_TYPE;
+
 class EventNameByType : public map<TypeCode,const char*> {
 public:
   EventNameByType() {
@@ -245,17 +273,60 @@ FGLinuxInputDevice::FGLinuxInputDevice() :
 {
 }
 
+static inline bool bitSet( unsigned char * buf, unsigned char bit )
+{
+  return (buf[bit/sizeof(bit)/8] >> (bit%(sizeof(bit)*8))) & 1;
+}
+
 void FGLinuxInputDevice::Open()
 {
   if( fd != -1 ) return;
   if( (fd = ::open( devname.c_str(), O_RDWR )) == -1 ) { 
     throw exception();
   }
+
+  if( GetGrab() && ioctl( fd, EVIOCGRAB, 2 ) == -1 ) {
+    SG_LOG( SG_INPUT, SG_WARN, "Can't grab " << devname << " for exclusive access" );
+  }
+
+  unsigned char buf[ABS_CNT/sizeof(unsigned char)/8];
+  // get axes maximums
+  if( ioctl( fd, EVIOCGBIT(EV_ABS,ABS_MAX), buf ) == -1 ) {
+    SG_LOG( SG_INPUT, SG_WARN, "Can't get abs-axes for " << devname );
+  } else {
+    for( unsigned i = 0; i < ABS_MAX; i++ ) {
+      if( bitSet( buf, i ) ) {
+        struct input_absinfo ai;
+        if( ioctl(fd, EVIOCGABS(i), &ai) == -1 ) {
+          SG_LOG( SG_INPUT, SG_WARN, "Can't get abs-axes maximums for " << devname );
+          continue;
+        }
+        absinfo[i] = ai;
+      }
+    }
+  }
+}
+
+double FGLinuxInputDevice::Normalize( struct input_event & event ) 
+{
+  if( absinfo.count(event.code) > 0 ) {
+     const struct input_absinfo & ai = absinfo[(unsigned int)event.code];
+     if( ai.maximum == ai.minimum )
+       return 0.0;
+     return ((double)event.value-(double)ai.minimum)/((double)ai.maximum-(double)ai.minimum);
+  } else {
+    return (double)event.value;
+  }
 }
 
 void FGLinuxInputDevice::Close()
 {
-  if( fd != -1 ) ::close(fd);
+  if( fd != -1 ) {
+    if( GetGrab() && ioctl( fd, EVIOCGRAB, 0 ) != 0 ) {
+      SG_LOG( SG_INPUT, SG_WARN, "Can't ungrab " << devname );
+    }
+    ::close(fd);
+  }
   fd = -1;
 }
 
@@ -290,7 +361,13 @@ const char * FGLinuxInputDevice::TranslateEventName( FGEventData & eventData )
   typeCode.type = linuxEventData.type;
   typeCode.code = linuxEventData.code;
   if( EVENT_NAME_BY_TYPE.count(typeCode) == 0 ) {
-    sprintf( ugly_buffer, "unknown-%u-%u", (unsigned)linuxEventData.type, (unsigned)linuxEventData.code );
+    // event not known in translation tables
+    if( EVENT_NAME_BY_EVENT_TYPE.count(linuxEventData.type) == 0 ) {
+      // event type not known in translation tables
+      sprintf( ugly_buffer, "unknown-%u-%u", (unsigned)linuxEventData.type, (unsigned)linuxEventData.code );
+      return ugly_buffer;
+    }
+    sprintf( ugly_buffer, "%s-%u", EVENT_NAME_BY_EVENT_TYPE[linuxEventData.type], (unsigned)linuxEventData.code );
     return ugly_buffer;
   }
 
@@ -329,9 +406,9 @@ static void DeviceRemovedCallback (LibHalContext *ctx, const char *udi)
 }
 #endif
 
-void FGLinuxEventInput::init()
+void FGLinuxEventInput::postinit()
 {
-  FGEventInput::init();
+  FGEventInput::postinit();
 
   DBusConnection * connection;
   DBusError dbus_error;
@@ -394,7 +471,6 @@ void FGLinuxEventInput::AddHalDevice( const char * udi )
 void FGLinuxEventInput::update( double dt )
 {
   FGEventInput::update( dt );
-
   // index the input devices by the associated fd and prepare
   // the pollfd array by filling in the file descriptor
   struct pollfd fds[input_devices.size()];
@@ -425,6 +501,9 @@ void FGLinuxEventInput::update( double dt )
 
         FGLinuxEventData eventData( event, dt, modifiers );
 
+        if( event.type == EV_ABS )
+          eventData.value = devicesByFd[fds[i].fd]->Normalize( event );
+
         // let the FGInputDevice handle the data
         devicesByFd[fds[i].fd]->HandleEvent( eventData );
       }