Commit ea4e38b5 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Linux DVB: revive --dvb-device to support multihead adaptors

parent b517ac74
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
"If there is more than one digital broadcasting adapter, " \ "If there is more than one digital broadcasting adapter, " \
"the adapter number must be selected. Numbering starts from zero.") "the adapter number must be selected. Numbering starts from zero.")
#define DEVICE_TEXT N_("DVB device")
#define DEVICE_LONGTEXT N_( \
"If the adapter provides multiple independent tuner devices, " \
"the device number must be selected. Numbering starts from zero.")
#define BUDGET_TEXT N_("Do not demultiplex") #define BUDGET_TEXT N_("Do not demultiplex")
#define BUDGET_LONGTEXT N_( \ #define BUDGET_LONGTEXT N_( \
"Only useful programs are normally demultiplexed from the transponder. " \ "Only useful programs are normally demultiplexed from the transponder. " \
...@@ -242,7 +246,9 @@ vlc_module_begin () ...@@ -242,7 +246,9 @@ vlc_module_begin ()
add_integer ("dvb-adapter", 0, ADAPTER_TEXT, ADAPTER_LONGTEXT, false) add_integer ("dvb-adapter", 0, ADAPTER_TEXT, ADAPTER_LONGTEXT, false)
change_integer_range (0, 255) change_integer_range (0, 255)
change_safe () change_safe ()
add_obsolete_integer ("dvb-device") add_integer ("dvb-device", 0, DEVICE_TEXT, DEVICE_LONGTEXT, false)
change_integer_range (0, 255)
change_safe ()
add_bool ("dvb-budget-mode", false, BUDGET_TEXT, BUDGET_LONGTEXT, true) add_bool ("dvb-budget-mode", false, BUDGET_TEXT, BUDGET_LONGTEXT, true)
#endif #endif
#ifdef WIN32 #ifdef WIN32
......
...@@ -50,28 +50,6 @@ ...@@ -50,28 +50,6 @@
(DVB_API_VERSION > 5 \ (DVB_API_VERSION > 5 \
|| (DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= (minor))) || (DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= (minor)))
/** Opens the device directory for the specified DVB adapter */
static int dvb_open_adapter (uint8_t adapter)
{
char dir[20];
snprintf (dir, sizeof (dir), "/dev/dvb/adapter%"PRIu8, adapter);
return vlc_open (dir, O_SEARCH|O_DIRECTORY);
}
/** Opens the DVB device node of the specified type */
static int dvb_open_node (int dir, const char *type, unsigned dev, int flags)
{
int fd;
char path[strlen (type) + 4];
snprintf (path, sizeof (path), "%s%u", type, dev);
fd = vlc_openat (dir, path, flags);
if (fd != -1)
fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_NONBLOCK);
return fd;
}
typedef struct typedef struct
{ {
int vlc; int vlc;
...@@ -182,11 +160,33 @@ struct dvb_device ...@@ -182,11 +160,33 @@ struct dvb_device
#ifdef HAVE_DVBPSI #ifdef HAVE_DVBPSI
cam_t *cam; cam_t *cam;
#endif #endif
unsigned systems; uint8_t device;
bool budget; bool budget;
//size_t buffer_size; //size_t buffer_size;
}; };
/** Opens the device directory for the specified DVB adapter */
static int dvb_open_adapter (uint8_t adapter)
{
char dir[20];
snprintf (dir, sizeof (dir), "/dev/dvb/adapter%"PRIu8, adapter);
return vlc_open (dir, O_SEARCH|O_DIRECTORY);
}
/** Opens the DVB device node of the specified type */
static int dvb_open_node (dvb_device_t *d, const char *type, int flags)
{
int fd;
char path[strlen (type) + 4];
snprintf (path, sizeof (path), "%s%u", type, d->device);
fd = vlc_openat (d->dir, path, flags);
if (fd != -1)
fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_NONBLOCK);
return fd;
}
/** /**
* Opens the DVB tuner * Opens the DVB tuner
*/ */
...@@ -199,6 +199,7 @@ dvb_device_t *dvb_open (vlc_object_t *obj) ...@@ -199,6 +199,7 @@ dvb_device_t *dvb_open (vlc_object_t *obj)
d->obj = obj; d->obj = obj;
uint8_t adapter = var_InheritInteger (obj, "dvb-adapter"); uint8_t adapter = var_InheritInteger (obj, "dvb-adapter");
d->device = var_InheritInteger (obj, "dvb-device");
d->dir = dvb_open_adapter (adapter); d->dir = dvb_open_adapter (adapter);
if (d->dir == -1) if (d->dir == -1)
...@@ -217,7 +218,7 @@ dvb_device_t *dvb_open (vlc_object_t *obj) ...@@ -217,7 +218,7 @@ dvb_device_t *dvb_open (vlc_object_t *obj)
if (d->budget) if (d->budget)
#endif #endif
{ {
d->demux = dvb_open_node (d->dir, "demux", 0, O_RDONLY); d->demux = dvb_open_node (d, "demux", O_RDONLY);
if (d->demux == -1) if (d->demux == -1)
{ {
msg_Err (obj, "cannot access demultiplexer: %m"); msg_Err (obj, "cannot access demultiplexer: %m");
...@@ -249,7 +250,7 @@ dvb_device_t *dvb_open (vlc_object_t *obj) ...@@ -249,7 +250,7 @@ dvb_device_t *dvb_open (vlc_object_t *obj)
{ {
for (size_t i = 0; i < MAX_PIDS; i++) for (size_t i = 0; i < MAX_PIDS; i++)
d->pids[i].pid = d->pids[i].fd = -1; d->pids[i].pid = d->pids[i].fd = -1;
d->demux = dvb_open_node (d->dir, "dvr", 0, O_RDONLY); d->demux = dvb_open_node (d, "dvr", O_RDONLY);
if (d->demux == -1) if (d->demux == -1)
{ {
msg_Err (obj, "cannot access DVR: %m"); msg_Err (obj, "cannot access DVR: %m");
...@@ -261,7 +262,7 @@ dvb_device_t *dvb_open (vlc_object_t *obj) ...@@ -261,7 +262,7 @@ dvb_device_t *dvb_open (vlc_object_t *obj)
} }
#ifdef HAVE_DVBPSI #ifdef HAVE_DVBPSI
int ca = dvb_open_node (d->dir, "ca", 0, O_RDWR); int ca = dvb_open_node (d, "ca", O_RDWR);
if (ca != -1) if (ca != -1)
{ {
d->cam = en50221_Init (obj, ca); d->cam = en50221_Init (obj, ca);
...@@ -379,7 +380,7 @@ int dvb_add_pid (dvb_device_t *d, uint16_t pid) ...@@ -379,7 +380,7 @@ int dvb_add_pid (dvb_device_t *d, uint16_t pid)
if (d->pids[i].fd != -1) if (d->pids[i].fd != -1)
continue; continue;
int fd = dvb_open_node (d->dir, "demux", 0, O_RDONLY); int fd = dvb_open_node (d, "demux", O_RDONLY);
if (fd == -1) if (fd == -1)
goto error; goto error;
...@@ -428,9 +429,31 @@ void dvb_remove_pid (dvb_device_t *d, uint16_t pid) ...@@ -428,9 +429,31 @@ void dvb_remove_pid (dvb_device_t *d, uint16_t pid)
#endif #endif
} }
/** Enumerates the systems supported by one frontend */ /** Finds a frontend of the correct type */
static unsigned dvb_probe_frontend (dvb_device_t *d, int fd) static int dvb_open_frontend (dvb_device_t *d)
{
if (d->frontend != -1)
return 0;
int fd = dvb_open_node (d, "frontend", O_RDWR);
if (fd == -1)
{
msg_Err (d->obj, "cannot access frontend: %m");
return -1;
}
d->frontend = fd;
return 0;
}
#define dvb_find_frontend(d, sys) (dvb_open_frontend(d))
/**
* Detects supported delivery systems.
* @return a bit mask of supported systems (zero on failure)
*/
unsigned dvb_enum_systems (dvb_device_t *d)
{ {
if (dvb_open_frontend (d))
return 0;
#if DVBv5(5) #if DVBv5(5)
struct dtv_property prop[2] = { struct dtv_property prop[2] = {
{ .cmd = DTV_API_VERSION }, { .cmd = DTV_API_VERSION },
...@@ -441,7 +464,7 @@ static unsigned dvb_probe_frontend (dvb_device_t *d, int fd) ...@@ -441,7 +464,7 @@ static unsigned dvb_probe_frontend (dvb_device_t *d, int fd)
.props = prop .props = prop
}; };
if (ioctl (fd, FE_GET_PROPERTY, &props) < 0) if (ioctl (d->frontend, FE_GET_PROPERTY, &props) < 0)
{ {
msg_Err (d->obj, "cannot enumerate frontend systems: %m"); msg_Err (d->obj, "cannot enumerate frontend systems: %m");
goto legacy; goto legacy;
...@@ -500,7 +523,7 @@ legacy: ...@@ -500,7 +523,7 @@ legacy:
}; };
unsigned systems = 0; unsigned systems = 0;
#endif #endif
if (ioctl (fd, FE_GET_PROPERTY, &props) < 0) if (ioctl (d->frontend, FE_GET_PROPERTY, &props) < 0)
{ {
msg_Err (d->obj, "unsupported kernel DVB version 3 or older (%m)"); msg_Err (d->obj, "unsupported kernel DVB version 3 or older (%m)");
return 0; return 0;
...@@ -519,7 +542,7 @@ legacy: ...@@ -519,7 +542,7 @@ legacy:
msg_Info (d->obj, "please recompile "PACKAGE_NAME" "PACKAGE_VERSION); msg_Info (d->obj, "please recompile "PACKAGE_NAME" "PACKAGE_VERSION);
#endif #endif
struct dvb_frontend_info info; struct dvb_frontend_info info;
if (ioctl (fd, FE_GET_INFO, &info) < 0) if (ioctl (d->frontend, FE_GET_INFO, &info) < 0)
{ {
msg_Err (d->obj, "cannot get frontend info: %m"); msg_Err (d->obj, "cannot get frontend info: %m");
return 0; return 0;
...@@ -564,70 +587,6 @@ legacy: ...@@ -564,70 +587,6 @@ legacy:
return systems; return systems;
} }
/** Finds a frontend of the correct type */
static int dvb_find_frontend (dvb_device_t *d, unsigned system)
{
if (d->frontend != -1)
{
if (d->systems & system)
return 0; /* already got an adequate frontend */
close (d->frontend);
d->frontend = -1;
}
for (unsigned n = 0; n < 256; n++)
{
int fd = dvb_open_node (d->dir, "frontend", n, O_RDWR);
if (fd == -1)
{
if (errno == ENOENT)
break; /* all frontends already enumerated */
msg_Err (d->obj, "cannot access frontend %u: %m", n);
continue;
}
d->systems = dvb_probe_frontend (d, fd);
if (d->systems & system)
{
msg_Dbg (d->obj, "selected frontend %u", n);
d->frontend = fd;
return 0;
}
msg_Dbg (d->obj, "skipping frontend %u: wrong type", n);
close (fd);
}
msg_Err (d->obj, "no suitable frontend found");
return -1;
}
/**
* Detects supported delivery systems.
* @return a bit mask of supported systems (zero on failure)
*/
unsigned dvb_enum_systems (dvb_device_t *d)
{
unsigned systems = 0;
for (unsigned n = 0; n < 256; n++)
{
int fd = dvb_open_node (d->dir, "frontend", n, O_RDWR);
if (fd == -1)
{
if (errno == ENOENT)
break; /* all frontends already enumerated */
msg_Err (d->obj, "cannot access frontend %u; %m", n);
continue;
}
systems |= dvb_probe_frontend (d, fd);
close (fd);
}
return systems;
}
float dvb_get_signal_strength (dvb_device_t *d) float dvb_get_signal_strength (dvb_device_t *d)
{ {
uint16_t strength; uint16_t strength;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment