aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libdvbv5/dvb-dev-local.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@s-opensource.com>2017-11-26 08:33:13 (GMT)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-11-27 10:19:29 (GMT)
commit0d34c5545f1f3e959a26820ba33d7bf3497d076f (patch)
tree6f0bfaa5ea725cf087401d9a155aaa321cbfa819 /lib/libdvbv5/dvb-dev-local.c
parenta8a04d397e929381a2150bee2100fc28ad2cfbec (diff)
dvb: better cope with dvbloopback
The dvbloopback OOT Kernel module is a dirty hack. It requires a Kernel patch that breaks the DVB core, removing mutex_lock(&dvbdev_mutex) during DVB open. Also, support for FE_GET_PROPERTY/FE_SET_PROPERTY is broken: it causes the Kernel to crash with: dvblb_poll 0frontend1: fd:0 BUG: unable to handle kernel paging request at 00007ffff41561c0 IP: dvblb_ioctl+0x428/0x6e0 [dvbloopback] Yet, it seems that users are trying to use it on some enviroments, as I got some reports that libdvbv5 doesn't handle it well. So, let's add some workarounds on libdvbv5, in order to make it work. There is a catch, though: without libdvbv5, it won't support second generation TV standards, like DVB-S2 and DVB-T2. This changeset works around 3 issues with dvbloopback: 1) only frontend0/dvr0/demux0/.. is used as a normal dvb adapter. The second ones are used by an special userspace interface, with shouldn't be vibible by libdvbv5 applications; 2) it expects that the device is opened with O_NONBLOCK; 3) the DVBv5 API support is broken. So, fallback to DVBv3. Tested using https://github.com/bas-t/dvbloopback, with is the first occurrence on Google for dvbloopback here. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'lib/libdvbv5/dvb-dev-local.c')
-rw-r--r--lib/libdvbv5/dvb-dev-local.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/lib/libdvbv5/dvb-dev-local.c b/lib/libdvbv5/dvb-dev-local.c
index eb2f077..7b1e1d8 100644
--- a/lib/libdvbv5/dvb-dev-local.c
+++ b/lib/libdvbv5/dvb-dev-local.c
@@ -175,6 +175,13 @@ static int handle_device_change(struct dvb_device_priv *dvb,
dvb_dev->bus_addr = buf;
+ /* Detect dvbloopback and ignore its control interface */
+ if (!strcmp(dvb_dev->bus_addr, "platform:dvbloopback")) {
+ char c = dvb_dev->path[strlen(dvb_dev->path) - 1] - '0';
+ if (c)
+ goto err;
+ }
+
/* Add new element */
dvb->d.num_devices++;
dvb_dev = realloc(dvb->d.devices, sizeof(*dvb->d.devices) * dvb->d.num_devices);
@@ -437,8 +444,19 @@ static struct dvb_open_descriptor
/*
* The frontend API was designed for sync frontend access.
* It is not ready to handle async frontend access.
+ * However, dvbloopback is a different beast: it only works
+ * if opened with O_NONBLOCK.
+ * Also, support for FE_SET_PROPERTY/FE_GET_PROPERTY
+ * is broken with dvbloopback and recent Kernels, as it
+ * doesn't copy from/to usermemory properly.
*/
- flags &= ~O_NONBLOCK;
+ if (!strcmp(dev->bus_addr, "platform:dvbloopback")) {
+ dvb_logwarn(_("Detected dvbloopback. Disabling DVBv5 API"));
+ parms->p.legacy_fe = 1;
+ flags |= O_NONBLOCK;
+ } else {
+ flags &= ~O_NONBLOCK;
+ }
ret = dvb_fe_open_fname(parms, strdup(dev->path), flags);
if (ret) {
@@ -575,6 +593,23 @@ static ssize_t dvb_local_read(struct dvb_open_descriptor *open_dev,
return -EINVAL;
}
+ /*
+ * As we opened dvbloopback on non-blocking mode, we need to
+ * check if read is ready, in order to emulate blocking mode
+ */
+ if (!strcmp(dev->bus_addr, "platform:dvbloopback")) {
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(fd, &set);
+ ret = TEMP_FAILURE_RETRY(select(FD_SETSIZE,
+ &set, NULL, &set, NULL));
+ if (ret == -1) {
+ if (errno != EOVERFLOW)
+ dvb_perror("read()");
+ return -errno;
+ }
+ }
+
ret = read(fd, buf, count);
if (ret == -1) {
if (errno != EOVERFLOW)

Privacy Policy