summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--device.c81
-rw-r--r--device.h1
-rw-r--r--pvrinput.c2
-rw-r--r--udev.c222
-rw-r--r--udev.h51
6 files changed, 334 insertions, 28 deletions
diff --git a/Makefile b/Makefile
index aa94782..fd4b7e0 100644
--- a/Makefile
+++ b/Makefile
@@ -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 6b86c88..184fb2d 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] = {
@@ -89,6 +90,25 @@ cPvrDevice::cPvrDevice(int DeviceNumber, cDevice *ParentDevice)
SupportsSlicedVBI = true;
VBIDeviceCount++;
log(pvrDEBUG1, "%s supports sliced VBI Capture, total number of VBI capable devices is now %d", *devName, VBIDeviceCount);
+
+ cUdev::Init();
+ cUdevDevice *v4ldev = cUdev::GetDeviceFromDevName(*devName);
+ if (v4ldev != NULL) {
+ static const char *propertyName = "ID_PATH";
+ static const char *vbi_dev_name = "/dev/vbi";
+ const char *id_path = v4ldev->GetPropertyValue(propertyName);
+ if (id_path != NULL) {
+ cList<cUdevDevice> *v4ldevices = cUdev::EnumDevices("video4linux", propertyName, id_path);
+ for (cUdevDevice *dev = v4ldevices->First(); dev; dev = v4ldevices->Next(dev)) {
+ log(pvrDEBUG1, "pvrinput: %s is related to %s", *devName, dev->GetDevnode());
+ if (strncmp(dev->GetDevnode(), vbi_dev_name, strlen(vbi_dev_name)) == 0)
+ vbi_dev = dev->GetDevnode();
+ }
+ delete v4ldevices;
+ }
+ delete v4ldev;
+ }
+ cUdev::Free();
}
if (video_vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
hasDecoder = true; //can only be a PVR350
@@ -662,37 +682,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_dev && SupportsSlicedVBI) {
+ log(pvrDEBUG1, "SetVBImode(%d, %d) on %s (%s)", vbiLinesPerFrame, vbistatus, *vbi_dev, CARDNAME[cardname]);
+
+ int vbi_fd = open(*vbi_dev, O_RDWR);
+ if (vbi_fd < 0) {
+ log(pvrERROR, "cPvrDevice::SetVBImode(): error opening %s (%s), %d:%s",
+ *vbi_dev, 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_dev, 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_dev, CARDNAME[cardname], errno, strerror(errno));
+ close(vbi_fd);
+ return false;
+ }
}
- }
+ close(vbi_fd);
+ }
return true;
}
diff --git a/device.h b/device.h
index 3714ff2..e9b0861 100644
--- a/device.h
+++ b/device.h
@@ -97,6 +97,7 @@ private:
eEncState EncoderState;
int driver_apiversion;
bool SupportsSlicedVBI;
+ cString vbi_dev;
bool hasDecoder;
bool hasTuner;
int streamType;
diff --git a/pvrinput.c b/pvrinput.c
index 4e74d55..f41727e 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-07";
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..d78e39d
--- /dev/null
+++ b/udev.c
@@ -0,0 +1,222 @@
+#include "udev.h"
+#include <linux/stddef.h>
+
+// --- cUdevListEntry --------------------------------------------------------
+
+cUdevListEntry::cUdevListEntry(struct udev_list_entry *ListEntry)
+:listEntry(ListEntry)
+{
+}
+
+cUdevListEntry::~cUdevListEntry(void)
+{
+}
+
+cUdevListEntry *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 *cUdevListEntry::GetName(void) const
+{
+ if (listEntry == NULL)
+ return NULL;
+ return udev_list_entry_get_name(listEntry);
+}
+
+const char *cUdevListEntry::GetValue(void) const
+{
+ if (listEntry == NULL)
+ return NULL;
+ return udev_list_entry_get_value(listEntry);
+}
+
+// --- cUdevDevice -----------------------------------------------------------
+
+cUdevDevice::cUdevDevice(udev_device *Device, bool DoUnref)
+:device(Device)
+,doUnref(DoUnref)
+{
+}
+
+cUdevDevice::~cUdevDevice(void)
+{
+ if (doUnref && device)
+ udev_device_unref(device);
+}
+
+int 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 *cUdevDevice::GetAction(void) const
+{
+ if (device == NULL)
+ return NULL;
+ return udev_device_get_action(device);
+}
+
+cUdevListEntry *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 *cUdevDevice::GetDevnode(void) const
+{
+ if (device == NULL)
+ return false;
+ return udev_device_get_devnode(device);
+}
+
+const char *cUdevDevice::GetDevpath(void) const
+{
+ if (device == NULL)
+ return false;
+ return udev_device_get_devpath(device);
+}
+
+cUdevDevice *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 *cUdevDevice::GetPropertyValue(const char *Key) const
+{
+ if (device == NULL)
+ return false;
+ return udev_device_get_property_value(device, Key);
+}
+
+const char *cUdevDevice::GetSubsystem(void) const
+{
+ if (device == NULL)
+ return false;
+ return udev_device_get_subsystem(device);
+}
+
+const char *cUdevDevice::GetSysname(void) const
+{
+ if (device == NULL)
+ return false;
+ return udev_device_get_sysname(device);
+}
+
+const char *cUdevDevice::GetSyspath(void) const
+{
+ if (device == NULL)
+ return false;
+ return udev_device_get_syspath(device);
+}
+
+// --- cUdev -----------------------------------------------------------------
+
+struct udev *cUdev::udev = NULL;
+
+struct udev *cUdev::Init(void)
+{
+ if (udev == NULL)
+ udev = udev_new();
+ return udev;
+}
+
+void cUdev::Free(void)
+{
+ if (udev)
+ udev_unref(udev);
+ udev = NULL;
+}
+
+cUdevDevice *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);
+}
+
+cUdevDevice *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<cUdevDevice> *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("pvrinput: 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("pvrinput: 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("pvrinput: can't scan for devices: %d", rc);
+ goto unref;
+ }
+ l = udev_enumerate_get_list_entry(e);
+ if (l == NULL) {
+ isyslog("pvrinput: 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..23f8f5b
--- /dev/null
+++ b/udev.h
@@ -0,0 +1,51 @@
+#ifndef __PVRINPUT_UDEV_H
+#define __PVRINPUT_UDEV_H
+
+#include <libudev.h>
+
+#include <vdr/tools.h>
+
+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 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