X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInput%2FFGLinuxEventInput.cxx;h=621e15fd8b41a9d5994ab96139385a160f5c2ff8;hb=2ea50c63bbb95e143662de2f136c79898236e38d;hp=b0de0d617893720090ef7d5f8fdc6dc9664e938b;hpb=5c57153e6233a112fa3aec8fd648a1a7d8743099;p=flightgear.git diff --git a/src/Input/FGLinuxEventInput.cxx b/src/Input/FGLinuxEventInput.cxx index b0de0d617..621e15fd8 100644 --- a/src/Input/FGLinuxEventInput.cxx +++ b/src/Input/FGLinuxEventInput.cxx @@ -29,6 +29,8 @@ #include #include #include +#include + struct TypeCode { unsigned type; @@ -174,9 +176,15 @@ static struct EventTypes { { { EV_SW, SW_LID }, "switch-lid" }, { { EV_SW, SW_TABLET_MODE }, "switch-tablet-mode" }, { { EV_SW, SW_HEADPHONE_INSERT }, "switch-headphone-insert" }, +#ifdef SW_RFKILL_ALL { { EV_SW, SW_RFKILL_ALL }, "switch-rfkill" }, +#endif +#ifdef SW_MICROPHONE_INSERT { { EV_SW, SW_MICROPHONE_INSERT }, "switch-microphone-insert" }, - { { EV_SW, SW_DOCK }, "swtich-dock" }, +#endif +#ifdef SW_DOCK + { { EV_SW, SW_DOCK }, "switch-dock" }, +#endif { { EV_LED, LED_NUML}, "led-numlock" }, { { EV_LED, LED_CAPSL}, "led-capslock" }, @@ -192,10 +200,38 @@ 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 { +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 { public: EventNameByType() { - for( int i = 0; i < sizeof(EVENT_TYPES)/sizeof(EVENT_TYPES[0]); i++ ) + for( unsigned i = 0; i < sizeof(EVENT_TYPES)/sizeof(EVENT_TYPES[0]); i++ ) (*this)[EVENT_TYPES[i].typeCode] = EVENT_TYPES[i].name; } }; @@ -204,14 +240,14 @@ static EventNameByType EVENT_NAME_BY_TYPE; struct ltstr { bool operator()(const char * s1, const char * s2 ) const { - return strcmp( s1, s2 ) < 0; + return string(s1).compare( s2 ) < 0; } }; class EventTypeByName : public map { public: EventTypeByName() { - for( int i = 0; i < sizeof(EVENT_TYPES)/sizeof(EVENT_TYPES[0]); i++ ) + for( unsigned i = 0; i < sizeof(EVENT_TYPES)/sizeof(EVENT_TYPES[0]); i++ ) (*this)[EVENT_TYPES[i].name] = EVENT_TYPES[i].typeCode; } }; @@ -220,9 +256,8 @@ static EventTypeByName EVENT_TYPE_BY_NAME; FGLinuxInputDevice::FGLinuxInputDevice( string aName, string aDevname ) : FGInputDevice(aName), - fd(-1), - devname( aDevname ) - + devname( aDevname ), + fd(-1) { } @@ -240,26 +275,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(); } -/* - input_event evt; - evt.type=EV_LED; - evt.code = 8; - evt.value = 1; - evt.time.tv_sec = 0; - evt.time.tv_usec = 0; - write( fd, &evt, sizeof(evt) ); -*/ + + 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; } @@ -294,7 +363,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; } @@ -333,9 +408,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; @@ -398,7 +473,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()]; @@ -418,7 +492,7 @@ void FGLinuxEventInput::update( double dt ) // do no more than maxpolls in a single loop to prevent locking int maxpolls = 100; while( maxpolls-- > 0 && ::poll( fds, i, 0 ) > 0 ) { - for( int i = 0; i < sizeof(fds)/sizeof(fds[0]); i++ ) { + for( unsigned i = 0; i < sizeof(fds)/sizeof(fds[0]); i++ ) { if( fds[i].revents & POLLIN ) { // if this device reports data ready, it should be a input_event struct @@ -429,6 +503,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 ); }