diff options
author | Lars Hanisch <dvb@flensrocker.de> | 2014-01-07 21:39:48 +0100 |
---|---|---|
committer | Lars Hanisch <dvb@flensrocker.de> | 2014-01-07 21:39:48 +0100 |
commit | 7b55348e7a085be33d1f9b16d77c519df1c8772a (patch) | |
tree | ec7fa54fa9887882efef59075e2d773b491ec6a3 | |
parent | 38ffaa978886f85db84fa893d1fcd3f6fba11e58 (diff) | |
download | vdr-plugin-pvrinput-7b55348e7a085be33d1f9b16d77c519df1c8772a.tar.gz vdr-plugin-pvrinput-7b55348e7a085be33d1f9b16d77c519df1c8772a.tar.bz2 |
use udev to find related vbi device
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | device.c | 81 | ||||
-rw-r--r-- | device.h | 1 | ||||
-rw-r--r-- | pvrinput.c | 2 | ||||
-rw-r--r-- | udev.c | 222 | ||||
-rw-r--r-- | udev.h | 51 |
6 files changed, 334 insertions, 28 deletions
@@ -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) @@ -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; } @@ -97,6 +97,7 @@ private: eEncState EncoderState; int driver_apiversion; bool SupportsSlicedVBI; + cString vbi_dev; bool hasDecoder; bool hasTuner; int streamType; @@ -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"); @@ -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; +} @@ -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 |