mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2023-10-10 13:37:43 +02:00
adapt to mainline kernel changes
This commit is contained in:
parent
626aa6d7be
commit
e9399971f8
@ -1,19 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
/*
|
/*
|
||||||
* dmxdev.c - DVB demultiplexer device
|
* dmxdev.c - DVB demultiplexer device
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
|
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
|
||||||
* for convergence integrated media GmbH
|
* for convergence integrated media GmbH
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define pr_fmt(fmt) "dmxdev: " fmt
|
#define pr_fmt(fmt) "dmxdev: " fmt
|
||||||
@ -369,13 +359,13 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
|
|||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
||||||
static void dvb_dmxdev_filter_timeout(struct timer_list *t)
|
static void dvb_dmxdev_filter_timeout(struct timer_list *t)
|
||||||
{
|
{
|
||||||
struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer);
|
struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer);
|
||||||
|
|
||||||
dmxdevfilter->buffer.error = -ETIMEDOUT;
|
dmxdevfilter->buffer.error = -ETIMEDOUT;
|
||||||
spin_lock_irq(&dmxdevfilter->dev->lock);
|
spin_lock_irq(&dmxdevfilter->dev->lock);
|
||||||
dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
|
dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
|
||||||
spin_unlock_irq(&dmxdevfilter->dev->lock);
|
spin_unlock_irq(&dmxdevfilter->dev->lock);
|
||||||
wake_up(&dmxdevfilter->buffer.queue);
|
wake_up(&dmxdevfilter->buffer.queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
|
static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
|
||||||
@ -384,8 +374,8 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
|
|||||||
|
|
||||||
del_timer(&dmxdevfilter->timer);
|
del_timer(&dmxdevfilter->timer);
|
||||||
if (para->timeout) {
|
if (para->timeout) {
|
||||||
dmxdevfilter->timer.expires =
|
dmxdevfilter->timer.expires =
|
||||||
jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
|
jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
|
||||||
add_timer(&dmxdevfilter->timer);
|
add_timer(&dmxdevfilter->timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,6 +405,7 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
||||||
const u8 *buffer2, size_t buffer2_len,
|
const u8 *buffer2, size_t buffer2_len,
|
||||||
struct dmx_section_filter *filter,
|
struct dmx_section_filter *filter,
|
||||||
@ -475,14 +466,14 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
|||||||
|
|
||||||
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
||||||
const u8 *buffer2, size_t buffer2_len,
|
const u8 *buffer2, size_t buffer2_len,
|
||||||
struct dmx_ts_feed *feed,
|
struct dmx_ts_feed *feed,
|
||||||
u32 *buffer_flags)
|
u32 *buffer_flags)
|
||||||
{
|
{
|
||||||
struct dmxdev_filter *dmxdevfilter = feed->priv;
|
struct dmxdev_filter *dmxdevfilter = feed->priv;
|
||||||
|
struct dvb_ringbuffer *buffer;
|
||||||
#ifdef CONFIG_DVB_MMAP
|
#ifdef CONFIG_DVB_MMAP
|
||||||
struct dvb_vb2_ctx *ctx;
|
struct dvb_vb2_ctx *ctx;
|
||||||
#endif
|
#endif
|
||||||
struct dvb_ringbuffer *buffer;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spin_lock(&dmxdevfilter->dev->lock);
|
spin_lock(&dmxdevfilter->dev->lock);
|
||||||
@ -849,6 +840,11 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
|
|||||||
if (mutex_lock_interruptible(&dmxdev->mutex))
|
if (mutex_lock_interruptible(&dmxdev->mutex))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
|
if (dmxdev->exit) {
|
||||||
|
mutex_unlock(&dmxdev->mutex);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < dmxdev->filternum; i++)
|
for (i = 0; i < dmxdev->filternum; i++)
|
||||||
if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
|
if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
|
||||||
break;
|
break;
|
||||||
@ -1485,7 +1481,7 @@ static const struct dvb_device dvbdev_dvr = {
|
|||||||
|
|
||||||
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
||||||
{
|
{
|
||||||
int i;
|
int i, ret;
|
||||||
|
|
||||||
if (dmxdev->demux->open(dmxdev->demux) < 0)
|
if (dmxdev->demux->open(dmxdev->demux) < 0)
|
||||||
return -EUSERS;
|
return -EUSERS;
|
||||||
@ -1508,21 +1504,36 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
|||||||
DMXDEV_STATE_FREE);
|
DMXDEV_STATE_FREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
|
ret = dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
|
||||||
DVB_DEVICE_DEMUX, dmxdev->filternum);
|
DVB_DEVICE_DEMUX, dmxdev->filternum);
|
||||||
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
|
if (ret < 0)
|
||||||
|
goto err_register_dvbdev;
|
||||||
|
|
||||||
|
ret = dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
|
||||||
dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
|
dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_register_dvr_dvbdev;
|
||||||
|
|
||||||
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
|
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_register_dvr_dvbdev:
|
||||||
|
dvb_unregister_device(dmxdev->dvbdev);
|
||||||
|
err_register_dvbdev:
|
||||||
|
vfree(dmxdev->filter);
|
||||||
|
dmxdev->filter = NULL;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(dvb_dmxdev_init);
|
EXPORT_SYMBOL(dvb_dmxdev_init);
|
||||||
|
|
||||||
void dvb_dmxdev_release(struct dmxdev *dmxdev)
|
void dvb_dmxdev_release(struct dmxdev *dmxdev)
|
||||||
{
|
{
|
||||||
|
mutex_lock(&dmxdev->mutex);
|
||||||
dmxdev->exit = 1;
|
dmxdev->exit = 1;
|
||||||
|
mutex_unlock(&dmxdev->mutex);
|
||||||
|
|
||||||
if (dmxdev->dvbdev->users > 1) {
|
if (dmxdev->dvbdev->users > 1) {
|
||||||
wait_event(dmxdev->dvbdev->wait_queue,
|
wait_event(dmxdev->dvbdev->wait_queue,
|
||||||
dmxdev->dvbdev->users == 1);
|
dmxdev->dvbdev->users == 1);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* dvb_ca.c: generic DVB functions for EN50221 CAM interfaces
|
* dvb_ca.c: generic DVB functions for EN50221 CAM interfaces
|
||||||
*
|
*
|
||||||
@ -164,7 +164,7 @@ static void dvb_ca_private_free(struct dvb_ca_private *ca)
|
|||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
dvb_free_device(ca->dvbdev);
|
dvb_device_put(ca->dvbdev);
|
||||||
for (i = 0; i < ca->slot_count; i++)
|
for (i = 0; i < ca->slot_count; i++)
|
||||||
vfree(ca->slot_info[i].rx_buffer.data);
|
vfree(ca->slot_info[i].rx_buffer.data);
|
||||||
|
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
/*
|
/*
|
||||||
* dvb_demux.c - DVB kernel demux API
|
* dvb_demux.c - DVB kernel demux API
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
|
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
|
||||||
* & Marcus Metzler <marcus@convergence.de>
|
* & Marcus Metzler <marcus@convergence.de>
|
||||||
* for convergence integrated media GmbH
|
* for convergence integrated media GmbH
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define pr_fmt(fmt) "dvb_demux: " fmt
|
#define pr_fmt(fmt) "dvb_demux: " fmt
|
||||||
@ -256,7 +246,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
|
|||||||
{
|
{
|
||||||
struct dvb_demux *demux = feed->demux;
|
struct dvb_demux *demux = feed->demux;
|
||||||
struct dmx_section_feed *sec = &feed->feed.sec;
|
struct dmx_section_feed *sec = &feed->feed.sec;
|
||||||
u16 limit, seclen, n;
|
u16 limit, seclen;
|
||||||
|
|
||||||
if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
|
if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
@ -285,7 +275,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
|
|||||||
/* to be sure always set secbuf */
|
/* to be sure always set secbuf */
|
||||||
sec->secbuf = sec->secbuf_base + sec->secbufp;
|
sec->secbuf = sec->secbuf_base + sec->secbufp;
|
||||||
|
|
||||||
for (n = 0; sec->secbufp + 2 < limit; n++) {
|
while (sec->secbufp + 2 < limit) {
|
||||||
seclen = section_length(sec->secbuf);
|
seclen = section_length(sec->secbuf);
|
||||||
if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
|
if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
|
||||||
|| seclen + sec->secbufp > limit)
|
|| seclen + sec->secbufp > limit)
|
||||||
@ -489,8 +479,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
|
dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
|
||||||
pid, demux->cnt_storage[pid],
|
pid, demux->cnt_storage[pid],
|
||||||
buf[3] & 0xf);
|
buf[3] & 0xf);
|
||||||
demux->cnt_storage[pid] = buf[3] & 0xf;
|
demux->cnt_storage[pid] = buf[3] & 0xf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
|
|||||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||||
|
|
||||||
if (fepriv)
|
if (fepriv)
|
||||||
dvb_free_device(fepriv->dvbdev);
|
dvb_device_put(fepriv->dvbdev);
|
||||||
|
|
||||||
dvb_frontend_invoke_release(fe, fe->ops.release);
|
dvb_frontend_invoke_release(fe, fe->ops.release);
|
||||||
|
|
||||||
@ -924,6 +924,7 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
|
|||||||
|
|
||||||
/* If the standard is for satellite, convert frequencies to kHz */
|
/* If the standard is for satellite, convert frequencies to kHz */
|
||||||
switch (c->delivery_system) {
|
switch (c->delivery_system) {
|
||||||
|
case SYS_DSS:
|
||||||
case SYS_DVBS:
|
case SYS_DVBS:
|
||||||
case SYS_DVBS2:
|
case SYS_DVBS2:
|
||||||
case SYS_TURBO:
|
case SYS_TURBO:
|
||||||
@ -949,6 +950,7 @@ static u32 dvb_frontend_get_stepsize(struct dvb_frontend *fe)
|
|||||||
u32 step = max(fe_step, tuner_step);
|
u32 step = max(fe_step, tuner_step);
|
||||||
|
|
||||||
switch (c->delivery_system) {
|
switch (c->delivery_system) {
|
||||||
|
case SYS_DSS:
|
||||||
case SYS_DVBS:
|
case SYS_DVBS:
|
||||||
case SYS_DVBS2:
|
case SYS_DVBS2:
|
||||||
case SYS_TURBO:
|
case SYS_TURBO:
|
||||||
@ -980,6 +982,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
|
|||||||
|
|
||||||
/* range check: symbol rate */
|
/* range check: symbol rate */
|
||||||
switch (c->delivery_system) {
|
switch (c->delivery_system) {
|
||||||
|
case SYS_DSS:
|
||||||
case SYS_DVBS:
|
case SYS_DVBS:
|
||||||
case SYS_DVBS2:
|
case SYS_DVBS2:
|
||||||
case SYS_TURBO:
|
case SYS_TURBO:
|
||||||
@ -1047,6 +1050,10 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
|
|||||||
c->input = NO_INPUT;
|
c->input = NO_INPUT;
|
||||||
|
|
||||||
switch (c->delivery_system) {
|
switch (c->delivery_system) {
|
||||||
|
case SYS_DSS:
|
||||||
|
c->modulation = QPSK;
|
||||||
|
c->rolloff = ROLLOFF_20;
|
||||||
|
break;
|
||||||
case SYS_DVBS:
|
case SYS_DVBS:
|
||||||
case SYS_DVBS2:
|
case SYS_DVBS2:
|
||||||
case SYS_TURBO:
|
case SYS_TURBO:
|
||||||
@ -1839,6 +1846,7 @@ static void prepare_tuning_algo_parameters(struct dvb_frontend *fe)
|
|||||||
} else {
|
} else {
|
||||||
/* default values */
|
/* default values */
|
||||||
switch (c->delivery_system) {
|
switch (c->delivery_system) {
|
||||||
|
case SYS_DSS:
|
||||||
case SYS_DVBS:
|
case SYS_DVBS:
|
||||||
case SYS_DVBS2:
|
case SYS_DVBS2:
|
||||||
case SYS_ISDBS:
|
case SYS_ISDBS:
|
||||||
@ -2312,6 +2320,9 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
|
|||||||
case SYS_DVBC_ANNEX_C:
|
case SYS_DVBC_ANNEX_C:
|
||||||
rolloff = 113;
|
rolloff = 113;
|
||||||
break;
|
break;
|
||||||
|
case SYS_DSS:
|
||||||
|
rolloff = 120;
|
||||||
|
break;
|
||||||
case SYS_DVBS:
|
case SYS_DVBS:
|
||||||
case SYS_TURBO:
|
case SYS_TURBO:
|
||||||
case SYS_ISDBS:
|
case SYS_ISDBS:
|
||||||
@ -2582,8 +2593,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
|
|||||||
|
|
||||||
case FE_DISEQC_SEND_BURST:
|
case FE_DISEQC_SEND_BURST:
|
||||||
if (fe->ops.diseqc_send_burst) {
|
if (fe->ops.diseqc_send_burst) {
|
||||||
err = fe->ops.diseqc_send_burst(fe,
|
err = fe->ops.diseqc_send_burst(fe, (long)parg);
|
||||||
(enum fe_sec_mini_cmd)parg);
|
|
||||||
fepriv->state = FESTATE_DISEQC;
|
fepriv->state = FESTATE_DISEQC;
|
||||||
fepriv->status = 0;
|
fepriv->status = 0;
|
||||||
}
|
}
|
||||||
@ -2591,9 +2601,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
|
|||||||
|
|
||||||
case FE_SET_TONE:
|
case FE_SET_TONE:
|
||||||
if (fe->ops.set_tone) {
|
if (fe->ops.set_tone) {
|
||||||
err = fe->ops.set_tone(fe,
|
fepriv->tone = (long)parg;
|
||||||
(enum fe_sec_tone_mode)parg);
|
err = fe->ops.set_tone(fe, fepriv->tone);
|
||||||
fepriv->tone = (enum fe_sec_tone_mode)parg;
|
|
||||||
fepriv->state = FESTATE_DISEQC;
|
fepriv->state = FESTATE_DISEQC;
|
||||||
fepriv->status = 0;
|
fepriv->status = 0;
|
||||||
}
|
}
|
||||||
@ -2601,9 +2610,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
|
|||||||
|
|
||||||
case FE_SET_VOLTAGE:
|
case FE_SET_VOLTAGE:
|
||||||
if (fe->ops.set_voltage) {
|
if (fe->ops.set_voltage) {
|
||||||
err = fe->ops.set_voltage(fe,
|
fepriv->voltage = (long)parg;
|
||||||
(enum fe_sec_voltage)parg);
|
err = fe->ops.set_voltage(fe, fepriv->voltage);
|
||||||
fepriv->voltage = (enum fe_sec_voltage)parg;
|
|
||||||
fepriv->state = FESTATE_DISEQC;
|
fepriv->state = FESTATE_DISEQC;
|
||||||
fepriv->status = 0;
|
fepriv->status = 0;
|
||||||
}
|
}
|
||||||
@ -2767,7 +2775,6 @@ typedef unsigned int __poll_t;
|
|||||||
#define EPOLLOUT POLLOUT
|
#define EPOLLOUT POLLOUT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
|
static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
|
||||||
{
|
{
|
||||||
struct dvb_device *dvbdev = file->private_data;
|
struct dvb_device *dvbdev = file->private_data;
|
||||||
@ -2796,7 +2803,17 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
|||||||
if (fe->exit == DVB_FE_DEVICE_REMOVED)
|
if (fe->exit == DVB_FE_DEVICE_REMOVED)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (adapter->mfe_shared) {
|
if (adapter->mfe_shared == 2) {
|
||||||
|
mutex_lock(&adapter->mfe_lock);
|
||||||
|
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
|
||||||
|
if (adapter->mfe_dvbdev &&
|
||||||
|
!adapter->mfe_dvbdev->writers) {
|
||||||
|
mutex_unlock(&adapter->mfe_lock);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
adapter->mfe_dvbdev = dvbdev;
|
||||||
|
}
|
||||||
|
} else if (adapter->mfe_shared) {
|
||||||
mutex_lock(&adapter->mfe_lock);
|
mutex_lock(&adapter->mfe_lock);
|
||||||
|
|
||||||
if (!adapter->mfe_dvbdev)
|
if (!adapter->mfe_dvbdev)
|
||||||
@ -2974,7 +2991,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe)
|
|||||||
else if (fe->ops.tuner_ops.sleep)
|
else if (fe->ops.tuner_ops.sleep)
|
||||||
ret = fe->ops.tuner_ops.sleep(fe);
|
ret = fe->ops.tuner_ops.sleep(fe);
|
||||||
|
|
||||||
if (fe->ops.sleep)
|
if (fe->ops.suspend)
|
||||||
|
ret = fe->ops.suspend(fe);
|
||||||
|
else if (fe->ops.sleep)
|
||||||
ret = fe->ops.sleep(fe);
|
ret = fe->ops.sleep(fe);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -2990,7 +3009,9 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
|
|||||||
fe->id);
|
fe->id);
|
||||||
|
|
||||||
fe->exit = DVB_FE_DEVICE_RESUME;
|
fe->exit = DVB_FE_DEVICE_RESUME;
|
||||||
if (fe->ops.init)
|
if (fe->ops.resume)
|
||||||
|
ret = fe->ops.resume(fe);
|
||||||
|
else if (fe->ops.init)
|
||||||
ret = fe->ops.init(fe);
|
ret = fe->ops.init(fe);
|
||||||
|
|
||||||
if (fe->ops.tuner_ops.resume)
|
if (fe->ops.tuner_ops.resume)
|
||||||
@ -3024,6 +3045,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
|
|||||||
.name = fe->ops.info.name,
|
.name = fe->ops.info.name,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
dev_dbg(dvb->device, "%s:\n", __func__);
|
dev_dbg(dvb->device, "%s:\n", __func__);
|
||||||
|
|
||||||
@ -3053,8 +3075,14 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
|
|||||||
fe->dvb = dvb;
|
fe->dvb = dvb;
|
||||||
fepriv->inversion = INVERSION_OFF;
|
fepriv->inversion = INVERSION_OFF;
|
||||||
|
|
||||||
dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
|
ret = dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
|
||||||
fe, DVB_DEVICE_FRONTEND, 0);
|
fe, DVB_DEVICE_FRONTEND, 0);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
dvb_frontend_put(fe);
|
||||||
|
mutex_unlock(&frontend_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
dev_info(fe->dvb->device,
|
dev_info(fe->dvb->device,
|
||||||
"DVB: registering adapter %i frontend %i (%s)...\n",
|
"DVB: registering adapter %i frontend %i (%s)...\n",
|
||||||
|
@ -60,6 +60,9 @@
|
|||||||
|
|
||||||
#include <media/dvb_demux.h>
|
#include <media/dvb_demux.h>
|
||||||
#include <media/dvb_net.h>
|
#include <media/dvb_net.h>
|
||||||
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
|
||||||
|
#include <linux/nospec.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
|
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
|
||||||
{
|
{
|
||||||
@ -662,7 +665,7 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
|
|||||||
h->ts_remain > 2 ?
|
h->ts_remain > 2 ?
|
||||||
*(unsigned short *)h->from_where : 0);
|
*(unsigned short *)h->from_where : 0);
|
||||||
|
|
||||||
#ifdef DVB_ULE_DEBUG
|
#ifdef DVB_ULE_DEBUG
|
||||||
hexdump(iov[0].iov_base, iov[0].iov_len);
|
hexdump(iov[0].iov_base, iov[0].iov_len);
|
||||||
hexdump(iov[1].iov_base, iov[1].iov_len);
|
hexdump(iov[1].iov_base, iov[1].iov_len);
|
||||||
hexdump(iov[2].iov_base, iov[2].iov_len);
|
hexdump(iov[2].iov_base, iov[2].iov_len);
|
||||||
@ -678,7 +681,7 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
|
|||||||
hexdump(ule_where - TS_SZ, TS_SZ);
|
hexdump(ule_where - TS_SZ, TS_SZ);
|
||||||
}
|
}
|
||||||
ule_dump = 1;
|
ule_dump = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
h->dev->stats.rx_errors++;
|
h->dev->stats.rx_errors++;
|
||||||
h->dev->stats.rx_crc_errors++;
|
h->dev->stats.rx_crc_errors++;
|
||||||
@ -1062,7 +1065,7 @@ static int dvb_net_feed_start(struct net_device *dev)
|
|||||||
int ret = 0, i;
|
int ret = 0, i;
|
||||||
struct dvb_net_priv *priv = netdev_priv(dev);
|
struct dvb_net_priv *priv = netdev_priv(dev);
|
||||||
struct dmx_demux *demux = priv->demux;
|
struct dmx_demux *demux = priv->demux;
|
||||||
const unsigned char *mac = (unsigned char *) dev->dev_addr;
|
const unsigned char *mac = (const unsigned char *) dev->dev_addr;
|
||||||
|
|
||||||
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
|
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
|
||||||
mutex_lock(&priv->mutex);
|
mutex_lock(&priv->mutex);
|
||||||
@ -1483,14 +1486,21 @@ static int dvb_net_do_ioctl(struct file *file,
|
|||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
struct dvb_net_priv *priv_data;
|
struct dvb_net_priv *priv_data;
|
||||||
struct dvb_net_if *dvbnetif = parg;
|
struct dvb_net_if *dvbnetif = parg;
|
||||||
|
int if_num = dvbnetif->if_num;
|
||||||
|
|
||||||
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
|
if (if_num >= DVB_NET_DEVICES_MAX) {
|
||||||
!dvbnet->state[dvbnetif->if_num]) {
|
ret = -EINVAL;
|
||||||
|
goto ioctl_error;
|
||||||
|
}
|
||||||
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
|
||||||
|
if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
|
||||||
|
#endif
|
||||||
|
if (!dvbnet->state[if_num]) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto ioctl_error;
|
goto ioctl_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
netdev = dvbnet->device[dvbnetif->if_num];
|
netdev = dvbnet->device[if_num];
|
||||||
|
|
||||||
priv_data = netdev_priv(netdev);
|
priv_data = netdev_priv(netdev);
|
||||||
dvbnetif->pid=priv_data->pid;
|
dvbnetif->pid=priv_data->pid;
|
||||||
@ -1543,14 +1553,21 @@ static int dvb_net_do_ioctl(struct file *file,
|
|||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
struct dvb_net_priv *priv_data;
|
struct dvb_net_priv *priv_data;
|
||||||
struct __dvb_net_if_old *dvbnetif = parg;
|
struct __dvb_net_if_old *dvbnetif = parg;
|
||||||
|
int if_num = dvbnetif->if_num;
|
||||||
|
|
||||||
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
|
if (if_num >= DVB_NET_DEVICES_MAX) {
|
||||||
!dvbnet->state[dvbnetif->if_num]) {
|
ret = -EINVAL;
|
||||||
|
goto ioctl_error;
|
||||||
|
}
|
||||||
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
|
||||||
|
if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
|
||||||
|
#endif
|
||||||
|
if (!dvbnet->state[if_num]) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto ioctl_error;
|
goto ioctl_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
netdev = dvbnet->device[dvbnetif->if_num];
|
netdev = dvbnet->device[if_num];
|
||||||
|
|
||||||
priv_data = netdev_priv(netdev);
|
priv_data = netdev_priv(netdev);
|
||||||
dvbnetif->pid=priv_data->pid;
|
dvbnetif->pid=priv_data->pid;
|
||||||
|
@ -63,7 +63,7 @@ int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
|
|||||||
* this pairs with smp_store_release() in dvb_ringbuffer_write(),
|
* this pairs with smp_store_release() in dvb_ringbuffer_write(),
|
||||||
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
|
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
|
||||||
*
|
*
|
||||||
* for memory barriers also see Documentation/core-api/circular-buffers.txt
|
* for memory barriers also see Documentation/core-api/circular-buffers.rst
|
||||||
*/
|
*/
|
||||||
return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
|
return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
|
||||||
#endif
|
#endif
|
||||||
@ -75,7 +75,7 @@ ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
|
|||||||
{
|
{
|
||||||
ssize_t free;
|
ssize_t free;
|
||||||
|
|
||||||
/* ACCESS_ONCE() to load read pointer on writer side
|
/* READ_ONCE() to load read pointer on writer side
|
||||||
* this pairs with smp_store_release() in dvb_ringbuffer_read(),
|
* this pairs with smp_store_release() in dvb_ringbuffer_read(),
|
||||||
* dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(),
|
* dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(),
|
||||||
* or dvb_ringbuffer_reset()
|
* or dvb_ringbuffer_reset()
|
||||||
@ -171,7 +171,7 @@ ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, si
|
|||||||
#else
|
#else
|
||||||
/* smp_store_release() for read pointer update to ensure
|
/* smp_store_release() for read pointer update to ensure
|
||||||
* that buf is not overwritten until read is complete,
|
* that buf is not overwritten until read is complete,
|
||||||
* this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
|
* this pairs with READ_ONCE() in dvb_ringbuffer_free()
|
||||||
*/
|
*/
|
||||||
smp_store_release(&rbuf->pread, 0);
|
smp_store_release(&rbuf->pread, 0);
|
||||||
#endif
|
#endif
|
||||||
@ -203,7 +203,7 @@ void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
|
|||||||
#else
|
#else
|
||||||
/* smp_store_release() for read pointer update to ensure
|
/* smp_store_release() for read pointer update to ensure
|
||||||
* that buf is not overwritten until read is complete,
|
* that buf is not overwritten until read is complete,
|
||||||
* this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
|
* this pairs with READ_ONCE() in dvb_ringbuffer_free()
|
||||||
*/
|
*/
|
||||||
smp_store_release(&rbuf->pread, 0);
|
smp_store_release(&rbuf->pread, 0);
|
||||||
#endif
|
#endif
|
||||||
@ -391,7 +391,7 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t*
|
|||||||
idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
|
idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
consumed = idx - rbuf->pread;
|
consumed = (idx - rbuf->pread);
|
||||||
if (consumed < 0)
|
if (consumed < 0)
|
||||||
consumed += rbuf->size;
|
consumed += rbuf->size;
|
||||||
|
|
||||||
|
@ -5,10 +5,6 @@
|
|||||||
* Copyright (C) 2015 Samsung Electronics
|
* Copyright (C) 2015 Samsung Electronics
|
||||||
*
|
*
|
||||||
* Author: jh1009.sung@samsung.com
|
* Author: jh1009.sung@samsung.com
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
@ -358,6 +354,12 @@ int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
|
|||||||
|
|
||||||
int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
|
int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
|
||||||
{
|
{
|
||||||
|
struct vb2_queue *q = &ctx->vb_q;
|
||||||
|
|
||||||
|
if (b->index >= q->num_buffers) {
|
||||||
|
dprintk(1, "[%s] buffer index out of range\n", ctx->name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
vb2_core_querybuf(&ctx->vb_q, b->index, b);
|
vb2_core_querybuf(&ctx->vb_q, b->index, b);
|
||||||
dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
|
dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
|
||||||
return 0;
|
return 0;
|
||||||
@ -382,8 +384,13 @@ int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp)
|
|||||||
|
|
||||||
int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
|
int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
|
||||||
{
|
{
|
||||||
|
struct vb2_queue *q = &ctx->vb_q;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (b->index >= q->num_buffers) {
|
||||||
|
dprintk(1, "[%s] buffer index out of range\n", ctx->name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL);
|
ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
|
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
/*
|
/*
|
||||||
* dvbdev.c
|
* dvbdev.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
|
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
|
||||||
* & Marcus Metzler <marcus@convergence.de>
|
* & Marcus Metzler <marcus@convergence.de>
|
||||||
* for convergence integrated media GmbH
|
* for convergence integrated media GmbH
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define pr_fmt(fmt) "dvbdev: " fmt
|
#define pr_fmt(fmt) "dvbdev: " fmt
|
||||||
@ -118,7 +108,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
|
|||||||
new_fops = fops_get(dvbdev->fops);
|
new_fops = fops_get(dvbdev->fops);
|
||||||
if (!new_fops)
|
if (!new_fops)
|
||||||
goto fail;
|
goto fail;
|
||||||
file->private_data = dvbdev;
|
file->private_data = dvb_device_get(dvbdev);
|
||||||
replace_fops(file, new_fops);
|
replace_fops(file, new_fops);
|
||||||
if (file->f_op->open)
|
if (file->f_op->open)
|
||||||
err = file->f_op->open(inode, file);
|
err = file->f_op->open(inode, file);
|
||||||
@ -182,6 +172,9 @@ int dvb_generic_release(struct inode *inode, struct file *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dvbdev->users++;
|
dvbdev->users++;
|
||||||
|
|
||||||
|
dvb_device_put(dvbdev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dvb_generic_release);
|
EXPORT_SYMBOL(dvb_generic_release);
|
||||||
@ -264,7 +257,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
|
|||||||
static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
|
static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
|
||||||
const char *name, int npads)
|
const char *name, int npads)
|
||||||
{
|
{
|
||||||
int i, ret = 0;
|
int i;
|
||||||
|
|
||||||
dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads),
|
dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
@ -281,6 +274,7 @@ static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
|
|||||||
for (i = 0; i < npads; i++) {
|
for (i = 0; i < npads; i++) {
|
||||||
struct media_pad *pads = &dvbdev->tsout_pads[i];
|
struct media_pad *pads = &dvbdev->tsout_pads[i];
|
||||||
struct media_entity *entity = &dvbdev->tsout_entity[i];
|
struct media_entity *entity = &dvbdev->tsout_entity[i];
|
||||||
|
int ret;
|
||||||
|
|
||||||
entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
|
entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
|
||||||
if (!entity->name)
|
if (!entity->name)
|
||||||
@ -353,6 +347,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
|
|||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!dvbdev->pads) {
|
if (!dvbdev->pads) {
|
||||||
kfree(dvbdev->entity);
|
kfree(dvbdev->entity);
|
||||||
|
dvbdev->entity = NULL;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -499,6 +494,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dvbdev, template, sizeof(struct dvb_device));
|
memcpy(dvbdev, template, sizeof(struct dvb_device));
|
||||||
|
kref_init(&dvbdev->ref);
|
||||||
dvbdev->type = type;
|
dvbdev->type = type;
|
||||||
dvbdev->id = id;
|
dvbdev->id = id;
|
||||||
dvbdev->adapter = adap;
|
dvbdev->adapter = adap;
|
||||||
@ -529,7 +525,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
dvbdev->minor = minor;
|
dvbdev->minor = minor;
|
||||||
dvb_minors[minor] = dvbdev;
|
dvb_minors[minor] = dvb_device_get(dvbdev);
|
||||||
up_write(&minor_rwsem);
|
up_write(&minor_rwsem);
|
||||||
|
|
||||||
ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
|
ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
|
||||||
@ -574,6 +570,7 @@ void dvb_remove_device(struct dvb_device *dvbdev)
|
|||||||
|
|
||||||
down_write(&minor_rwsem);
|
down_write(&minor_rwsem);
|
||||||
dvb_minors[dvbdev->minor] = NULL;
|
dvb_minors[dvbdev->minor] = NULL;
|
||||||
|
dvb_device_put(dvbdev);
|
||||||
up_write(&minor_rwsem);
|
up_write(&minor_rwsem);
|
||||||
|
|
||||||
dvb_media_device_free(dvbdev);
|
dvb_media_device_free(dvbdev);
|
||||||
@ -585,21 +582,34 @@ void dvb_remove_device(struct dvb_device *dvbdev)
|
|||||||
EXPORT_SYMBOL(dvb_remove_device);
|
EXPORT_SYMBOL(dvb_remove_device);
|
||||||
|
|
||||||
|
|
||||||
void dvb_free_device(struct dvb_device *dvbdev)
|
static void dvb_free_device(struct kref *ref)
|
||||||
{
|
{
|
||||||
if (!dvbdev)
|
struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
|
||||||
return;
|
|
||||||
|
|
||||||
kfree (dvbdev->fops);
|
kfree (dvbdev->fops);
|
||||||
kfree (dvbdev);
|
kfree (dvbdev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dvb_free_device);
|
|
||||||
|
|
||||||
|
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
|
||||||
|
{
|
||||||
|
kref_get(&dvbdev->ref);
|
||||||
|
return dvbdev;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_device_get);
|
||||||
|
|
||||||
|
|
||||||
|
void dvb_device_put(struct dvb_device *dvbdev)
|
||||||
|
{
|
||||||
|
if (dvbdev)
|
||||||
|
kref_put(&dvbdev->ref, dvb_free_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dvb_unregister_device(struct dvb_device *dvbdev)
|
void dvb_unregister_device(struct dvb_device *dvbdev)
|
||||||
{
|
{
|
||||||
dvb_remove_device(dvbdev);
|
dvb_remove_device(dvbdev);
|
||||||
dvb_free_device(dvbdev);
|
dvb_device_put(dvbdev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dvb_unregister_device);
|
EXPORT_SYMBOL(dvb_unregister_device);
|
||||||
|
|
||||||
@ -1041,9 +1051,13 @@ EXPORT_SYMBOL_GPL(dvb_module_release);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
|
||||||
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||||
|
#else
|
||||||
|
static int dvb_uevent(const struct device *dev, struct kobj_uevent_env *env)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
struct dvb_device *dvbdev = dev_get_drvdata(dev);
|
const struct dvb_device *dvbdev = dev_get_drvdata(dev);
|
||||||
|
|
||||||
add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
|
add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
|
||||||
add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
|
add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
|
||||||
@ -1051,9 +1065,13 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
|
||||||
static char *dvb_devnode(struct device *dev, umode_t *mode)
|
static char *dvb_devnode(struct device *dev, umode_t *mode)
|
||||||
|
#else
|
||||||
|
static char *dvb_devnode(const struct device *dev, umode_t *mode)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
struct dvb_device *dvbdev = dev_get_drvdata(dev);
|
const struct dvb_device *dvbdev = dev_get_drvdata(dev);
|
||||||
|
|
||||||
return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
|
return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
|
||||||
dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
|
dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
|
||||||
|
@ -280,7 +280,28 @@ enum fe_spectral_inversion {
|
|||||||
* @FEC_3_5: Forward Error Correction Code 3/5
|
* @FEC_3_5: Forward Error Correction Code 3/5
|
||||||
* @FEC_9_10: Forward Error Correction Code 9/10
|
* @FEC_9_10: Forward Error Correction Code 9/10
|
||||||
* @FEC_2_5: Forward Error Correction Code 2/5
|
* @FEC_2_5: Forward Error Correction Code 2/5
|
||||||
*
|
* @FEC_1_3: Forward Error Correction Code 1/3
|
||||||
|
* @FEC_1_4: Forward Error Correction Code 1/4
|
||||||
|
* @FEC_5_9: Forward Error Correction Code 5/9
|
||||||
|
* @FEC_7_9: Forward Error Correction Code 7/9
|
||||||
|
* @FEC_8_15: Forward Error Correction Code 8/15
|
||||||
|
* @FEC_11_15: Forward Error Correction Code 11/15
|
||||||
|
* @FEC_13_18: Forward Error Correction Code 13/18
|
||||||
|
* @FEC_9_20: Forward Error Correction Code 9/20
|
||||||
|
* @FEC_11_20: Forward Error Correction Code 11/20
|
||||||
|
* @FEC_23_36: Forward Error Correction Code 23/36
|
||||||
|
* @FEC_25_36: Forward Error Correction Code 25/36
|
||||||
|
* @FEC_13_45: Forward Error Correction Code 13/45
|
||||||
|
* @FEC_26_45: Forward Error Correction Code 26/45
|
||||||
|
* @FEC_28_45: Forward Error Correction Code 28/45
|
||||||
|
* @FEC_32_45: Forward Error Correction Code 32/45
|
||||||
|
* @FEC_77_90: Forward Error Correction Code 77/90
|
||||||
|
* @FEC_11_45: Forward Error Correction Code 11/45
|
||||||
|
* @FEC_4_15: Forward Error Correction Code 4/15
|
||||||
|
* @FEC_14_45: Forward Error Correction Code 14/45
|
||||||
|
* @FEC_7_15: Forward Error Correction Code 7/15
|
||||||
|
* @FEC_29_45: Forward Error Correction Code 29/45
|
||||||
|
* @FEC_31_45: Forward Error Correction Code 31/45
|
||||||
* Please note that not all FEC types are supported by a given standard.
|
* Please note that not all FEC types are supported by a given standard.
|
||||||
*/
|
*/
|
||||||
enum fe_code_rate {
|
enum fe_code_rate {
|
||||||
@ -297,8 +318,28 @@ enum fe_code_rate {
|
|||||||
FEC_3_5,
|
FEC_3_5,
|
||||||
FEC_9_10,
|
FEC_9_10,
|
||||||
FEC_2_5,
|
FEC_2_5,
|
||||||
FEC_1_4,
|
|
||||||
FEC_1_3,
|
FEC_1_3,
|
||||||
|
FEC_1_4,
|
||||||
|
FEC_5_9,
|
||||||
|
FEC_7_9,
|
||||||
|
FEC_8_15,
|
||||||
|
FEC_11_15,
|
||||||
|
FEC_13_18,
|
||||||
|
FEC_9_20,
|
||||||
|
FEC_11_20,
|
||||||
|
FEC_23_36,
|
||||||
|
FEC_25_36,
|
||||||
|
FEC_13_45,
|
||||||
|
FEC_26_45,
|
||||||
|
FEC_28_45,
|
||||||
|
FEC_32_45,
|
||||||
|
FEC_77_90,
|
||||||
|
FEC_11_45,
|
||||||
|
FEC_4_15,
|
||||||
|
FEC_14_45,
|
||||||
|
FEC_7_15,
|
||||||
|
FEC_29_45,
|
||||||
|
FEC_31_45,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -317,6 +358,16 @@ enum fe_code_rate {
|
|||||||
* @APSK_32: 32-APSK modulation
|
* @APSK_32: 32-APSK modulation
|
||||||
* @DQPSK: DQPSK modulation
|
* @DQPSK: DQPSK modulation
|
||||||
* @QAM_4_NR: 4-QAM-NR modulation
|
* @QAM_4_NR: 4-QAM-NR modulation
|
||||||
|
* @QAM_1024: 1024-QAM modulation
|
||||||
|
* @QAM_4096: 4096-QAM modulation
|
||||||
|
* @APSK_8_L: 8APSK-L modulation
|
||||||
|
* @APSK_16_L: 16APSK-L modulation
|
||||||
|
* @APSK_32_L: 32APSK-L modulation
|
||||||
|
* @APSK_64: 64APSK modulation
|
||||||
|
* @APSK_64_L: 64APSK-L modulation
|
||||||
|
* @APSK_128: 128APSK modulation
|
||||||
|
* @APSK_256: 256APSK modulation
|
||||||
|
* @APSK_256_L: 256APSK-L modulation
|
||||||
*
|
*
|
||||||
* Please note that not all modulations are supported by a given standard.
|
* Please note that not all modulations are supported by a given standard.
|
||||||
*
|
*
|
||||||
@ -336,9 +387,16 @@ enum fe_modulation {
|
|||||||
APSK_32,
|
APSK_32,
|
||||||
DQPSK,
|
DQPSK,
|
||||||
QAM_4_NR,
|
QAM_4_NR,
|
||||||
|
QAM_1024,
|
||||||
|
QAM_4096,
|
||||||
|
APSK_8_L,
|
||||||
|
APSK_16_L,
|
||||||
|
APSK_32_L,
|
||||||
APSK_64,
|
APSK_64,
|
||||||
|
APSK_64_L,
|
||||||
APSK_128,
|
APSK_128,
|
||||||
APSK_256,
|
APSK_256,
|
||||||
|
APSK_256_L,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -393,6 +451,7 @@ enum fe_transmit_mode {
|
|||||||
* @GUARD_INTERVAL_PN420: PN length 420 (1/4)
|
* @GUARD_INTERVAL_PN420: PN length 420 (1/4)
|
||||||
* @GUARD_INTERVAL_PN595: PN length 595 (1/6)
|
* @GUARD_INTERVAL_PN595: PN length 595 (1/6)
|
||||||
* @GUARD_INTERVAL_PN945: PN length 945 (1/9)
|
* @GUARD_INTERVAL_PN945: PN length 945 (1/9)
|
||||||
|
* @GUARD_INTERVAL_1_64: Guard interval 1/64
|
||||||
*
|
*
|
||||||
* Please note that not all guard intervals are supported by a given standard.
|
* Please note that not all guard intervals are supported by a given standard.
|
||||||
*/
|
*/
|
||||||
@ -408,6 +467,7 @@ enum fe_guard_interval {
|
|||||||
GUARD_INTERVAL_PN420,
|
GUARD_INTERVAL_PN420,
|
||||||
GUARD_INTERVAL_PN595,
|
GUARD_INTERVAL_PN595,
|
||||||
GUARD_INTERVAL_PN945,
|
GUARD_INTERVAL_PN945,
|
||||||
|
GUARD_INTERVAL_1_64,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -561,6 +621,9 @@ enum fe_pilot {
|
|||||||
* @ROLLOFF_20: Roloff factor: α=20%
|
* @ROLLOFF_20: Roloff factor: α=20%
|
||||||
* @ROLLOFF_25: Roloff factor: α=25%
|
* @ROLLOFF_25: Roloff factor: α=25%
|
||||||
* @ROLLOFF_AUTO: Auto-detect the roloff factor.
|
* @ROLLOFF_AUTO: Auto-detect the roloff factor.
|
||||||
|
* @ROLLOFF_15: Rolloff factor: α=15%
|
||||||
|
* @ROLLOFF_10: Rolloff factor: α=10%
|
||||||
|
* @ROLLOFF_5: Rolloff factor: α=5%
|
||||||
*
|
*
|
||||||
* .. note:
|
* .. note:
|
||||||
*
|
*
|
||||||
@ -587,6 +650,8 @@ enum fe_rolloff {
|
|||||||
* Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM)
|
* Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM)
|
||||||
* @SYS_DVBC_ANNEX_C:
|
* @SYS_DVBC_ANNEX_C:
|
||||||
* Cable TV: DVB-C following ITU-T J.83 Annex C spec
|
* Cable TV: DVB-C following ITU-T J.83 Annex C spec
|
||||||
|
* @SYS_DVBC2:
|
||||||
|
* Cable TV: DVB-C2
|
||||||
* @SYS_ISDBC:
|
* @SYS_ISDBC:
|
||||||
* Cable TV: ISDB-C (no drivers yet)
|
* Cable TV: ISDB-C (no drivers yet)
|
||||||
* @SYS_DVBT:
|
* @SYS_DVBT:
|
||||||
@ -604,7 +669,7 @@ enum fe_rolloff {
|
|||||||
* @SYS_DVBS:
|
* @SYS_DVBS:
|
||||||
* Satellite TV: DVB-S
|
* Satellite TV: DVB-S
|
||||||
* @SYS_DVBS2:
|
* @SYS_DVBS2:
|
||||||
* Satellite TV: DVB-S2
|
* Satellite TV: DVB-S2 and DVB-S2X
|
||||||
* @SYS_TURBO:
|
* @SYS_TURBO:
|
||||||
* Satellite TV: DVB-S Turbo
|
* Satellite TV: DVB-S Turbo
|
||||||
* @SYS_ISDBS:
|
* @SYS_ISDBS:
|
||||||
@ -714,7 +779,7 @@ enum atscmh_rs_frame_mode {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum atscmh_rs_code_mode
|
* enum atscmh_rs_code_mode - ATSC-M/H Reed Solomon modes
|
||||||
* @ATSCMH_RSCODE_211_187: Reed Solomon code (211,187).
|
* @ATSCMH_RSCODE_211_187: Reed Solomon code (211,187).
|
||||||
* @ATSCMH_RSCODE_223_187: Reed Solomon code (223,187).
|
* @ATSCMH_RSCODE_223_187: Reed Solomon code (223,187).
|
||||||
* @ATSCMH_RSCODE_235_187: Reed Solomon code (235,187).
|
* @ATSCMH_RSCODE_235_187: Reed Solomon code (235,187).
|
||||||
@ -755,8 +820,8 @@ enum fecap_scale_params {
|
|||||||
* struct dtv_stats - Used for reading a DTV status property
|
* struct dtv_stats - Used for reading a DTV status property
|
||||||
*
|
*
|
||||||
* @scale:
|
* @scale:
|
||||||
* Filled with enum fecap_scale_params - the scale in usage
|
* Filled with enum fecap_scale_params - the scale in usage
|
||||||
* for that parameter
|
* for that parameter
|
||||||
*
|
*
|
||||||
* @svalue:
|
* @svalue:
|
||||||
* integer value of the measure, for %FE_SCALE_DECIBEL,
|
* integer value of the measure, for %FE_SCALE_DECIBEL,
|
||||||
|
@ -369,6 +369,10 @@ struct dvb_frontend_internal_info {
|
|||||||
* allocated by the driver.
|
* allocated by the driver.
|
||||||
* @init: callback function used to initialize the tuner device.
|
* @init: callback function used to initialize the tuner device.
|
||||||
* @sleep: callback function used to put the tuner to sleep.
|
* @sleep: callback function used to put the tuner to sleep.
|
||||||
|
* @suspend: callback function used to inform that the Kernel will
|
||||||
|
* suspend.
|
||||||
|
* @resume: callback function used to inform that the Kernel is
|
||||||
|
* resuming from suspend.
|
||||||
* @write: callback function used by some demod legacy drivers to
|
* @write: callback function used by some demod legacy drivers to
|
||||||
* allow other drivers to write data into their registers.
|
* allow other drivers to write data into their registers.
|
||||||
* Should not be used on new drivers.
|
* Should not be used on new drivers.
|
||||||
@ -438,7 +442,6 @@ struct dvb_frontend_internal_info {
|
|||||||
* @analog_ops: pointer to &struct analog_demod_ops
|
* @analog_ops: pointer to &struct analog_demod_ops
|
||||||
*/
|
*/
|
||||||
struct dvb_frontend_ops {
|
struct dvb_frontend_ops {
|
||||||
|
|
||||||
struct dvb_frontend_internal_info info;
|
struct dvb_frontend_internal_info info;
|
||||||
|
|
||||||
u8 delsys[MAX_DELSYS];
|
u8 delsys[MAX_DELSYS];
|
||||||
@ -449,6 +452,8 @@ struct dvb_frontend_ops {
|
|||||||
|
|
||||||
int (*init)(struct dvb_frontend* fe);
|
int (*init)(struct dvb_frontend* fe);
|
||||||
int (*sleep)(struct dvb_frontend* fe);
|
int (*sleep)(struct dvb_frontend* fe);
|
||||||
|
int (*suspend)(struct dvb_frontend *fe);
|
||||||
|
int (*resume)(struct dvb_frontend *fe);
|
||||||
|
|
||||||
int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
|
int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
|
||||||
|
|
||||||
@ -765,7 +770,8 @@ void dvb_frontend_detach(struct dvb_frontend *fe);
|
|||||||
* &dvb_frontend_ops.tuner_ops.suspend\(\) is available, it calls it. Otherwise,
|
* &dvb_frontend_ops.tuner_ops.suspend\(\) is available, it calls it. Otherwise,
|
||||||
* it will call &dvb_frontend_ops.tuner_ops.sleep\(\), if available.
|
* it will call &dvb_frontend_ops.tuner_ops.sleep\(\), if available.
|
||||||
*
|
*
|
||||||
* It will also call &dvb_frontend_ops.sleep\(\) to put the demod to suspend.
|
* It will also call &dvb_frontend_ops.suspend\(\) to put the demod to suspend,
|
||||||
|
* if available. Otherwise it will call &dvb_frontend_ops.sleep\(\).
|
||||||
*
|
*
|
||||||
* The drivers should also call dvb_frontend_suspend\(\) as part of their
|
* The drivers should also call dvb_frontend_suspend\(\) as part of their
|
||||||
* handler for the &device_driver.suspend\(\).
|
* handler for the &device_driver.suspend\(\).
|
||||||
@ -779,7 +785,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe);
|
|||||||
*
|
*
|
||||||
* This function resumes the usual operation of the tuner after resume.
|
* This function resumes the usual operation of the tuner after resume.
|
||||||
*
|
*
|
||||||
* In order to resume the frontend, it calls the demod &dvb_frontend_ops.init\(\).
|
* In order to resume the frontend, it calls the demod
|
||||||
|
* &dvb_frontend_ops.resume\(\) if available. Otherwise it calls demod
|
||||||
|
* &dvb_frontend_ops.init\(\).
|
||||||
*
|
*
|
||||||
* If &dvb_frontend_ops.tuner_ops.resume\(\) is available, It, it calls it.
|
* If &dvb_frontend_ops.tuner_ops.resume\(\) is available, It, it calls it.
|
||||||
* Otherwise,t will call &dvb_frontend_ops.tuner_ops.init\(\), if available.
|
* Otherwise,t will call &dvb_frontend_ops.tuner_ops.init\(\), if available.
|
||||||
|
@ -214,7 +214,7 @@ extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
|
|||||||
* @buf: Buffer to write.
|
* @buf: Buffer to write.
|
||||||
* @len: Length of buffer (currently limited to 65535 bytes max).
|
* @len: Length of buffer (currently limited to 65535 bytes max).
|
||||||
*
|
*
|
||||||
* Return: Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
|
* Return: Number of bytes written, or -EFAULT, -ENOMEM, -EINVAL.
|
||||||
*/
|
*/
|
||||||
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf,
|
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DVB_MAX_ADAPTERS 64
|
#define DVB_MAX_ADAPTERS 64
|
||||||
|
|
||||||
#define DVB_UNSET (-1)
|
#define DVB_UNSET (-1)
|
||||||
|
|
||||||
@ -96,7 +96,11 @@ struct dvb_frontend;
|
|||||||
* @device: pointer to struct device
|
* @device: pointer to struct device
|
||||||
* @module: pointer to struct module
|
* @module: pointer to struct module
|
||||||
* @mfe_shared: indicates mutually exclusive frontends.
|
* @mfe_shared: indicates mutually exclusive frontends.
|
||||||
* Use of this flag is currently deprecated.
|
* 1 = legacy exclusion behavior: blocking any open() call
|
||||||
|
* 2 = enhanced exclusion behavior, emulating the standard
|
||||||
|
* behavior of busy frontends: allowing read-only sharing
|
||||||
|
* and otherwise returning immediately with -EBUSY when any
|
||||||
|
* of the frontends is already opened with write access.
|
||||||
* @mfe_dvbdev: Frontend device in use, in the case of MFE
|
* @mfe_dvbdev: Frontend device in use, in the case of MFE
|
||||||
* @mfe_lock: Lock to prevent using the other frontends when MFE is
|
* @mfe_lock: Lock to prevent using the other frontends when MFE is
|
||||||
* used.
|
* used.
|
||||||
@ -135,6 +139,7 @@ struct dvb_adapter {
|
|||||||
* struct dvb_device - represents a DVB device node
|
* struct dvb_device - represents a DVB device node
|
||||||
*
|
*
|
||||||
* @list_head: List head with all DVB devices
|
* @list_head: List head with all DVB devices
|
||||||
|
* @ref: reference counter
|
||||||
* @fops: pointer to struct file_operations
|
* @fops: pointer to struct file_operations
|
||||||
* @adapter: pointer to the adapter that holds this device node
|
* @adapter: pointer to the adapter that holds this device node
|
||||||
* @type: type of the device, as defined by &enum dvb_device_type.
|
* @type: type of the device, as defined by &enum dvb_device_type.
|
||||||
@ -165,6 +170,7 @@ struct dvb_adapter {
|
|||||||
*/
|
*/
|
||||||
struct dvb_device {
|
struct dvb_device {
|
||||||
struct list_head list_head;
|
struct list_head list_head;
|
||||||
|
struct kref ref;
|
||||||
const struct file_operations *fops;
|
const struct file_operations *fops;
|
||||||
struct dvb_adapter *adapter;
|
struct dvb_adapter *adapter;
|
||||||
enum dvb_device_type type;
|
enum dvb_device_type type;
|
||||||
@ -196,6 +202,20 @@ struct dvb_device {
|
|||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dvb_device_get - Increase dvb_device reference
|
||||||
|
*
|
||||||
|
* @dvbdev: pointer to struct dvb_device
|
||||||
|
*/
|
||||||
|
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dvb_device_put - Decrease dvb_device reference
|
||||||
|
*
|
||||||
|
* @dvbdev: pointer to struct dvb_device
|
||||||
|
*/
|
||||||
|
void dvb_device_put(struct dvb_device *dvbdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dvb_register_adapter - Registers a new DVB adapter
|
* dvb_register_adapter - Registers a new DVB adapter
|
||||||
*
|
*
|
||||||
@ -240,29 +260,16 @@ int dvb_register_device(struct dvb_adapter *adap,
|
|||||||
/**
|
/**
|
||||||
* dvb_remove_device - Remove a registered DVB device
|
* dvb_remove_device - Remove a registered DVB device
|
||||||
*
|
*
|
||||||
* This does not free memory. To do that, call dvb_free_device().
|
* This does not free memory. dvb_free_device() will do that when
|
||||||
|
* reference counter is empty
|
||||||
*
|
*
|
||||||
* @dvbdev: pointer to struct dvb_device
|
* @dvbdev: pointer to struct dvb_device
|
||||||
*/
|
*/
|
||||||
void dvb_remove_device(struct dvb_device *dvbdev);
|
void dvb_remove_device(struct dvb_device *dvbdev);
|
||||||
|
|
||||||
/**
|
|
||||||
* dvb_free_device - Free memory occupied by a DVB device.
|
|
||||||
*
|
|
||||||
* Call dvb_unregister_device() before calling this function.
|
|
||||||
*
|
|
||||||
* @dvbdev: pointer to struct dvb_device
|
|
||||||
*/
|
|
||||||
void dvb_free_device(struct dvb_device *dvbdev);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dvb_unregister_device - Unregisters a DVB device
|
* dvb_unregister_device - Unregisters a DVB device
|
||||||
*
|
*
|
||||||
* This is a combination of dvb_remove_device() and dvb_free_device().
|
|
||||||
* Using this function is usually a mistake, and is often an indicator
|
|
||||||
* for a use-after-free bug (when a userspace process keeps a file
|
|
||||||
* handle to a detached device).
|
|
||||||
*
|
|
||||||
* @dvbdev: pointer to struct dvb_device
|
* @dvbdev: pointer to struct dvb_device
|
||||||
*/
|
*/
|
||||||
void dvb_unregister_device(struct dvb_device *dvbdev);
|
void dvb_unregister_device(struct dvb_device *dvbdev);
|
||||||
|
Loading…
Reference in New Issue
Block a user