From: bruceperens Date: Sat, 19 Apr 2014 00:37:30 +0000 (+0000) Subject: Implement event capture. X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=9d64c4ef74b3307674c4d9097578a0096f0c0de6;p=freetel-svn-tracking.git Implement event capture. git-svn-id: https://svn.code.sf.net/p/freetel/code@1509 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/freedv-server/source/platform/linux/evdev.cpp b/freedv-server/source/platform/linux/evdev.cpp index 429cd3c8..8c45a529 100644 --- a/freedv-server/source/platform/linux/evdev.cpp +++ b/freedv-server/source/platform/linux/evdev.cpp @@ -13,8 +13,8 @@ #include namespace FreeDV { - static bool - bit_set(unsigned int bit, const uint8_t * field) + inline static bool + bit_is_set(unsigned int bit, const uint8_t * field) { return ((field[bit / 8] & (1 << (bit % 8))) != 0); } @@ -69,6 +69,18 @@ namespace FreeDV { return string; } + bool + EvDev::button_state(unsigned int index) + { + uint8_t buttons[(KEY_MAX + 7) / 8]; + + + if ( ioctl(fd, EVIOCGKEY(sizeof(buttons)), buttons) < 0 ) + do_throw(errno, name, special_file, "ioctl EVIOCGKEY"); + + return bit_is_set(index, buttons); + } + void EvDev::delete_enumeration( EvDev::device_enumeration * data, @@ -140,7 +152,7 @@ namespace FreeDV { device.name = strdup(str.str().c_str()); - if ( bit_set(EV_KEY, device.event_types) == 0 + if ( bit_is_set(EV_KEY, device.event_types) == 0 || ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device.buttons)), device.buttons) < 0 ) memset(device.buttons, 0, sizeof(device.buttons)); @@ -148,6 +160,17 @@ namespace FreeDV { return true; } + bool + EvDev::has_button(unsigned int index) + { + uint8_t buttons[(KEY_MAX + 7) / 8]; + + if ( ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(buttons)), buttons) < 0 ) + return false; + + return bit_is_set(index, buttons); + } + int EvDev::poll_fds(PollType * array, int length) { @@ -167,7 +190,7 @@ namespace FreeDV { if ( ioctl(fd, FIONREAD, &length) < 0 ) do_throw(errno, name, special_file, "ioctl FIONREAD"); - return length; + return length / sizeof(input_event); } std::size_t diff --git a/freedv-server/source/platform/linux/evdev.h b/freedv-server/source/platform/linux/evdev.h index d8d3589b..52d11a8c 100644 --- a/freedv-server/source/platform/linux/evdev.h +++ b/freedv-server/source/platform/linux/evdev.h @@ -26,6 +26,8 @@ namespace FreeDV { struct device_enumeration & device); public: + bool button_state(unsigned int index); + static void delete_enumeration( device_enumeration * data, std::size_t count); @@ -33,12 +35,18 @@ namespace FreeDV { static device_enumeration * enumerate(std::size_t & count); + bool has_button(unsigned int index); + + const char * long_name() { return name; } + int poll_fds(PollType *, int); std::size_t ready(); std::size_t read_events(input_event * data, std::size_t count); + const char * device_name() { return special_file; } + EvDev(const char * name); ~EvDev(); }; diff --git a/freedv-server/source/platform/linux/ptt_evdev.cpp b/freedv-server/source/platform/linux/ptt_evdev.cpp index 0263329f..08f3c16e 100644 --- a/freedv-server/source/platform/linux/ptt_evdev.cpp +++ b/freedv-server/source/platform/linux/ptt_evdev.cpp @@ -5,24 +5,51 @@ /// #include "evdev.h" +#include +#include #include #include - -static bool -bit_set(unsigned int bit, const uint8_t * field) -{ - return ((field[bit / 8] & (1 << (bit % 8))) != 0); -} +#include namespace FreeDV { + NORETURN static void + do_throw( + const char * name, + const char * message = 0) + { + std::ostringstream str; + + str << "EVDEV "; + + str << '\"' << name << "\": "; + if ( message ) { + str << message; + } + + str << '.'; + throw std::runtime_error(str.str().c_str()); + } + + inline static bool + bit_is_set(unsigned int bit, const uint8_t * field) + { + return ((field[bit / 8] & (1 << (bit % 8))) != 0); + } + /// PTT driver using Linux evdev. /// class PTT_EvDev : public PTTInput { private: - /// This is true if ready has not yet been sent. - /// + EvDev * dev; + int button_index; bool pressed; - bool ready_one_shot; + bool changed; + + PTT_EvDev(const PTT_EvDev &); + PTT_EvDev & operator =(const PTT_EvDev &); + + void process_events(); + public: /// Instantiate. /// @@ -37,7 +64,7 @@ namespace FreeDV { /// \return The number of file descriptors written to the array. virtual int poll_fds(PollType * array, int space); - /// Return the amount of bytes ready for read. + /// Return the amount of events ready for read. /// std::size_t ready(); @@ -47,33 +74,90 @@ namespace FreeDV { }; PTT_EvDev::PTT_EvDev(const char * _parameters) - : PTTInput("constant", _parameters), pressed(false), ready_one_shot(true) + : PTTInput("evdev", _parameters), dev(0), button_index(0), pressed(false), + changed(false) { + char * p = strdup(parameters); + char * number = index(p, ','); + + if ( number == 0 ) + do_throw( + parameters, + "The device name must be followed by a comma and a button number."); + + *number++ = '\0'; + + button_index = atoi(number); + + dev = new EvDev(p); + delete p; + + if ( !dev->has_button(button_index) ) { + std::ostringstream str; + + str << "There is no button " << button_index << " in this device."; + + do_throw(parameters, str.str().c_str()); + } + + pressed = dev->button_state(button_index); } PTT_EvDev::~PTT_EvDev() { + delete dev; } int - PTT_EvDev::poll_fds(PollType *, int) + PTT_EvDev::poll_fds(PollType * array, int count) { - return 0; + return dev->poll_fds(array, count); + } + + void + PTT_EvDev::process_events() + { + while ( dev->ready() > 0 ) { + input_event events[10]; + + const std::size_t count = dev->read_events( + events, + sizeof(events) / sizeof(*events)); + + for ( std::size_t i = 0; i < count; i++ ) { + const input_event * const event = &events[i]; + if ( event->type == EV_KEY && event->code == button_index ) { + switch ( event->value ) { + case 0: + if ( pressed ) + changed = true; + pressed = false; + break; + case 1: + if ( !pressed ) + changed = true; + pressed = true; + break; + default: + ; + } + } + } + } } std::size_t PTT_EvDev::ready() { - if ( ready_one_shot ) - return 1; - else - return 0; + return dev->ready(); } bool PTT_EvDev::state() { - return false; + process_events(); + changed = false; + return pressed; } PTTInput * @@ -89,18 +173,18 @@ namespace FreeDV { EvDev::device_enumeration * const devices = EvDev::enumerate(count); for ( std::size_t i = 0; i < count; i++ ) { - if ( bit_set(EV_KEY, devices[i].event_types) ) { + if ( bit_is_set(EV_KEY, devices[i].event_types) ) { int low = -1; int high = -1; for ( int j = KEY_F1; j <= KEY_MAX; j++ ) { - if ( bit_set(j, devices[i].buttons) ) { + if ( bit_is_set(j, devices[i].buttons) ) { low = j; break; } } for ( int j = KEY_MAX; j >= KEY_F1; j-- ) { - if ( bit_set(j, devices[i].buttons) ) { + if ( bit_is_set(j, devices[i].buttons) ) { high = j; break; }