Evdev enumeration working.
authorbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 18 Apr 2014 16:57:09 +0000 (16:57 +0000)
committerbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 18 Apr 2014 16:57:09 +0000 (16:57 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1501 01035d8c-6547-0410-b346-abe4f91aad63

freedv-server/source/drivers.h
freedv-server/source/platform/linux/alsa.h [new file with mode: 0644]
freedv-server/source/platform/linux/evdev.cpp
freedv-server/source/platform/linux/evdev.h
freedv-server/source/platform/linux/ptt_evdev.cpp [new file with mode: 0644]

index 1494608892439c7e9c04394cb64cd67050f41cd2..d92c92a34e885b9355b3c08382bcc9a93cf6a436 100644 (file)
@@ -796,6 +796,12 @@ Modem *            ModemNoOp(const char * parameter);
 ///
 PTTInput *     PTTConstant(const char * parameter);
 
+/// Opens a push-to-talk device based on Linux evdev.
+/// \param parameter
+/// \return A pointer to the PTT_EvDev instance for the device.
+///
+PTTInput *     PTT_EvDev(const char * parameter);
+
 /// Opens a "constant" text ionput device, which has a constant text value
 /// which is to be transmitted as ancillary data.
 /// \param parameter The text to be transmitted.
diff --git a/freedv-server/source/platform/linux/alsa.h b/freedv-server/source/platform/linux/alsa.h
new file mode 100644 (file)
index 0000000..5f72599
--- /dev/null
@@ -0,0 +1,21 @@
+/// \file platform/linux/alsa.h
+/// Definitions for use by ALSA drivers.
+///
+/// \copyright Copyright (C) 2013-2014 Algoram. See the LICENSE file.
+///
+
+#include <alsa/asoundlib.h>
+
+namespace FreeDV {
+  snd_pcm_t *
+  ALSASetup(
+   const char *                name,
+   snd_pcm_stream_t    stream,
+   int                 mode,
+   snd_pcm_format_t    format,
+   snd_pcm_access_t    access,
+   unsigned int        channels,
+   unsigned int        rate,
+   snd_pcm_uframes_t   period_size,
+   snd_pcm_uframes_t   buffer_size);
+}
index 073436ef5dad849f334271a454bc7f2b1bde502c..1ff4e0f57f2f5dc4d7e301feb68ecdcfc7496065 100644 (file)
 #include <fcntl.h>
 #include <sstream>
 
-// Remove extra spaces from string, in place.
-char *
-clean_string(char * string)
-{
-  char * s = string;
-
-  while ( *s != 0 ) {
-    if ( *s == ' ' && s[1] == ' ' ) {
+namespace FreeDV {
+  // Remove extra spaces from string, in place.
+  char *
+  clean_string(char * string)
+  {
+    char * s = string;
+  
+    while ( *s != 0 ) {
+      if ( *s == ' ' && s[1] == ' ' ) {
+        s++;
+        char * end = s;
+        while ( *end == ' ' )
+          end++;
+        memmove(s, end, strlen(end) + 1);
+      }
       s++;
-      char * end = s;
-      while ( *end == ' ' )
-        end++;
-      memmove(s, end, strlen(end) + 1);
     }
-    s++;
+  
+    const std::size_t length = strlen(string);
+  
+    if ( length > 1 && string[length - 1] == ' ' )
+      string[length - 1] = '\0';
+  
+    return string;
   }
-
-  const std::size_t length = strlen(string);
-
-  if ( length > 1 && string[length - 1] == ' ' )
-    string[length - 1] = '\0';
-
-  return string;
-}
-
-void
-EvDev::delete_enumeration(
- EvDev::device_enumeration *   data,
- std::size_t                   count)
-{
-  for ( std::size_t i = 0; i < count; i++ ) {
-    delete data[i].special_file;
-    delete data[i].name;
+  
+  void
+  EvDev::delete_enumeration(
+   EvDev::device_enumeration * data,
+   std::size_t                 count)
+  {
+    for ( std::size_t i = 0; i < count; i++ ) {
+      if ( data[i].special_file )
+        delete data[i].special_file;
+      if ( data[i].name )
+        delete data[i].name;
+    }
+    delete data;
   }
-  delete data;
-}
-
-struct EvDev::device_enumeration *
-EvDev::enumerate(std::size_t & count)
-{
-  struct device_enumeration    devices[100];
-
-  count = 0;
-
-  for ( int i = 0; sizeof(devices) / sizeof(*devices); i++ ) {
+  
+  struct EvDev::device_enumeration *
+  EvDev::enumerate(std::size_t & count)
+  {
+    struct device_enumeration  devices[100];
+  
+    count = 0;
+  
+    for ( std::size_t i = 0; i < (sizeof(devices) / sizeof(*devices)); i++ ) {
+      std::ostringstream       str;
+  
+      str << "/dev/input/event" << i;
+  
+      const char * const special_file = str.str().c_str();
+  
+      const int fd = open(special_file, O_RDONLY);
+  
+      if ( fd >= 0 ) {
+        if ( enumerate_device(special_file, fd, devices[count]) )
+          count++;
+        close(fd);
+      }
+    }
+    device_enumeration * const r = new device_enumeration[count];
+    
+    memcpy(r, devices, count * sizeof(*r));
+  
+    return r;
+  }
+  
+  bool
+  EvDev::enumerate_device(
+   const char *                special_file,
+   int                 fd,
+   device_enumeration &        device)
+  {
+    char                       buf[100];
     std::ostringstream str;
-
-    str << "/dev/input/event" << i;
-
-    const char * const special_file = str.str().c_str();
-
-    const int fd = open(special_file, O_RDONLY);
-
-    if ( fd >= 0 ) {
-      if ( enumerate_device(special_file, fd, devices[count]) )
-        count++;
-      close(fd);
+  
+    device.special_file = strdup(special_file);
+  
+    if ( ioctl(fd, EVIOCGNAME(sizeof(buf)), buf) < 0
+    ||   ioctl(fd, EVIOCGBIT(0, sizeof(device.event_types)), device.event_types)
+     < 0 )
+      return false;
+  
+    str << clean_string(buf);
+  
+    if ( ioctl(fd, EVIOCGUNIQ(sizeof(buf)), buf) >= 0
+    && buf[0] != '\0'
+    && buf[0] != ' ' )
+      str << ' ' << clean_string(buf);
+  
+    if ( ioctl(fd, EVIOCGPHYS(sizeof(buf)), buf) >= 0 )
+      str << " at " << clean_string(buf);
+  
+    device.name = strdup(str.str().c_str());
+  
+    return true;
+  }
+  
+  char * *
+  EvDev::EnumerateButtonDevices()
+  {
+    std::size_t                        count = 0;
+    std::size_t                        length = 0;
+    device_enumeration * const devices = enumerate(count);
+  
+    for ( std::size_t i = 0; i < count; i++ ) {
+      if ( test_bit(EV_KEY, devices[i].event_types) )
+        length++;
     }
+  
+    char * * names = new char * [length + 1];
+  
+    std::size_t        j = 0;
+    for ( std::size_t i = 0; i < count; i++ ) {
+      if ( test_bit(EV_KEY, devices[i].event_types) )
+        names[j++] = devices[i].name;
+        devices[i].name = 0;
+    }
+    names[j] = 0;
+  
+    delete_enumeration(devices, count);
+    return names;
   }
-  device_enumeration * const r = new device_enumeration[count];
   
-  memcpy(r, devices, count * sizeof(*r));
-
-  return r;
-}
-
-bool
-EvDev::enumerate_device(
- const char *          special_file,
- int                   fd,
- device_enumeration &  device)
-{
-  char                 buf[100];
-  std::ostringstream   str;
-
-  device.special_file = strdup(special_file);
-
-  if ( ioctl(fd, EVIOCGNAME(sizeof(buf)), buf) < 0
-  ||   ioctl(fd, EVIOCGBIT(0, sizeof(device.event_types)), device.event_types)
-   < 0 )
-    return false;
-
-  str << clean_string(buf);
-
-  if ( ioctl(fd, EVIOCGUNIQ(sizeof(buf)), buf) >= 0 )
-    str << ' ' << clean_string(buf);
-
-  if ( ioctl(fd, EVIOCGPHYS(sizeof(buf)), buf) >= 0 )
-    str << " at " << clean_string(buf);
-
-  device.name = strdup(str.str().c_str());
-
-  return true;
-}
-
-const char * const *
-EvDev::EnumerateButtonDevices()
-{
-  std::size_t                  count = 0;
-  std::size_t                  length = 0;
-  device_enumeration * const   devices = enumerate(count);
-
-  for ( std::size_t i = 0; i < count; i++ ) {
-    if ( test_bit(EV_KEY, devices[i].event_types) )
-      length++;
+  EvDev::EvDev(const char *)
+  {
+  }
+  
+  EvDev::~EvDev()
+  {
   }
-
-  delete_enumeration(devices, count);
-  return 0;
-}
-
-EvDev::EvDev(const char *)
-{
-}
-
-EvDev::~EvDev()
-{
 }
index e4491ef7e80e581537f41b5396f0e5dc7df02b13..ade529d672bf96799419754f701726f7b7f48112 100644 (file)
@@ -8,36 +8,37 @@
 #define LONG(x) ((x)/BITS_PER_LONG)
 #define test_bit(bit, array)   ((array[LONG(bit)] >> OFF(bit)) & 1)
 
-class EvDev {
-protected:
-  struct device_enumeration {
-    const char *       special_file;
-    const char *       name;
-    uint8_t            event_types[(EV_MAX + 7) / 8];
+namespace FreeDV {
+  class EvDev {
+  protected:
+    struct device_enumeration {
+      char *   special_file;
+      char *   name;
+      uint8_t  event_types[(EV_MAX + 7) / 8];
+    };
+  
+  private:
+  
+                       EvDev(const EvDev &);
+    EvDev &            operator =(const EvDev &);
+  
+    static bool                enumerate_device(
+                        const char *                   name,
+                        int                            fd,
+                        struct device_enumeration &    device);
+  
+  protected:
+    static void                delete_enumeration(
+                        device_enumeration *   data,
+                        std::size_t            count);
+  
+    static device_enumeration *
+                       enumerate(std::size_t & count);
+  
+  public:
+    static char * *    EnumerateButtonDevices();
+  
+                       EvDev(const char * name);
+                       ~EvDev();
   };
-
-private:
-
-                       EvDev(const EvDev &);
-  EvDev &              operator =(const EvDev &);
-
-  static bool          enumerate_device(
-                        const char *                   name,
-                        int                            fd,
-                        struct device_enumeration &    device);
-
-protected:
-  static void          delete_enumeration(
-                        device_enumeration *   data,
-                        std::size_t            count);
-
-  static device_enumeration *
-                       enumerate(std::size_t & count);
-
-public:
-  static const char * const *
-                       EnumerateButtonDevices();
-
-                       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
new file mode 100644 (file)
index 0000000..ee0770b
--- /dev/null
@@ -0,0 +1,107 @@
+/// \file ptt_evdev.cpp
+/// Implementation of the evdev PTT driver.
+///
+/// \copyright Copyright (C) 2013-2014 Algoram. See the LICENSE file.
+///
+
+#include "evdev.h"
+#include "drivers.h"
+#include <iostream>
+#include <stdexcept>
+
+namespace FreeDV {
+  /// PTT driver using Linux evdev.
+  ///
+  class PTT_EvDev : public PTTInput {
+  private:
+    /// This is true if ready has not yet been sent.
+    ///
+    bool               pressed;
+    bool               ready_one_shot;
+  public:
+    /// Instantiate.
+    ///
+                       PTT_EvDev(const char * parameters);
+    virtual            ~PTT_EvDev();
+    
+    /// Return file descriptors for poll()
+    /// \param array The address of an array that will be written
+    /// with a sequence of file descriptors.
+    /// \param space The maximum number of file descriptors that may be
+    /// stored in the array.
+    /// \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.
+    ///
+    std::size_t        ready();
+
+    /// Return true if the PTT input is pressed.
+    ///
+    bool       state();
+  };
+
+  PTT_EvDev::PTT_EvDev(const char * _parameters)
+  : PTTInput("constant", _parameters), pressed(false), ready_one_shot(true)
+  {
+  }
+
+  PTT_EvDev::~PTT_EvDev()
+  {
+  }
+
+  int
+  PTT_EvDev::poll_fds(PollType *, int)
+  {
+    return 0;
+  }
+
+  std::size_t
+  PTT_EvDev::ready()
+  {
+    if ( ready_one_shot )
+      return 1;
+    else
+      return 0;
+  }
+
+  bool
+  PTT_EvDev::state()
+  {
+    return false;
+  }
+
+  PTTInput *
+  Driver::PTT_EvDev(const char * parameter)
+  {
+    return new ::FreeDV::PTT_EvDev(parameter);
+  }
+
+  static std::ostream &
+  PTT_EvDevEnumerator(std::ostream & stream)
+  {
+    char * *   devices = EvDev::EnumerateButtonDevices();
+
+    char * *   d = devices;
+
+    while ( *d != 0 )
+      stream << "\"evdev:" << *d++ << '\"' << std::endl;
+
+    d = devices;
+
+    while ( *d != 0 )
+      delete *d++;
+
+    delete devices;
+
+    return stream;
+  }
+
+  static bool
+  initializer()
+  {
+    driver_manager()->register_ptt_input("evdev", Driver::PTT_EvDev, PTT_EvDevEnumerator);
+    return true;
+  }
+  static const bool UNUSED initialized = initializer();
+}