Close all DVB device file descriptors when not in use. Fixes #892.
This commit is contained in:
parent
b5cfa01789
commit
f88892bd67
4 changed files with 100 additions and 27 deletions
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <linux/dvb/version.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <pthread.h>
|
||||
#include "htsmsg.h"
|
||||
|
||||
|
||||
|
@ -184,6 +185,7 @@ typedef struct th_dvb_adapter {
|
|||
uint32_t tda_disable_pmt_monitor;
|
||||
char *tda_displayname;
|
||||
|
||||
char *tda_fe_path;
|
||||
int tda_fe_fd;
|
||||
int tda_type;
|
||||
struct dvb_frontend_info *tda_fe_info;
|
||||
|
@ -192,7 +194,9 @@ typedef struct th_dvb_adapter {
|
|||
|
||||
char *tda_demux_path;
|
||||
|
||||
char *tda_dvr_path;
|
||||
char *tda_dvr_path;
|
||||
pthread_t tda_dvr_thread;
|
||||
int tda_dvr_pipe[2];
|
||||
|
||||
int tda_hostconnection;
|
||||
|
||||
|
@ -279,6 +283,10 @@ void dvb_adapter_init(uint32_t adapter_mask);
|
|||
|
||||
void dvb_adapter_mux_scanner(void *aux);
|
||||
|
||||
void dvb_adapter_start (th_dvb_adapter_t *tda);
|
||||
|
||||
void dvb_adapter_stop (th_dvb_adapter_t *tda);
|
||||
|
||||
void dvb_adapter_set_displayname(th_dvb_adapter_t *tda, const char *s);
|
||||
|
||||
void dvb_adapter_set_auto_discovery(th_dvb_adapter_t *tda, int on);
|
||||
|
@ -404,7 +412,7 @@ htsmsg_t *dvb_transport_build_msg(struct service *t);
|
|||
*/
|
||||
int dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason);
|
||||
|
||||
void dvb_fe_stop(th_dvb_mux_instance_t *tdmi);
|
||||
void dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,12 +16,14 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
@ -368,12 +370,10 @@ dvb_adapter_checkspeed(th_dvb_adapter_t *tda)
|
|||
static void
|
||||
tda_add(int adapter_num)
|
||||
{
|
||||
char path[200];
|
||||
char fname[256];
|
||||
char path[200], fname[256];
|
||||
int fe, i, r;
|
||||
th_dvb_adapter_t *tda;
|
||||
char buf[400];
|
||||
pthread_t ptid;
|
||||
|
||||
snprintf(path, sizeof(path), "/dev/dvb/adapter%d", adapter_num);
|
||||
snprintf(fname, sizeof(fname), "%s/frontend0", path);
|
||||
|
@ -394,18 +394,20 @@ tda_add(int adapter_num)
|
|||
snprintf(tda->tda_demux_path, 256, "%s/demux0", path);
|
||||
tda->tda_dvr_path = malloc(256);
|
||||
snprintf(tda->tda_dvr_path, 256, "%s/dvr0", path);
|
||||
tda->tda_fe_path = strdup(fname);
|
||||
|
||||
|
||||
tda->tda_fe_fd = fe;
|
||||
tda->tda_fe_fd = -1;
|
||||
tda->tda_dvr_pipe[0] = -1;
|
||||
|
||||
tda->tda_fe_info = malloc(sizeof(struct dvb_frontend_info));
|
||||
|
||||
if(ioctl(tda->tda_fe_fd, FE_GET_INFO, tda->tda_fe_info)) {
|
||||
if(ioctl(fe, FE_GET_INFO, tda->tda_fe_info)) {
|
||||
tvhlog(LOG_ALERT, "dvb", "%s: Unable to query adapter", fname);
|
||||
close(fe);
|
||||
free(tda);
|
||||
return;
|
||||
}
|
||||
close(fe);
|
||||
|
||||
tda->tda_type = tda->tda_fe_info->type;
|
||||
|
||||
|
@ -437,7 +439,6 @@ tda_add(int adapter_num)
|
|||
|
||||
TAILQ_INSERT_TAIL(&dvb_adapters, tda, tda_global_link);
|
||||
|
||||
pthread_create(&ptid, NULL, dvb_adapter_input_dvr, tda);
|
||||
|
||||
dvb_table_init(tda);
|
||||
|
||||
|
@ -447,6 +448,48 @@ tda_add(int adapter_num)
|
|||
gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 1);
|
||||
}
|
||||
|
||||
void
|
||||
dvb_adapter_start ( th_dvb_adapter_t *tda )
|
||||
{
|
||||
/* Open front end */
|
||||
if (tda->tda_fe_fd == -1) {
|
||||
tda->tda_fe_fd = tvh_open(tda->tda_fe_path, O_RDWR | O_NONBLOCK, 0);
|
||||
if (tda->tda_fe_fd == -1) return;
|
||||
tvhlog(LOG_DEBUG, "dvb", "%s opened frontend %s", tda->tda_rootpath, tda->tda_fe_path);
|
||||
}
|
||||
|
||||
/* Start DVR thread */
|
||||
if (tda->tda_dvr_pipe[0] == -1) {
|
||||
assert(pipe2(tda->tda_dvr_pipe, O_NONBLOCK | O_CLOEXEC) != -1);
|
||||
pthread_create(&tda->tda_dvr_thread, NULL, dvb_adapter_input_dvr, tda);
|
||||
tvhlog(LOG_DEBUG, "dvb", "%s started dvr thread", tda->tda_rootpath);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dvb_adapter_stop ( th_dvb_adapter_t *tda )
|
||||
{
|
||||
/* Poweroff */
|
||||
dvb_adapter_poweroff(tda);
|
||||
|
||||
/* Close front end */
|
||||
if (tda->tda_fe_fd != -1) {
|
||||
tvhlog(LOG_DEBUG, "dvb", "%s closing frontend", tda->tda_rootpath);
|
||||
close(tda->tda_fe_fd);
|
||||
tda->tda_fe_fd = -1;
|
||||
}
|
||||
|
||||
/* Stop DVR thread */
|
||||
if (tda->tda_dvr_pipe[0] != -1) {
|
||||
tvhlog(LOG_DEBUG, "dvb", "%s stopping thread", tda->tda_rootpath);
|
||||
assert(write(tda->tda_dvr_pipe[1], "", 1) == 1);
|
||||
pthread_join(tda->tda_dvr_thread, NULL);
|
||||
close(tda->tda_dvr_pipe[0]);
|
||||
close(tda->tda_dvr_pipe[1]);
|
||||
tda->tda_dvr_pipe[0] = -1;
|
||||
tvhlog(LOG_DEBUG, "dvb", "%s stopped thread", tda->tda_rootpath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -581,8 +624,7 @@ dvb_adapter_mux_scanner(void *aux)
|
|||
|
||||
/* Ensure we stop current mux and power off (if required) */
|
||||
if (tda->tda_mux_current)
|
||||
dvb_fe_stop(tda->tda_mux_current);
|
||||
dvb_adapter_poweroff(tda);
|
||||
dvb_fe_stop(tda->tda_mux_current, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -659,41 +701,58 @@ static void *
|
|||
dvb_adapter_input_dvr(void *aux)
|
||||
{
|
||||
th_dvb_adapter_t *tda = aux;
|
||||
int fd, i, r;
|
||||
int fd, i, r, efd, nfds;
|
||||
uint8_t tsb[188 * 10];
|
||||
service_t *t;
|
||||
struct epoll_event ev;
|
||||
|
||||
fd = tvh_open(tda->tda_dvr_path, O_RDONLY, 0);
|
||||
fd = tvh_open(tda->tda_dvr_path, O_RDONLY | O_NONBLOCK, 0);
|
||||
if(fd == -1) {
|
||||
tvhlog(LOG_ALERT, "dvb", "%s: unable to open dvr", tda->tda_dvr_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create poll */
|
||||
efd = epoll_create(2);
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.fd = fd;
|
||||
epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev);
|
||||
ev.data.fd = tda->tda_dvr_pipe[0];
|
||||
epoll_ctl(efd, EPOLL_CTL_ADD, tda->tda_dvr_pipe[0], &ev);
|
||||
|
||||
while(1){
|
||||
|
||||
/* Wait for input */
|
||||
nfds = epoll_wait(efd, &ev, 1, -1);
|
||||
if (nfds < 1) continue;
|
||||
if (ev.data.fd != fd) break;
|
||||
|
||||
while(1) {
|
||||
r = read(fd, tsb, sizeof(tsb));
|
||||
|
||||
pthread_mutex_lock(&tda->tda_delivery_mutex);
|
||||
|
||||
for(i = 0; i < r; i += 188) {
|
||||
LIST_FOREACH(t, &tda->tda_transports, s_active_link)
|
||||
if(t->s_dvb_mux_instance == tda->tda_mux_current)
|
||||
ts_recv_packet1(t, tsb + i, NULL);
|
||||
if(t->s_dvb_mux_instance == tda->tda_mux_current)
|
||||
ts_recv_packet1(t, tsb + i, NULL);
|
||||
}
|
||||
|
||||
if(tda->tda_dump_fd != -1) {
|
||||
if(write(tda->tda_dump_fd, tsb, r) != r) {
|
||||
tvhlog(LOG_ERR, "dvb",
|
||||
tvhlog(LOG_ERR, "dvb",
|
||||
"\"%s\" unable to write to mux dump file -- %s",
|
||||
tda->tda_identifier, strerror(errno));
|
||||
|
||||
close(tda->tda_dump_fd);
|
||||
tda->tda_dump_fd = -1;
|
||||
}
|
||||
close(tda->tda_dump_fd);
|
||||
tda->tda_dump_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&tda->tda_delivery_mutex);
|
||||
}
|
||||
|
||||
close(efd);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ dvb_fe_monitor(void *aux)
|
|||
* Stop the given TDMI
|
||||
*/
|
||||
void
|
||||
dvb_fe_stop(th_dvb_mux_instance_t *tdmi)
|
||||
dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune)
|
||||
{
|
||||
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
|
||||
|
||||
|
@ -233,8 +233,13 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi)
|
|||
}
|
||||
|
||||
epggrab_mux_stop(tdmi, 0);
|
||||
|
||||
|
||||
time(&tdmi->tdmi_lost_adapter);
|
||||
|
||||
if (!retune) {
|
||||
gtimer_disarm(&tda->tda_fe_monitor_timer);
|
||||
dvb_adapter_stop(tda);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -439,9 +444,10 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason)
|
|||
}
|
||||
|
||||
if(tda->tda_mux_current != NULL)
|
||||
dvb_fe_stop(tda->tda_mux_current);
|
||||
|
||||
|
||||
dvb_fe_stop(tda->tda_mux_current, 1);
|
||||
else
|
||||
dvb_adapter_start(tda);
|
||||
|
||||
if(tda->tda_type == FE_QPSK) {
|
||||
|
||||
/* DVB-S */
|
||||
|
|
|
@ -317,7 +317,7 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
|
|||
dvb_transport_notify_by_adapter(tda);
|
||||
|
||||
if(tda->tda_mux_current == tdmi)
|
||||
dvb_fe_stop(tda->tda_mux_current);
|
||||
dvb_fe_stop(tda->tda_mux_current, 0);
|
||||
|
||||
if(tdmi->tdmi_conf.dmc_satconf != NULL)
|
||||
LIST_REMOVE(tdmi, tdmi_satconf_link);
|
||||
|
|
Loading…
Add table
Reference in a new issue