[vdr-plugin-pvrinput] 01/04: Imported Upstream version 2014-01-11+git20150213

Tobias Grimm tiber-guest at moszumanska.debian.org
Fri Feb 13 22:51:34 UTC 2015


This is an automated email from the git hooks/post-receive script.

tiber-guest pushed a commit to branch master
in repository vdr-plugin-pvrinput.

commit a044c87646ecb5c93c4e073fd1268d7148c67ad3
Author: etobi <git at e-tobi.net>
Date:   Fri Feb 13 22:03:28 2015 +0100

    Imported Upstream version 2014-01-11+git20150213
---
 Makefile   |   7 +-
 device.c   | 179 ++++++++++++++++++++++++++++------------------
 device.h   |   7 +-
 pvrinput.c |   2 +-
 udev.c     | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 udev.h     |  56 +++++++++++++++
 6 files changed, 411 insertions(+), 76 deletions(-)

diff --git a/Makefile b/Makefile
index 67f09e9..fd4b7e0 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ pri
 ### The directory environment:
 
 # Use package data if installed...otherwise assume we're under the VDR source directory:
-PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
+PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." pkg-config --variable=$(1) vdr))
 LIBDIR = $(call PKGCFG,libdir)
 LOCDIR = $(call PKGCFG,locdir)
 PLGCFG = $(call PKGCFG,plgcfg)
@@ -27,6 +27,7 @@ TMPDIR ?= /tmp
 
 export CFLAGS   = $(call PKGCFG,cflags)
 export CXXFLAGS = $(call PKGCFG,cxxflags)
+export LDADD    = $(shell pkg-config --libs libudev)
 
 ### The version number of VDR's plugin API:
 
@@ -53,7 +54,7 @@ DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
 
 ### The object files (add further files here):
 
-OBJS = $(PLUGIN).o common.o device.o reader.o menu.o setup.o filter.o sourceparams.o submenu.o
+OBJS = $(PLUGIN).o common.o device.o reader.o menu.o setup.o filter.o sourceparams.o submenu.o udev.o
 
 ### The main target:
 
@@ -102,7 +103,7 @@ install-i18n: $(I18Nmsgs)
 ### Targets:
 
 $(SOFILE): $(OBJS)
-	$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
+	$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LDADD) -o $@
 
 install-lib: $(SOFILE)
 	install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
diff --git a/device.c b/device.c
index b90266c..1a57289 100644
--- a/device.c
+++ b/device.c
@@ -1,4 +1,5 @@
 #include "common.h"
+#include "udev.h"
 #include <linux/dvb/video.h>
 
 char DRIVERNAME[][15] = {
@@ -33,7 +34,6 @@ cPvrDevice::cPvrDevice(int DeviceNumber, cDevice *ParentDevice)
   isClosing(false),
   readThreadRunning(false),
   ChannelSettingsDone(false),
-  FirstChannelSwitch(true),
   pvrusb2_ready(true),
   driver(undef),
   cardname(UNDEF),
@@ -42,7 +42,7 @@ cPvrDevice::cPvrDevice(int DeviceNumber, cDevice *ParentDevice)
 {
   log(pvrDEBUG2, "new cPvrDevice (%d)", number);
   v4l2_fd = mpeg_fd = radio_fd = -1;
-  v4l2_dev = mpeg_dev = radio_dev = -1;
+  v4l2_dev = mpeg_dev = -1;
   vpid = apid = tpid = -1;
   cString devName;
   struct v4l2_capability video_vcap;
@@ -90,44 +90,59 @@ cPvrDevice::cPvrDevice(int DeviceNumber, cDevice *ParentDevice)
     VBIDeviceCount++;
     log(pvrDEBUG1, "%s supports sliced VBI Capture, total number of VBI capable devices is now %d", *devName, VBIDeviceCount);
     }
+  bool supports_radio = false;
+  if (video_vcap.capabilities & V4L2_CAP_RADIO)
+     supports_radio = true;
+
+  pvrinput::cUdev::Init();
+  pvrinput::cUdevDevice *v4ldev = pvrinput::cUdev::GetDeviceFromDevName(*devName);
+  if (v4ldev != NULL) {
+     static const char *propertyName = "ID_PATH";
+     static const char *vbi_dev_node = "/dev/vbi";
+     static const char *radio_dev_node = "/dev/radio";
+     const char *id_path = v4ldev->GetPropertyValue(propertyName);
+     if (id_path != NULL) {
+        cList<pvrinput::cUdevDevice> *v4ldevices = pvrinput::cUdev::EnumDevices("video4linux", propertyName, id_path);
+        for (pvrinput::cUdevDevice *dev = v4ldevices->First(); dev; dev = v4ldevices->Next(dev)) {
+            log(pvrDEBUG1, "pvrinput: %s is related to %s", *devName, dev->GetDevnode());
+            if (SupportsSlicedVBI && (*vbi_devname == NULL) && (strncmp(dev->GetDevnode(), vbi_dev_node, strlen(vbi_dev_node)) == 0))
+               vbi_devname = dev->GetDevnode();
+            else if (supports_radio && (*radio_devname == NULL) && (strncmp(dev->GetDevnode(), radio_dev_node, strlen(radio_dev_node)) == 0))
+               radio_devname = dev->GetDevnode();
+            }
+        delete v4ldevices;
+        }
+     delete v4ldev;
+     }
+  pvrinput::cUdev::Free();
+
   if (video_vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
      hasDecoder = true; //can only be a PVR350
-  for (i = 0; i < kMaxPvrDevices; i++) {
-    if (radio_dev<0 && (video_vcap.capabilities & V4L2_CAP_RADIO)) { //searching matching radio dev
-      devName = cString::sprintf("/dev/radio%d", i);
-      radio_fd = open(devName, O_RDWR);
-      if (radio_fd >= 0) {
-        memset(&capability, 0, sizeof(capability));
-        if (IOCTL(radio_fd, VIDIOC_QUERYCAP, &capability) != 0)
-           log(pvrERROR, "VIDIOC_QUERYCAP failed, %d:%s", errno, strerror(errno));
-        if (!strncmp(*BusID, (const char*)capability.bus_info, strlen(*BusID) - 1)) {
-          radio_dev = i; // store info for later
-          log(pvrDEBUG1, "/dev/radio%d = FM radio dev",radio_dev);
-          }
-        close(radio_fd); // a pvrusb2 will remain on input 3. The bool FirstChannelSwitch will solve this later
-        radio_fd = -1;
-      }
+
+  if (driver == cx88_blackbird) {
+     for (i = 0; i < kMaxPvrDevices; i++) {
+       if (mpeg_dev < 0) { // the blackbird uses two (!) different devices, search the other one.
+         close(v4l2_fd);
+         v4l2_fd = -1;
+         devName = cString::sprintf("/dev/video%d", i);
+         mpeg_fd = open(devName, O_RDWR);
+         if (mpeg_fd > 0) {
+           memset(&capability, 0, sizeof(capability));
+           IOCTL(mpeg_fd, VIDIOC_QUERYCAP, &capability);
+           if (!strncmp(*BusID, (const char*)capability.bus_info, strlen(*BusID) - 1)
+              && !strcmp("cx8800", (const char*)capability.driver)) {
+             mpeg_dev = v4l2_dev; //for this driver we found mpeg_dev up to now.
+             v4l2_dev = i;        //reassigning, now with correct value.
+             log(pvrDEBUG1, "/dev/video%d = v4l2 dev (analog properties: volume/hue/brightness/inputs..)", v4l2_dev);
+             log(pvrDEBUG1, "/dev/video%d = mpeg dev (MPEG properties: bitrates/frame rate/filters..)", mpeg_dev);
+             }
+           close(mpeg_fd);
+           mpeg_fd = -1;
+           }
+         }
+       } // end device search loop
     }
-    if (mpeg_dev < 0 && (driver == cx88_blackbird)) { // the blackbird uses two (!) different devices, search the other one.
-      close(v4l2_fd);
-      v4l2_fd = -1;
-      devName = cString::sprintf("/dev/video%d", i);
-      mpeg_fd = open(devName, O_RDWR);
-      if (mpeg_fd) {
-        memset(&capability, 0, sizeof(capability));
-        IOCTL(mpeg_fd, VIDIOC_QUERYCAP, &capability);
-        if (!strncmp(*BusID, (const char*)capability.bus_info, strlen(*BusID) - 1)
-           && !strcmp("cx8800", (const char*)capability.driver)) {
-          mpeg_dev = v4l2_dev; //for this driver we found mpeg_dev up to now.
-          v4l2_dev = i;        //reassigning, now with correct value.
-          log(pvrDEBUG1, "/dev/video%d = v4l2 dev (analog properties: volume/hue/brightness/inputs..)", v4l2_dev);
-          log(pvrDEBUG1, "/dev/video%d = mpeg dev (MPEG properties: bitrates/frame rate/filters..)", mpeg_dev);
-          }
-        close(mpeg_fd);
-        mpeg_fd = -1;
-        }
-      }
-    } // end device search loop
+
   switch (driver) {
     case ivtv:        //ivtv, cx18, pvrusb2 and hdpvr share the same device.
     case cx18:
@@ -486,7 +501,7 @@ bool cPvrDevice::Tune(int freq)
 
 bool cPvrDevice::SetInput(int input)
 {
-  if (input == CurrentInput && !FirstChannelSwitch)
+  if (input == CurrentInput)
      return true;
   log(pvrDEBUG1, "cPvrDevice::SetInput on /dev/video%d (%s) to %d", number, CARDNAME[cardname], input);
   if (IOCTL(v4l2_fd, VIDIOC_S_INPUT, &input) != 0) {
@@ -662,37 +677,48 @@ void cPvrDevice::SetEncoderState(eEncState state)
 
 bool cPvrDevice::SetVBImode(int vbiLinesPerFrame, int vbistatus)
 {
-  if (v4l2_fd >= 0 && SupportsSlicedVBI) {
-    log(pvrDEBUG1, "SetVBImode(%d, %d) on /dev/video%d (%s)", vbiLinesPerFrame, vbistatus, number, CARDNAME[cardname]);
-    struct v4l2_format vbifmt;
-    struct v4l2_ext_controls ctrls;
-    struct v4l2_ext_control  ctrl;
-    memset(&vbifmt, 0, sizeof(vbifmt));
-    memset(&ctrls,  0, sizeof(ctrls));
-    memset(&ctrl,   0, sizeof(ctrl));
-    ctrl.id    = V4L2_CID_MPEG_STREAM_VBI_FMT;
-    ctrl.value = vbistatus; 
-    ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
-    ctrls.controls = &ctrl;
-    ctrls.count = 1;
-    if (IOCTL(v4l2_fd, VIDIOC_S_EXT_CTRLS, &ctrls) != 0) {
-      log(pvrERROR, "cPvrDevice::SetVBImode(): error setting vbi mode (ctrls) on /dev/video%d (%s), %d:%s",
-          number, CARDNAME[cardname], errno, strerror(errno));
-      return false; 
-      }
-    if ((ctrl.value == V4L2_MPEG_STREAM_VBI_FMT_IVTV) && (vbiLinesPerFrame == 625)) {
+  if (*vbi_devname && SupportsSlicedVBI) {
+     log(pvrDEBUG1, "SetVBImode(%d, %d) on %s (%s)", vbiLinesPerFrame, vbistatus, *vbi_devname, CARDNAME[cardname]);
+
+     int vbi_fd = open(*vbi_devname, O_RDWR);
+     if (vbi_fd < 0) {
+        log(pvrERROR, "cPvrDevice::SetVBImode(): error opening %s (%s), %d:%s",
+            *vbi_devname, CARDNAME[cardname], errno, strerror(errno));
+        return false;
+        }
+
+     struct v4l2_format vbifmt;
+     struct v4l2_ext_controls ctrls;
+     struct v4l2_ext_control  ctrl;
+     memset(&vbifmt, 0, sizeof(vbifmt));
+     memset(&ctrls,  0, sizeof(ctrls));
+     memset(&ctrl,   0, sizeof(ctrl));
+     ctrl.id    = V4L2_CID_MPEG_STREAM_VBI_FMT;
+     ctrl.value = vbistatus; 
+     ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
+     ctrls.controls = &ctrl;
+     ctrls.count = 1;
+     if (IOCTL(vbi_fd, VIDIOC_S_EXT_CTRLS, &ctrls) != 0) {
+        log(pvrERROR, "cPvrDevice::SetVBImode(): error setting vbi mode (ctrls) on %s (%s), %d:%s",
+            *vbi_devname, CARDNAME[cardname], errno, strerror(errno));
+        close(vbi_fd);
+        return false; 
+        }
+     if ((ctrl.value == V4L2_MPEG_STREAM_VBI_FMT_IVTV) && (vbiLinesPerFrame == 625)) {
         vbifmt.fmt.sliced.service_set = V4L2_SLICED_VBI_625;
         vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
         vbifmt.fmt.sliced.reserved[0] = 0;
         vbifmt.fmt.sliced.reserved[1] = 0;
 
-        if (IOCTL(v4l2_fd, VIDIOC_S_FMT, &vbifmt) < 0) {
-          log(pvrERROR, "cPvrDevice::SetVBImode():error setting vbi mode (fmt) on /dev/video%d (%s), %d:%s",
-              number, CARDNAME[cardname], errno, strerror(errno));
-          return false;
-          }
+        if (IOCTL(vbi_fd, VIDIOC_S_FMT, &vbifmt) < 0) {
+           log(pvrERROR, "cPvrDevice::SetVBImode():error setting vbi mode (fmt) on %s (%s), %d:%s",
+               *vbi_devname, CARDNAME[cardname], errno, strerror(errno));
+           close(vbi_fd);
+           return false;
+           }
         }
-    }
+     close(vbi_fd);
+     }
   return true;
 }
 
@@ -749,7 +775,7 @@ bool cPvrDevice::SetChannelDevice(const cChannel * Channel, bool LiveView)
   if (!ParseChannel(Channel, &input, &norm, &LinesPerFrame, &card, &inputType, &apid, &vpid, &tpid))
      return false;
 
-  if ((Channel->Number() == CurrentChannel.Number()) && (Channel->Frequency() == CurrentFrequency) && (input == CurrentInput) && (norm == CurrentNorm))
+  if ((Channel->GetChannelID() == CurrentChannel.GetChannelID()) && (Channel->Frequency() == CurrentFrequency) && (input == CurrentInput) && (norm == CurrentNorm))
     return true;
   log(pvrDEBUG1, "cPvrDevice::SetChannelDevice prepare switch to %d (%s) %3.2fMHz (/dev/video%d = %s)",
     Channel->Number(), Channel->Name(), (double)Channel->Frequency() / 1000,  number, CARDNAME[cardname]);
@@ -854,13 +880,12 @@ bool cPvrDevice::OpenDvr(void)
                  case ivtv:
                  case cx18:
                  case pvrusb2:
-                   if (radio_dev < 0)
+                   if (*radio_devname == NULL)
                       return false; //no hardware support.
                    if (radio_fd < 0) {
-                     cString devName = cString::sprintf("/dev/radio%d", radio_dev);
-                     radio_fd = open(devName, O_RDONLY);
+                     radio_fd = open(*radio_devname, O_RDONLY);
                      if (radio_fd < 0) {
-                       log(pvrERROR, "Error opening FM radio device %s: %s", *devName, strerror(errno));
+                       log(pvrERROR, "Error opening FM radio device %s: %s", *radio_devname, strerror(errno));
                        return false;
                        }
                      if (driver == pvrusb2)
@@ -900,7 +925,6 @@ bool cPvrDevice::OpenDvr(void)
          } //end: switch (newInputType)
        CurrentInputType = newInputType;
        ChannelSettingsDone = true;
-       FirstChannelSwitch = false;
        } //end: if ((!ChannelSettingsDone)
      if (CurrentInputType == eTelevision)
         SetVBImode(newLinesPerFrame, PvrSetup.SliceVBI ? V4L2_MPEG_STREAM_VBI_FMT_IVTV : V4L2_MPEG_STREAM_VBI_FMT_NONE);
@@ -1021,6 +1045,21 @@ int cPvrDevice::SignalQuality(void) const
   return -1;
 }
 
+const cChannel *cPvrDevice::GetCurrentlyTunedTransponder(void) const
+{
+  return &CurrentChannel;
+}
+
+bool cPvrDevice::IsTunedToTransponder(const cChannel *Channel) const
+{
+  return CurrentChannel.GetChannelID() == Channel->GetChannelID();
+}
+
+bool cPvrDevice::MaySwitchTransponder(const cChannel *Channel) const
+{
+  return CurrentChannel.GetChannelID() == Channel->GetChannelID();
+}
+
 bool cPvrDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
 {
   bool result = false;
@@ -1071,7 +1110,7 @@ bool cPvrDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
            }
     }
   if (inputType == eRadio) {
-    if (radio_dev < 0) {
+    if (*radio_devname == NULL) {
       log(pvrDEBUG1, "cPvrDevice::ProvidesChannel: /dev/video%d (%s) has no radio", number, CARDNAME[cardname]);
       return false;
       }
diff --git a/device.h b/device.h
index f2f720a..fecfade 100644
--- a/device.h
+++ b/device.h
@@ -73,7 +73,7 @@ private:
   int radio_fd;
   int v4l2_dev;
   int mpeg_dev;
-  int radio_dev;
+  cString radio_devname;
   int inputs[12];
   int numInputs;
   int vpid;
@@ -97,6 +97,7 @@ private:
   eEncState EncoderState;
   int driver_apiversion;
   bool SupportsSlicedVBI;
+  cString vbi_devname;
   bool hasDecoder;
   bool hasTuner;
   int  streamType;
@@ -105,7 +106,6 @@ private:
   bool isClosing;
   bool readThreadRunning;
   bool ChannelSettingsDone;
-  bool FirstChannelSwitch;
   bool pvrusb2_ready;
   eV4l2Driver driver;
   eV4l2CardName cardname;
@@ -135,6 +135,9 @@ public:
   virtual int NumProvidedSystems(void) const;
   virtual int SignalStrength(void) const;
   virtual int SignalQuality(void) const;
+  virtual const cChannel *GetCurrentlyTunedTransponder(void) const;
+  virtual bool IsTunedToTransponder(const cChannel *Channel) const;
+  virtual bool MaySwitchTransponder(const cChannel *Channel) const;
   bool ParseChannel(const cChannel *Channel, int *input, uint64_t *norm, int *LinesPerFrame, int *card,
                     eInputType *inputType, int *apid, int *vpid, int *tpid) const;
   int  ReOpen(void);
diff --git a/pvrinput.c b/pvrinput.c
index 4e74d55..b001c85 100644
--- a/pvrinput.c
+++ b/pvrinput.c
@@ -6,7 +6,7 @@
 #endif
 #endif
 
-static const char *VERSION        = "2013-01-23";
+static const char *VERSION        = "2014-01-11";
 static const char *DESCRIPTION    = tr("use Hauppauge PVR as input device");
 static const char *MAINMENUENTRY  = tr("PVR picture settings");
 
diff --git a/udev.c b/udev.c
new file mode 100644
index 0000000..dbd14fc
--- /dev/null
+++ b/udev.c
@@ -0,0 +1,236 @@
+#include "udev.h"
+#include <linux/stddef.h>
+
+// --- cUdevListEntry --------------------------------------------------------
+
+pvrinput::cUdevListEntry::cUdevListEntry(struct udev_list_entry *ListEntry)
+:listEntry(ListEntry)
+{
+}
+
+pvrinput::cUdevListEntry::~cUdevListEntry(void)
+{
+}
+
+pvrinput::cUdevListEntry *pvrinput::cUdevListEntry::GetNext(void) const
+{
+  if (listEntry == NULL)
+     return NULL;
+  struct udev_list_entry *next = udev_list_entry_get_next(listEntry);
+  if (next == NULL)
+     return NULL;
+  return new cUdevListEntry(next);
+}
+
+const char *pvrinput::cUdevListEntry::GetName(void) const
+{
+ if (listEntry == NULL)
+     return NULL;
+  return udev_list_entry_get_name(listEntry);
+}
+
+const char *pvrinput::cUdevListEntry::GetValue(void) const
+{
+ if (listEntry == NULL)
+     return NULL;
+  return udev_list_entry_get_value(listEntry);
+}
+
+// --- cUdevDevice -----------------------------------------------------------
+
+pvrinput::cUdevDevice::cUdevDevice(udev_device *Device, bool DoUnref)
+:device(Device)
+,doUnref(DoUnref)
+{
+}
+
+pvrinput::cUdevDevice::~cUdevDevice(void)
+{
+  if (doUnref && device)
+     udev_device_unref(device);
+}
+
+int pvrinput::cUdevDevice::Compare(const cListObject &ListObject) const
+{
+  const char *n1 = GetDevnode();
+  const char *n2 = ((cUdevDevice*)&ListObject)->GetDevnode();
+  if ((n1 != NULL) && (n2 != NULL))
+     return strcmp(n1, n2);
+  return 0;
+}
+
+const char  *pvrinput::cUdevDevice::GetAction(void) const
+{
+  if (device == NULL)
+     return NULL;
+  return udev_device_get_action(device);
+}
+
+pvrinput::cUdevListEntry *pvrinput::cUdevDevice::GetDevlinksList(void) const
+{
+  if (device == NULL)
+     return NULL;
+  struct udev_list_entry *listEntry = udev_device_get_devlinks_list_entry(device);
+  if (listEntry == NULL)
+     return NULL;
+  return new cUdevListEntry(listEntry);
+}
+
+const char  *pvrinput::cUdevDevice::GetDevnode(void) const
+{
+  if (device == NULL)
+     return false;
+  return udev_device_get_devnode(device);
+}
+
+const char  *pvrinput::cUdevDevice::GetDevpath(void) const
+{
+  if (device == NULL)
+     return false;
+  return udev_device_get_devpath(device);
+}
+
+pvrinput::cUdevDevice *pvrinput::cUdevDevice::GetParent(void) const
+{
+  if (device == NULL)
+     return NULL;
+  struct udev_device *parent = udev_device_get_parent(device);
+  if (parent == NULL)
+     return NULL;
+  return new cUdevDevice(parent, false);
+}
+
+const char *pvrinput::cUdevDevice::GetPropertyValue(const char *Key) const
+{
+  if (device == NULL)
+     return false;
+  return udev_device_get_property_value(device, Key);
+}
+
+const char *pvrinput::cUdevDevice::GetSubsystem(void) const
+{
+  if (device == NULL)
+     return false;
+  return udev_device_get_subsystem(device);
+}
+
+const char *pvrinput::cUdevDevice::GetSysname(void) const
+{
+  if (device == NULL)
+     return false;
+  return udev_device_get_sysname(device);
+}
+
+const char *pvrinput::cUdevDevice::GetSyspath(void) const
+{
+  if (device == NULL)
+     return false;
+  return udev_device_get_syspath(device);
+}
+
+// --- cUdev -----------------------------------------------------------------
+
+cMutex pvrinput::cUdev::udev_mutex;
+int    pvrinput::cUdev::udev_refcount = 0;
+struct udev  *pvrinput::cUdev::udev = NULL;
+
+struct udev *pvrinput::cUdev::Init(void)
+{
+  udev_mutex.Lock();
+  if (udev == NULL)
+     udev = udev_new();
+  else
+     udev_ref(udev);
+  udev_refcount++;
+  udev_mutex.Unlock();
+  return udev;
+}
+
+void pvrinput::cUdev::Free(void)
+{
+  udev_mutex.Lock();
+  if (udev_refcount <= 0)
+     esyslog("udev: don't call cUdev::Free before cUdev::Init!");
+  else {
+     udev_refcount--;
+     udev_unref(udev);
+     if (udev_refcount <= 0)
+        udev = NULL;
+     }
+  udev_mutex.Unlock();
+}
+
+pvrinput::cUdevDevice *pvrinput::cUdev::GetDeviceFromDevName(const char *DevName)
+{
+  if (DevName == NULL)
+     return NULL;
+  struct stat statbuf;
+  if (stat(DevName, &statbuf) < 0)
+     return NULL;
+  char type;
+  if (S_ISBLK(statbuf.st_mode))
+     type = 'b';
+  else if (S_ISCHR(statbuf.st_mode))
+     type = 'c';
+  else
+     return NULL;
+  udev_device *dev = udev_device_new_from_devnum(udev, type, statbuf.st_rdev);
+  if (dev == NULL)
+     return NULL;
+  return new cUdevDevice(dev);
+}
+
+pvrinput::cUdevDevice *pvrinput::cUdev::GetDeviceFromSysPath(const char *SysPath)
+{
+  if (SysPath == NULL)
+     return NULL;
+  udev_device *dev = udev_device_new_from_syspath(udev, SysPath);
+  if (dev == NULL)
+     return NULL;
+  return new cUdevDevice(dev);
+}
+
+cList<pvrinput::cUdevDevice> *pvrinput::cUdev::EnumDevices(const char *Subsystem, const char *Property, const char *Value)
+{
+  cList<cUdevDevice> *devices = new cList<cUdevDevice>;
+  struct udev_enumerate *e = udev_enumerate_new(udev);
+  struct udev_list_entry *l;
+  cUdevListEntry *listEntry;
+  const char *path;
+  cUdevDevice *dev;
+  if (e != NULL) {
+     int rc = 0;
+     if (Subsystem && ((rc = udev_enumerate_add_match_subsystem(e, Subsystem)) < 0)) {
+        esyslog("udev: can't add subsystem %s to enum-filter: %d", Subsystem, rc);
+        goto unref;
+        }
+     if (Property && Value && ((rc = udev_enumerate_add_match_property(e, Property, Value)) < 0)) {
+        esyslog("udev: can't add property %s value %s to enum-filter: %d", Property, Value, rc);
+        goto unref;
+        }
+     if ((rc = udev_enumerate_scan_devices(e)) < 0) {
+        esyslog("udev: can't scan for devices: %d", rc);
+        goto unref;
+        }
+     l = udev_enumerate_get_list_entry(e);
+     if (l == NULL) {
+        isyslog("udev: no devices found for %s/%s=%s", Subsystem, Property, Value);
+        goto unref;
+        }
+     listEntry = new cUdevListEntry(l);
+     while (listEntry) {
+        path = listEntry->GetName();
+        if (path != NULL) {
+           dev = GetDeviceFromSysPath(path);
+           if (dev != NULL)
+              devices->Add(dev);
+           }
+        cUdevListEntry *tmp = listEntry->GetNext();
+        delete listEntry;
+        listEntry = tmp;
+        }
+unref:
+     udev_enumerate_unref(e);
+     }
+  return devices;
+}
diff --git a/udev.h b/udev.h
new file mode 100644
index 0000000..9943541
--- /dev/null
+++ b/udev.h
@@ -0,0 +1,56 @@
+#ifndef __PVRINPUT_UDEV_H
+#define __PVRINPUT_UDEV_H
+
+#include <libudev.h>
+
+#include <vdr/tools.h>
+#include <vdr/thread.h>
+
+namespace pvrinput {
+  class cUdevListEntry {
+  private:
+    struct udev_list_entry *listEntry;
+  public:
+    cUdevListEntry(struct udev_list_entry *ListEntry);
+    virtual ~cUdevListEntry(void);
+    
+    cUdevListEntry *GetNext(void) const;
+    const char *GetName(void) const;
+    const char *GetValue(void) const;
+    };
+
+  class cUdevDevice : public cListObject {
+  private:
+    struct udev_device *device;
+    bool doUnref;
+  public:
+    cUdevDevice(udev_device *Device, bool DoUnref = true);
+    virtual ~cUdevDevice(void);
+    virtual int Compare(const cListObject &ListObject) const;
+
+    const char  *GetAction(void) const;
+    cUdevListEntry *GetDevlinksList(void) const;
+    const char  *GetDevnode(void) const;
+    const char  *GetDevpath(void) const;
+    cUdevDevice *GetParent(void) const;
+    const char  *GetPropertyValue(const char *Key) const;
+    const char  *GetSubsystem(void) const;
+    const char  *GetSysname(void) const;
+    const char  *GetSyspath(void) const;
+    };
+
+  class cUdev {
+  private:
+    static cMutex udev_mutex;
+    static int    udev_refcount; // newer libudev does this on its own
+    static struct udev *udev;
+  public:
+    static struct udev *Init(void);
+    static void Free(void);
+    static cUdevDevice *GetDeviceFromDevName(const char *DevName);
+    static cUdevDevice *GetDeviceFromSysPath(const char *SysPath);
+    static cList<cUdevDevice> *EnumDevices(const char *Subsystem, const char *Property, const char *Value);
+    };
+}
+
+#endif // __PVRINPUT_UDEV_H

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr-plugin-pvrinput.git



More information about the pkg-vdr-dvb-changes mailing list