1
0
mirror of https://github.com/DigitalDevices/dddvb.git synced 2023-10-10 13:37:43 +02:00

Merge branch 'internal'

This commit is contained in:
internal 2023-10-02 11:58:43 +02:00
commit 100aa25176
17 changed files with 342 additions and 1099 deletions

View File

@ -866,7 +866,7 @@ int mci_set_output(int fd, uint8_t connector, uint8_t nchannels, uint8_t unit,
break; break;
} }
fprintf(stderr,"Setting DVBT Modulator output to %s, %d channels, power %f%s\n", fprintf(stderr,"Setting DVB Modulator output to %s, %d channels, power %f%s\n",
con, nchannels, (double)power/100, un ); con, nchannels, (double)power/100, un );
return mci_cmd(fd,&msg_output); return mci_cmd(fd,&msg_output);
@ -934,19 +934,32 @@ int mci_set_channels(int fd, uint32_t freq, uint8_t nchan, uint8_t standard,
snprintf(stand, 24, "MOD_STANDARD_DVBT_5"); snprintf(stand, 24, "MOD_STANDARD_DVBT_5");
break; break;
case MOD_STANDARD_DVBC_8:
snprintf(stand, 24, "MOD_STANDARD_DVBC_8");
break;
case MOD_STANDARD_DVBC_7:
snprintf(stand, 24, "MOD_STANDARD_DVBC_7");
break;
case MOD_STANDARD_DVBC_6:
snprintf(stand, 24, "MOD_STANDARD_DVBC_6");
break;
default: default:
fprintf(stderr,"unknown standard in channels setup\n"); fprintf(stderr,"unknown standard in channels setup\n");
return -1; return -1;
break; break;
} }
fprintf(stderr,"Setting DVBT Modulator channels to %d HZ, %d channels, %s\n", fprintf(stderr,"Setting DVB Modulator channels to %d HZ, %d channels, %s\n",
freq, nchan, stand); freq, nchan, stand);
return mci_cmd(fd,&msg_channels); return mci_cmd(fd,&msg_channels);
} }
int mci_set_channels_simple(int adapt, uint32_t freq, uint8_t nchan) int mci_set_channels_simple(int adapt, enum fe_delivery_system delsys,
uint32_t freq, uint8_t nchan)
{ {
char fn[128]; char fn[128];
@ -958,8 +971,18 @@ int mci_set_channels_simple(int adapt, uint32_t freq, uint8_t nchan)
fprintf(stderr, "Could not open %s\n", fn); fprintf(stderr, "Could not open %s\n", fn);
return -1; return -1;
} }
switch(delsys){
case SYS_DVBC_ANNEX_A:
re = mci_set_channels(fd, freq, nchan, MOD_STANDARD_DVBC_8, 0, 0);
break;
re = mci_set_channels(fd, freq, nchan, MOD_STANDARD_DVBT_8, 0, 0); case SYS_DVBT:
re = mci_set_channels(fd, freq, nchan, MOD_STANDARD_DVBT_8, 0, 0);
break;
default:
re = -1;
}
close(fd); close(fd);
return re; return re;
} }
@ -971,15 +994,11 @@ int mci_set_stream( int fd, uint8_t stream, uint8_t channel, uint8_t standard,
uint8_t puncture_rate, uint8_t constellation, uint8_t puncture_rate, uint8_t constellation,
uint16_t cell_identifier) uint16_t cell_identifier)
{ {
struct mci_command msg_stream = { struct mci_command msg_stream;
.mod_command = MOD_SETUP_STREAM,
.mod_channel = 0,
.mod_stream = 0,
.mod_setup_stream = {
.standard = MOD_STANDARD_DVBC_8,
},
};
memset(&msg_stream,0,sizeof(msg_stream));
msg_stream.mod_command = MOD_SETUP_STREAM;
msg_stream.mod_channel = channel; msg_stream.mod_channel = channel;
msg_stream.mod_stream = stream; msg_stream.mod_stream = stream;
msg_stream.mod_setup_stream.standard = standard; msg_stream.mod_setup_stream.standard = standard;
@ -990,25 +1009,30 @@ int mci_set_stream( int fd, uint8_t stream, uint8_t channel, uint8_t standard,
msg_stream.mod_setup_stream.qam.modulation = modulation; msg_stream.mod_setup_stream.qam.modulation = modulation;
if (rolloff) if (rolloff)
msg_stream.mod_setup_stream.qam.rolloff = rolloff; msg_stream.mod_setup_stream.qam.rolloff = rolloff;
msg_stream.mod_setup_stream.ofdm.fft_size = fft_size; if (fft_size)
msg_stream.mod_setup_stream.ofdm.guard_interval = guard_interval; msg_stream.mod_setup_stream.ofdm.fft_size = fft_size;
msg_stream.mod_setup_stream.ofdm.puncture_rate = puncture_rate; if (guard_interval)
msg_stream.mod_setup_stream.ofdm.constellation = constellation; msg_stream.mod_setup_stream.ofdm.guard_interval = guard_interval;
if (puncture_rate)
msg_stream.mod_setup_stream.ofdm.puncture_rate = puncture_rate;
if (constellation)
msg_stream.mod_setup_stream.ofdm.constellation = constellation;
if (cell_identifier) if (cell_identifier)
msg_stream.mod_setup_stream.ofdm.cell_identifier = cell_identifier; msg_stream.mod_setup_stream.ofdm.cell_identifier = cell_identifier;
fprintf(stderr,"Setting DVBT Stream %d to channel %d\n",stream, channel); fprintf(stderr,"Setting DVB Stream %d to channel %d\n",stream, channel);
return mci_cmd(fd,&msg_stream); return mci_cmd(fd,&msg_stream);
} }
void set_dvbt_mods(int adapt, int chans, uint32_t start_freq, write_data *wd) void set_dvb_mods(int adapt, int chans, uint32_t start_freq,
enum fe_delivery_system delsys, write_data *wd)
{ {
if ((mci_set_output_simple(adapt, chans) < 0)|| if ((mci_set_output_simple(adapt, chans) < 0)||
(mci_set_channels_simple(adapt, start_freq, chans)< 0)) (mci_set_channels_simple(adapt, delsys, start_freq, chans)< 0))
{ {
fprintf(stderr,"Error setting up DVBT Modulator\n"); fprintf(stderr,"Error setting up DVB Modulator\n");
exit(1); exit(1);
} }
wd->chans = chans; wd->chans = chans;
@ -1019,16 +1043,29 @@ void set_dvbt_mods(int adapt, int chans, uint32_t start_freq, write_data *wd)
char *device; char *device;
int fd; int fd;
wd->tp[i].tpid = 1; // all the same transport stream id wd->tp[i].tpid = i;
wd->tp[i].delsys = SYS_DVBT; wd->tp[i].delsys = delsys;
wd->tp[i].freq = start_freq+8000000*i; wd->tp[i].freq = start_freq+8000000*i;
wd->tp[i].qam = 2;
wd->tp[i].symbolrate = 0;
wd->tp[i].bandwidth = 0;
wd->tp[i].guard = 0;
wd->tp[i].code_rate = 4;
wd->tp[i].trans_mode = MOD_STANDARD_DVBT_8;
switch(delsys){
case SYS_DVBT:
wd->tp[i].qam = 2;
wd->tp[i].symbolrate = 0;
wd->tp[i].bandwidth = 0;
wd->tp[i].guard = 0;
wd->tp[i].code_rate = 4;
wd->tp[i].trans_mode = MOD_STANDARD_DVBT_8;
break;
case SYS_DVBC_ANNEX_A:
wd->tp[i].qam = MOD_QAM_DVBC_256;
wd->tp[i].symbolrate = 6900000;
wd->tp[i].bandwidth = 0;
wd->tp[i].guard = 0;
wd->tp[i].code_rate = 0;
wd->tp[i].trans_mode = 0;
break;
}
device = malloc(sizeof(char)*40); device = malloc(sizeof(char)*40);
snprintf(device,35,"/dev/dvb/adapter%d/mod%d",adapt,i); snprintf(device,35,"/dev/dvb/adapter%d/mod%d",adapt,i);
fd = open(device, O_RDWR); fd = open(device, O_RDWR);
@ -1039,105 +1076,28 @@ void set_dvbt_mods(int adapt, int chans, uint32_t start_freq, write_data *wd)
exit(1); exit(1);
} }
mci_set_stream( fd, i, i, MOD_STANDARD_DVBT_8, 4, 0, 0, 0, 1, 0, 4, 2, 0); int re= 0;
close(fd); uint8_t stream_format = 4; //format is ransport stream
free(device); uint8_t fft_size = wd->tp[i].trans_mode;
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ switch(delsys){
case SYS_DVBC_ANNEX_A:
re = mci_set_stream( fd, i, i, MOD_STANDARD_DVBC_8,
stream_format, wd->tp[i].symbolrate,
wd->tp[i].qam, 0, 0, 0, 0, 0, 0);
break;
//++++++++++++++++++++++++++++++++DVBC MOD++++++++++++++++++++++++++++++++ case SYS_DVBT:
re = mci_set_stream( fd, i, i, MOD_STANDARD_DVBT_8,
static int set_property(int fd, uint32_t cmd, uint32_t data) stream_format, 0, 0,
{ 0, fft_size, wd->tp[i].guard,
struct dtv_property p; wd->tp[i].code_rate, wd->tp[i].qam,
struct dtv_properties c; 0);
int ret; break;
default:
p.cmd = cmd; re = -1;
c.num = 1;
c.props = &p;
p.u.data = data;
ret = ioctl(fd, FE_SET_PROPERTY, &c);
if (ret < 0) {
fprintf(stderr, "FE_SET_PROPERTY returned %d\n", errno);
return -1;
}
return 0;
}
static int set_input_bitrate(int fd, uint64_t data)
{
struct dtv_property p;
struct dtv_properties c;
int ret;
p.cmd = MODULATOR_INPUT_BITRATE;
c.num = 1;
c.props = &p;
p.u.data64 = data;
ret = ioctl(fd, FE_SET_PROPERTY, &c);
if (ret < 0) {
fprintf(stderr, "FE_SET_PROPERTY returned %d\n", errno);
return -1;
}
return 0;
}
void set_dvbc_mods(int adapt, int chans, uint32_t start_freq, write_data *wd)
{
uint32_t freq = start_freq;
uint8_t qam = QAM_256;
uint32_t sym = 6900000;
wd->chans = chans;
wd->fd_out = (int *)malloc(chans*sizeof(int));
memset(wd->fd_out,0,chans*sizeof(int));
for (int i = 0; i < chans; i++){
char *device;
int fd;
wd->tp[i].tpid = i;
wd->tp[i].delsys = SYS_DVBC_ANNEX_A;
wd->tp[i].freq = freq;
wd->tp[i].qam = qam;
wd->tp[i].symbolrate = sym;
wd->tp[i].bandwidth = 0;
wd->tp[i].guard = 0;
wd->tp[i].code_rate = 0;
wd->tp[i].trans_mode = 0;
device = malloc(sizeof(char)*40);
snprintf(device,35,"/dev/dvb/adapter%d/mod%d",adapt,i);
fd = open(device, O_RDWR);
if( fd < 0 )
{
fprintf(stderr,"Error opening %s : %s\n",device,strerror(errno));
free(device);
exit(1);
} }
if (set_property(fd, MODULATOR_FREQUENCY, freq) < 0){ if (re < 0) fprintf(stderr,"ERROR setting stream\n");
fprintf(stderr,"setting freq %d failed\n",freq);
exit(1);
}
if (set_property(fd, MODULATOR_MODULATION, qam) < 0){
fprintf(stderr,"setting qam %d failed\n",qam);
exit(1);
}
if (set_property(fd, MODULATOR_SYMBOL_RATE, sym) < 0){
fprintf(stderr,"setting sym %d failed\n",sym);
exit(1);
}
if (set_input_bitrate(fd, (DEFAULT_BIT_RATE_C << 32)) < 0){
fprintf(stderr,"setting bitrate %d failed\n",
(int)DEFAULT_BIT_RATE_C);
exit(1);
}
freq += 8000000;
close(fd); close(fd);
free(device); free(device);
} }
@ -1296,9 +1256,9 @@ int main(int argc, char **argv)
chans = ddevices.ndevs[adapt]; chans = ddevices.ndevs[adapt];
if (dvbt){ if (dvbt){
set_dvbt_mods(adapt, chans, start_freq, &wd); set_dvb_mods(adapt, chans, start_freq, SYS_DVBT, &wd);
} else { } else {
set_dvbc_mods(adapt, chans, start_freq, &wd); set_dvb_mods(adapt, chans, start_freq, SYS_DVBC_ANNEX_A, &wd);
} }
fprintf(stderr,"Reading from %s\n", filename); fprintf(stderr,"Reading from %s\n", filename);

View File

@ -237,6 +237,8 @@ static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot)
{ {
struct ddb_ci *ci = ca->data; struct ddb_ci *ci = ca->data;
write_creg(ci, 0x00, 0x01);
msleep(300);
write_creg(ci, 0x01, 0x01); write_creg(ci, 0x01, 0x01);
write_creg(ci, 0x04, 0x04); write_creg(ci, 0x04, 0x04);
msleep(300); msleep(300);

View File

@ -6,7 +6,7 @@
config DVB_MMAP config DVB_MMAP
bool "Enable DVB memory-mapped API (EXPERIMENTAL)" bool "Enable DVB memory-mapped API (EXPERIMENTAL)"
depends on DVB_CORE depends on DVB_CORE
depends on VIDEO_V4L2=y || VIDEO_V4L2=DVB_CORE depends on VIDEO_DEV=y || VIDEO_DEV=DVB_CORE
select VIDEOBUF2_VMALLOC select VIDEOBUF2_VMALLOC
help help
This option enables DVB experimental memory-mapped API, which This option enables DVB experimental memory-mapped API, which

View File

@ -6,8 +6,8 @@
dvb-net-$(CONFIG_DVB_NET) := dvb_net.o dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
dvb-vb2-$(CONFIG_DVB_MMAP) := dvb_vb2.o dvb-vb2-$(CONFIG_DVB_MMAP) := dvb_vb2.o
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
dvb_ca_en50221.o dvb_frontend.o \ dvb_ca_en50221.o dvb_frontend.o \
$(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) dvb_math.o $(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) dvb_math.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o obj-$(CONFIG_DVB_CORE) += dvb-core.o

View File

@ -4,7 +4,7 @@
dvb-net-$(CONFIG_DVB_NET) := dvb_net.o dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
dvb_ca_en50221.o dvb_frontend.o \ dvb_ca_en50221.o dvb_frontend.o \
$(dvb-net-y) dvb_ringbuffer.o dvb_math.o $(dvb-net-y) dvb_ringbuffer.o dvb_math.o

View File

@ -158,6 +158,12 @@ struct dvb_ca_private {
/* mutex serializing ioctls */ /* mutex serializing ioctls */
struct mutex ioctl_mutex; struct mutex ioctl_mutex;
/* A mutex used when a device is disconnected */
struct mutex remove_mutex;
/* Whether the device is disconnected */
int exit;
}; };
static void dvb_ca_private_free(struct dvb_ca_private *ca) static void dvb_ca_private_free(struct dvb_ca_private *ca)
@ -194,7 +200,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca);
static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
u8 *ebuf, int ecount); u8 *ebuf, int ecount);
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
u8 *ebuf, int ecount, u8 flags); u8 *ebuf, int ecount, int size_write_flag);
/** /**
* findstr - Safely find needle in haystack. * findstr - Safely find needle in haystack.
@ -785,18 +791,19 @@ exit:
* @buf: The data in this buffer is treated as a complete link-level packet to * @buf: The data in this buffer is treated as a complete link-level packet to
* be written. * be written.
* @bytes_write: Size of ebuf. * @bytes_write: Size of ebuf.
* @size_write_flag: A flag on Command Register which says whether the link size
* information will be writen or not.
* *
* return: Number of bytes written, or < 0 on error. * return: Number of bytes written, or < 0 on error.
*/ */
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
u8 *buf, int bytes_write, u8 flags) u8 *buf, int bytes_write, int size_write_flag)
{ {
struct dvb_ca_slot *sl = &ca->slot_info[slot]; struct dvb_ca_slot *sl = &ca->slot_info[slot];
int status; int status;
int i; int i;
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
flags=0;
/* sanity check */ /* sanity check */
if (bytes_write > sl->link_buf_size) if (bytes_write > sl->link_buf_size)
return -EINVAL; return -EINVAL;
@ -824,7 +831,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
/* OK, set HC bit */ /* OK, set HC bit */
status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
IRQEN | CMDREG_HC | flags); IRQEN | CMDREG_HC | size_write_flag);
if (status) if (status)
goto exit; goto exit;
@ -894,7 +901,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
buf[0], (buf[1] & 0x80) == 0, bytes_write); buf[0], (buf[1] & 0x80) == 0, bytes_write);
exit: exit:
ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | flags); ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
exitnowrite: exitnowrite:
return status; return status;
@ -1412,6 +1419,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
slot = array_index_nospec(slot, ca->slot_count); slot = array_index_nospec(slot, ca->slot_count);
#endif #endif
info->type = CA_CI_LINK; info->type = CA_CI_LINK;
info->flags = 0; info->flags = 0;
sl = &ca->slot_info[slot]; sl = &ca->slot_info[slot];
@ -1490,6 +1498,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
return -EFAULT; return -EFAULT;
buf += 2; buf += 2;
count -= 2; count -= 2;
if (slot >= ca->slot_count) if (slot >= ca->slot_count)
return -EINVAL; return -EINVAL;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
@ -1734,12 +1743,22 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
if (!try_module_get(ca->pub->owner)) mutex_lock(&ca->remove_mutex);
if (ca->exit) {
mutex_unlock(&ca->remove_mutex);
return -ENODEV;
}
if (!try_module_get(ca->pub->owner)) {
mutex_unlock(&ca->remove_mutex);
return -EIO; return -EIO;
}
err = dvb_generic_open(inode, file); err = dvb_generic_open(inode, file);
if (err < 0) { if (err < 0) {
module_put(ca->pub->owner); module_put(ca->pub->owner);
mutex_unlock(&ca->remove_mutex);
return err; return err;
} }
@ -1764,6 +1783,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
dvb_ca_private_get(ca); dvb_ca_private_get(ca);
mutex_unlock(&ca->remove_mutex);
return 0; return 0;
} }
@ -1783,6 +1803,8 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
mutex_lock(&ca->remove_mutex);
/* mark the CA device as closed */ /* mark the CA device as closed */
ca->open = 0; ca->open = 0;
dvb_ca_en50221_thread_update_delay(ca); dvb_ca_en50221_thread_update_delay(ca);
@ -1793,6 +1815,13 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
dvb_ca_private_put(ca); dvb_ca_private_put(ca);
if (dvbdev->users == 1 && ca->exit == 1) {
mutex_unlock(&ca->remove_mutex);
wake_up(&dvbdev->wait_queue);
} else {
mutex_unlock(&ca->remove_mutex);
}
return err; return err;
} }
@ -1920,6 +1949,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
} }
mutex_init(&ca->ioctl_mutex); mutex_init(&ca->ioctl_mutex);
mutex_init(&ca->remove_mutex);
if (signal_pending(current)) { if (signal_pending(current)) {
ret = -EINTR; ret = -EINTR;
@ -1962,6 +1992,14 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
mutex_lock(&ca->remove_mutex);
ca->exit = 1;
mutex_unlock(&ca->remove_mutex);
if (ca->dvbdev->users < 1)
wait_event(ca->dvbdev->wait_queue,
ca->dvbdev->users == 1);
/* shutdown the thread if there was one */ /* shutdown the thread if there was one */
kthread_stop(ca->thread); kthread_stop(ca->thread);

View File

@ -128,12 +128,12 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
cc = buf[3] & 0x0f; cc = buf[3] & 0x0f;
ccok = ((feed->cc + 1) & 0x0f) == cc; ccok = ((feed->cc + 1) & 0x0f) == cc;
feed->cc = cc;
if (!ccok) { if (!ccok) {
set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("missed packet: %d instead of %d!\n", dprintk_sect_loss("missed packet: %d instead of %d!\n",
cc, (feed->cc + 1) & 0x0f); cc, (feed->cc + 1) & 0x0f);
} }
feed->cc = cc;
if (buf[1] & 0x40) // PUSI ? if (buf[1] & 0x40) // PUSI ?
feed->peslen = 0xfffa; feed->peslen = 0xfffa;
@ -313,7 +313,6 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
cc = buf[3] & 0x0f; cc = buf[3] & 0x0f;
ccok = ((feed->cc + 1) & 0x0f) == cc; ccok = ((feed->cc + 1) & 0x0f) == cc;
feed->cc = cc;
if (buf[3] & 0x20) { if (buf[3] & 0x20) {
/* adaption field present, check for discontinuity_indicator */ /* adaption field present, check for discontinuity_indicator */
@ -349,6 +348,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
feed->pusi_seen = false; feed->pusi_seen = false;
dvb_dmx_swfilter_section_new(feed); dvb_dmx_swfilter_section_new(feed);
} }
feed->cc = cc;
if (buf[1] & 0x40) { if (buf[1] & 0x40) {
/* PUSI=1 (is set), section boundary is here */ /* PUSI=1 (is set), section boundary is here */

View File

@ -1,603 +0,0 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include "dvb_filter.h"
#if 0
static unsigned int bitrates[3][16] =
{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
#endif
static u32 freq[4] = {480, 441, 320, 0};
static unsigned int ac3_bitrates[32] =
{32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
0,0,0,0,0,0,0,0,0,0,0,0,0};
static u32 ac3_frames[3][32] =
{{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
{69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
{96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
#if 0
static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
void (*pes_write)(u8 *buf, int count, void *data),
void *priv)
{
dvb_filter_ipack_init(pa, IPACKS, pes_write);
dvb_filter_ipack_init(pv, IPACKS, pes_write);
pa->pid = pida;
pv->pid = pidv;
pa->data = priv;
pv->data = priv;
}
#endif
#if 0
static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
{
u8 off = 0;
if (!buf || !p ){
printk("NULL POINTER IDIOT\n");
return;
}
if (buf[1]&PAY_START) {
if (p->plength == MMAX_PLENGTH-6 && p->found>6){
p->plength = p->found-6;
p->found = 0;
send_ipack(p);
dvb_filter_ipack_reset(p);
}
}
if (buf[3] & ADAPT_FIELD) { // adaptation field?
off = buf[4] + 1;
if (off+4 > 187) return;
}
dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p);
}
#endif
#if 0
/* needs 5 byte input, returns picture coding type*/
static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr)
{
u8 pct;
if (pr) printk( "Pic header: ");
pic->temporal_reference[field] = (( headr[0] << 2 ) |
(headr[1] & 0x03) )& 0x03ff;
if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
pct = ( headr[1] >> 2 ) & 0x07;
pic->picture_coding_type[field] = pct;
if (pr) {
switch(pct){
case I_FRAME:
printk( " I-FRAME");
break;
case B_FRAME:
printk( " B-FRAME");
break;
case P_FRAME:
printk( " P-FRAME");
break;
}
}
pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) |
( (headr[3] & 0x1F) << 11) ) & 0xffff;
if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
((headr[4] & 0x80) >> 3);
if ( pct == B_FRAME ){
pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
}
if (pr) printk( " pic head param: 0x%x",
pic->picture_header_parameter);
return pct;
}
#endif
#if 0
/* needs 4 byte input */
static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
{
if (pr) printk("GOP header: ");
pic->time_code = (( headr[0] << 17 ) | ( headr[1] << 9) |
( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff;
if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F,
((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F),
((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F));
if ( ( headr[3] & 0x40 ) != 0 ){
pic->closed_gop = 1;
} else {
pic->closed_gop = 0;
}
if (pr) printk("closed: %d", pic->closed_gop);
if ( ( headr[3] & 0x20 ) != 0 ){
pic->broken_link = 1;
} else {
pic->broken_link = 0;
}
if (pr) printk(" broken: %d\n", pic->broken_link);
return 0;
}
#endif
#if 0
/* needs 8 byte input */
static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
{
int sw;
int form = -1;
if (pr) printk("Reading sequence header\n");
vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]);
sw = (int)((headr[3]&0xF0) >> 4) ;
switch( sw ){
case 1:
if (pr)
printk("Videostream: ASPECT: 1:1");
vi->aspect_ratio = 100;
break;
case 2:
if (pr)
printk("Videostream: ASPECT: 4:3");
vi->aspect_ratio = 133;
break;
case 3:
if (pr)
printk("Videostream: ASPECT: 16:9");
vi->aspect_ratio = 177;
break;
case 4:
if (pr)
printk("Videostream: ASPECT: 2.21:1");
vi->aspect_ratio = 221;
break;
case 5 ... 15:
if (pr)
printk("Videostream: ASPECT: reserved");
vi->aspect_ratio = 0;
break;
default:
vi->aspect_ratio = 0;
return -1;
}
if (pr)
printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size);
sw = (int)(headr[3]&0x0F);
switch ( sw ) {
case 1:
if (pr)
printk(" FRate: 23.976 fps");
vi->framerate = 23976;
form = -1;
break;
case 2:
if (pr)
printk(" FRate: 24 fps");
vi->framerate = 24000;
form = -1;
break;
case 3:
if (pr)
printk(" FRate: 25 fps");
vi->framerate = 25000;
form = VIDEO_MODE_PAL;
break;
case 4:
if (pr)
printk(" FRate: 29.97 fps");
vi->framerate = 29970;
form = VIDEO_MODE_NTSC;
break;
case 5:
if (pr)
printk(" FRate: 30 fps");
vi->framerate = 30000;
form = VIDEO_MODE_NTSC;
break;
case 6:
if (pr)
printk(" FRate: 50 fps");
vi->framerate = 50000;
form = VIDEO_MODE_PAL;
break;
case 7:
if (pr)
printk(" FRate: 60 fps");
vi->framerate = 60000;
form = VIDEO_MODE_NTSC;
break;
}
vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
vi->vbv_buffer_size
= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
if (pr){
printk(" BRate: %d Mbit/s",4*(vi->bit_rate)/10000);
printk(" vbvbuffer %d",16*1024*(vi->vbv_buffer_size));
printk("\n");
}
vi->video_format = form;
return 0;
}
#endif
#if 0
static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr)
{
u8 *headr;
int found = 0;
int c = 0;
while (found < 4 && c+4 < count){
u8 *b;
b = mbuf+c;
if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
&& b[3] == 0xb3) found = 4;
else {
c++;
}
}
if (! found) return -1;
c += 4;
if (c+12 >= count) return -1;
headr = mbuf+c;
if (read_sequence_header(headr, vi, pr) < 0) return -1;
vi->off = c-4;
return 0;
}
#endif
#if 0
static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
{
u8 *headr;
int found = 0;
int c = 0;
int fr = 0;
while (found < 2 && c < count){
u8 b[2];
memcpy( b, mbuf+c, 2);
if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
found = 2;
else {
c++;
}
}
if (!found) return -1;
if (c+3 >= count) return -1;
headr = mbuf+c;
ai->layer = (headr[1] & 0x06) >> 1;
if (pr)
printk("Audiostream: Layer: %d", 4-ai->layer);
ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
if (pr){
if (ai->bit_rate == 0)
printk(" Bit rate: free");
else if (ai->bit_rate == 0xf)
printk(" BRate: reserved");
else
printk(" BRate: %d kb/s", ai->bit_rate/1000);
}
fr = (headr[2] & 0x0c ) >> 2;
ai->frequency = freq[fr]*100;
if (pr){
if (ai->frequency == 3)
printk(" Freq: reserved\n");
else
printk(" Freq: %d kHz\n",ai->frequency);
}
ai->off = c;
return 0;
}
#endif
int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
{
u8 *headr;
int found = 0;
int c = 0;
u8 frame = 0;
int fr = 0;
while ( !found && c < count){
u8 *b = mbuf+c;
if ( b[0] == 0x0b && b[1] == 0x77 )
found = 1;
else {
c++;
}
}
if (!found) return -1;
if (pr)
printk("Audiostream: AC3");
ai->off = c;
if (c+5 >= count) return -1;
ai->layer = 0; // 0 for AC3
headr = mbuf+c+2;
frame = (headr[2]&0x3f);
ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
if (pr)
printk(" BRate: %d kb/s", (int) ai->bit_rate/1000);
ai->frequency = (headr[2] & 0xc0 ) >> 6;
fr = (headr[2] & 0xc0 ) >> 6;
ai->frequency = freq[fr]*100;
if (pr) printk (" Freq: %d Hz\n", (int) ai->frequency);
ai->framesize = ac3_frames[fr][frame >> 1];
if ((frame & 1) && (fr == 1)) ai->framesize++;
ai->framesize = ai->framesize << 1;
if (pr) printk (" Framesize %d\n",(int) ai->framesize);
return 0;
}
EXPORT_SYMBOL(dvb_filter_get_ac3info);
#if 0
static u8 *skip_pes_header(u8 **bufp)
{
u8 *inbuf = *bufp;
u8 *buf = inbuf;
u8 *pts = NULL;
int skip = 0;
static const int mpeg1_skip_table[16] = {
1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
};
if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
if (buf[7] & PTS_ONLY)
pts = buf+9;
else pts = NULL;
buf = inbuf + 9 + inbuf[8];
} else { /* mpeg1 */
for (buf = inbuf + 6; *buf == 0xff; buf++)
if (buf == inbuf + 6 + 16) {
break;
}
if ((*buf & 0xc0) == 0x40)
buf += 2;
skip = mpeg1_skip_table [*buf >> 4];
if (skip == 5 || skip == 10) pts = buf;
else pts = NULL;
buf += mpeg1_skip_table [*buf >> 4];
}
*bufp = buf;
return pts;
}
#endif
#if 0
static void initialize_quant_matrix( u32 *matrix )
{
int i;
matrix[0] = 0x08101013;
matrix[1] = 0x10131616;
matrix[2] = 0x16161616;
matrix[3] = 0x1a181a1b;
matrix[4] = 0x1b1b1a1a;
matrix[5] = 0x1a1a1b1b;
matrix[6] = 0x1b1d1d1d;
matrix[7] = 0x2222221d;
matrix[8] = 0x1d1d1b1b;
matrix[9] = 0x1d1d2020;
matrix[10] = 0x22222526;
matrix[11] = 0x25232322;
matrix[12] = 0x23262628;
matrix[13] = 0x28283030;
matrix[14] = 0x2e2e3838;
matrix[15] = 0x3a454553;
for ( i = 16 ; i < 32 ; i++ )
matrix[i] = 0x10101010;
}
#endif
#if 0
static void initialize_mpg_picture(struct mpg_picture *pic)
{
int i;
/* set MPEG1 */
pic->mpeg1_flag = 1;
pic->profile_and_level = 0x4A ; /* MP@LL */
pic->progressive_sequence = 1;
pic->low_delay = 0;
pic->sequence_display_extension_flag = 0;
for ( i = 0 ; i < 4 ; i++ ){
pic->frame_centre_horizontal_offset[i] = 0;
pic->frame_centre_vertical_offset[i] = 0;
}
pic->last_frame_centre_horizontal_offset = 0;
pic->last_frame_centre_vertical_offset = 0;
pic->picture_display_extension_flag[0] = 0;
pic->picture_display_extension_flag[1] = 0;
pic->sequence_header_flag = 0;
pic->gop_flag = 0;
pic->sequence_end_flag = 0;
}
#endif
#if 0
static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic )
{
int16_t last_h_offset;
int16_t last_v_offset;
int16_t *p_h_offset;
int16_t *p_v_offset;
if ( pic->mpeg1_flag ){
pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE;
pic->top_field_first = 0;
pic->repeat_first_field = 0;
pic->progressive_frame = 1;
pic->picture_coding_parameter = 0x000010;
}
/* Reset flag */
pic->picture_display_extension_flag[field_type] = 0;
last_h_offset = pic->last_frame_centre_horizontal_offset;
last_v_offset = pic->last_frame_centre_vertical_offset;
if ( field_type == FIRST_FIELD ){
p_h_offset = pic->frame_centre_horizontal_offset;
p_v_offset = pic->frame_centre_vertical_offset;
*p_h_offset = last_h_offset;
*(p_h_offset + 1) = last_h_offset;
*(p_h_offset + 2) = last_h_offset;
*p_v_offset = last_v_offset;
*(p_v_offset + 1) = last_v_offset;
*(p_v_offset + 2) = last_v_offset;
} else {
pic->frame_centre_horizontal_offset[3] = last_h_offset;
pic->frame_centre_vertical_offset[3] = last_v_offset;
}
}
#endif
#if 0
static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type)
{
pic->picture_header = 0;
pic->sequence_header_data
= ( INIT_HORIZONTAL_SIZE << 20 )
| ( INIT_VERTICAL_SIZE << 8 )
| ( INIT_ASPECT_RATIO << 4 )
| ( INIT_FRAME_RATE );
pic->mpeg1_flag = 0;
pic->vinfo.horizontal_size
= INIT_DISP_HORIZONTAL_SIZE;
pic->vinfo.vertical_size
= INIT_DISP_VERTICAL_SIZE;
pic->picture_display_extension_flag[field_type]
= 0;
pic->pts_flag[field_type] = 0;
pic->sequence_gop_header = 0;
pic->picture_header = 0;
pic->sequence_header_flag = 0;
pic->gop_flag = 0;
pic->sequence_end_flag = 0;
pic->sequence_display_extension_flag = 0;
pic->last_frame_centre_horizontal_offset = 0;
pic->last_frame_centre_vertical_offset = 0;
pic->channel = chan;
}
#endif
void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
dvb_filter_pes2ts_cb_t *cb, void *priv)
{
unsigned char *buf=p2ts->buf;
buf[0]=0x47;
buf[1]=(pid>>8);
buf[2]=pid&0xff;
p2ts->cc=0;
p2ts->cb=cb;
p2ts->priv=priv;
}
EXPORT_SYMBOL(dvb_filter_pes2ts_init);
int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
int len, int payload_start)
{
unsigned char *buf=p2ts->buf;
int ret=0, rest;
//len=6+((pes[4]<<8)|pes[5]);
if (payload_start)
buf[1]|=0x40;
else
buf[1]&=~0x40;
while (len>=184) {
buf[3]=0x10|((p2ts->cc++)&0x0f);
memcpy(buf+4, pes, 184);
if ((ret=p2ts->cb(p2ts->priv, buf)))
return ret;
len-=184; pes+=184;
buf[1]&=~0x40;
}
if (!len)
return 0;
buf[3]=0x30|((p2ts->cc++)&0x0f);
rest=183-len;
if (rest) {
buf[5]=0x00;
if (rest-1)
memset(buf+6, 0xff, rest-1);
}
buf[4]=rest;
memcpy(buf+5+rest, pes, len);
return p2ts->cb(p2ts->priv, buf);
}
EXPORT_SYMBOL(dvb_filter_pes2ts);

View File

@ -299,14 +299,22 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
} }
if (events->eventw == events->eventr) { if (events->eventw == events->eventr) {
int ret; struct wait_queue_entry wait;
int ret = 0;
if (flags & O_NONBLOCK) if (flags & O_NONBLOCK)
return -EWOULDBLOCK; return -EWOULDBLOCK;
ret = wait_event_interruptible(events->wait_queue, init_waitqueue_entry(&wait, current);
dvb_frontend_test_event(fepriv, events)); add_wait_queue(&events->wait_queue, &wait);
while (!dvb_frontend_test_event(fepriv, events)) {
wait_woken(&wait, TASK_INTERRUPTIBLE, 0);
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
}
remove_wait_queue(&events->wait_queue, &wait);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }

View File

@ -665,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);
@ -995,8 +995,8 @@ static void dvb_net_sec(struct net_device *dev,
} }
static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_net_sec_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, u32 *buffer_flags) struct dmx_section_filter *filter, u32 *buffer_flags)
{ {
struct net_device *dev = filter->priv; struct net_device *dev = filter->priv;
@ -1290,6 +1290,7 @@ static int dvb_net_set_mac (struct net_device *dev, void *p)
#else #else
eth_hw_addr_set(dev, addr->sa_data); eth_hw_addr_set(dev, addr->sa_data);
#endif #endif
if (netif_running(dev)) if (netif_running(dev))
schedule_work(&priv->restart_net_feed_wq); schedule_work(&priv->restart_net_feed_wq);
@ -1589,15 +1590,43 @@ static long dvb_net_ioctl(struct file *file,
return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl); return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
} }
static int locked_dvb_net_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_net *dvbnet = dvbdev->priv;
int ret;
if (mutex_lock_interruptible(&dvbnet->remove_mutex))
return -ERESTARTSYS;
if (dvbnet->exit) {
mutex_unlock(&dvbnet->remove_mutex);
return -ENODEV;
}
ret = dvb_generic_open(inode, file);
mutex_unlock(&dvbnet->remove_mutex);
return ret;
}
static int dvb_net_close(struct inode *inode, struct file *file) static int dvb_net_close(struct inode *inode, struct file *file)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dvb_net *dvbnet = dvbdev->priv; struct dvb_net *dvbnet = dvbdev->priv;
mutex_lock(&dvbnet->remove_mutex);
dvb_generic_release(inode, file); dvb_generic_release(inode, file);
if(dvbdev->users == 1 && dvbnet->exit == 1) if (dvbdev->users == 1 && dvbnet->exit == 1) {
mutex_unlock(&dvbnet->remove_mutex);
wake_up(&dvbdev->wait_queue); wake_up(&dvbdev->wait_queue);
} else {
mutex_unlock(&dvbnet->remove_mutex);
}
return 0; return 0;
} }
@ -1605,7 +1634,7 @@ static int dvb_net_close(struct inode *inode, struct file *file)
static const struct file_operations dvb_net_fops = { static const struct file_operations dvb_net_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.unlocked_ioctl = dvb_net_ioctl, .unlocked_ioctl = dvb_net_ioctl,
.open = dvb_generic_open, .open = locked_dvb_net_open,
.release = dvb_net_close, .release = dvb_net_close,
.llseek = noop_llseek, .llseek = noop_llseek,
}; };
@ -1624,10 +1653,13 @@ void dvb_net_release (struct dvb_net *dvbnet)
{ {
int i; int i;
mutex_lock(&dvbnet->remove_mutex);
dvbnet->exit = 1; dvbnet->exit = 1;
mutex_unlock(&dvbnet->remove_mutex);
if (dvbnet->dvbdev->users < 1) if (dvbnet->dvbdev->users < 1)
wait_event(dvbnet->dvbdev->wait_queue, wait_event(dvbnet->dvbdev->wait_queue,
dvbnet->dvbdev->users==1); dvbnet->dvbdev->users == 1);
dvb_unregister_device(dvbnet->dvbdev); dvb_unregister_device(dvbnet->dvbdev);
@ -1646,6 +1678,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
int i; int i;
mutex_init(&dvbnet->ioctl_mutex); mutex_init(&dvbnet->ioctl_mutex);
mutex_init(&dvbnet->remove_mutex);
dvbnet->demux = dmx; dvbnet->demux = dmx;
for (i=0; i<DVB_NET_DEVICES_MAX; i++) for (i=0; i<DVB_NET_DEVICES_MAX; i++)

View File

@ -30,6 +30,7 @@
#endif #endif
static DEFINE_MUTEX(dvbdev_mutex); static DEFINE_MUTEX(dvbdev_mutex);
static LIST_HEAD(dvbdevfops_list);
static int dvbdev_debug; static int dvbdev_debug;
module_param(dvbdev_debug, int, 0644); module_param(dvbdev_debug, int, 0644);
@ -83,9 +84,9 @@ static const u8 minor_type[] = {
}; };
#define nums2minor(num, type, id) \ #define nums2minor(num, type, id) \
(((num) << 6) | ((id) << 4) | minor_type[type]) (((num) << 6) | ((id) << 4) | minor_type[type])
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS * 64)
#endif #endif
static struct class *dvb_class; static struct class *dvb_class;
@ -122,9 +123,7 @@ fail:
return -ENODEV; return -ENODEV;
} }
static const struct file_operations dvb_device_fops = {
static const struct file_operations dvb_device_fops =
{
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = dvb_device_open, .open = dvb_device_open,
.llseek = noop_llseek, .llseek = noop_llseek,
@ -157,7 +156,6 @@ int dvb_generic_open(struct inode *inode, struct file *file)
} }
EXPORT_SYMBOL(dvb_generic_open); EXPORT_SYMBOL(dvb_generic_open);
int dvb_generic_release(struct inode *inode, struct file *file) int dvb_generic_release(struct inode *inode, struct file *file)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
@ -165,11 +163,10 @@ int dvb_generic_release(struct inode *inode, struct file *file)
if (!dvbdev) if (!dvbdev)
return -ENODEV; return -ENODEV;
if ((file->f_flags & O_ACCMODE) == O_RDONLY) { if ((file->f_flags & O_ACCMODE) == O_RDONLY)
dvbdev->readers++; dvbdev->readers++;
} else { else
dvbdev->writers++; dvbdev->writers++;
}
dvbdev->users++; dvbdev->users++;
@ -179,7 +176,6 @@ int dvb_generic_release(struct inode *inode, struct file *file)
} }
EXPORT_SYMBOL(dvb_generic_release); EXPORT_SYMBOL(dvb_generic_release);
long dvb_generic_ioctl(struct file *file, long dvb_generic_ioctl(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
@ -195,13 +191,13 @@ long dvb_generic_ioctl(struct file *file,
} }
EXPORT_SYMBOL(dvb_generic_ioctl); EXPORT_SYMBOL(dvb_generic_ioctl);
static int dvbdev_get_free_id(struct dvb_adapter *adap, int type)
static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
{ {
u32 id = 0; u32 id = 0;
while (id < DVB_MAX_IDS) { while (id < DVB_MAX_IDS) {
struct dvb_device *dev; struct dvb_device *dev;
list_for_each_entry(dev, &adap->device_list, list_head) list_for_each_entry(dev, &adap->device_list, list_head)
if (dev->type == type && dev->id == id) if (dev->type == type && dev->id == id)
goto skip; goto skip;
@ -255,7 +251,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
#if defined(CONFIG_MEDIA_CONTROLLER_DVB) #if defined(CONFIG_MEDIA_CONTROLLER_DVB)
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; int i;
@ -397,7 +393,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
static int dvb_register_media_device(struct dvb_device *dvbdev, static int dvb_register_media_device(struct dvb_device *dvbdev,
int type, int minor, int type, int minor,
unsigned demux_sink_pads) unsigned int demux_sink_pads)
{ {
#if defined(CONFIG_MEDIA_CONTROLLER_DVB) #if defined(CONFIG_MEDIA_CONTROLLER_DVB)
struct media_link *link; struct media_link *link;
@ -464,14 +460,16 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
enum dvb_device_type type, int demux_sink_pads) enum dvb_device_type type, int demux_sink_pads)
{ {
struct dvb_device *dvbdev; struct dvb_device *dvbdev;
struct file_operations *dvbdevfops; struct file_operations *dvbdevfops = NULL;
struct dvbdevfops_node *node = NULL, *new_node = NULL;
struct device *clsdev; struct device *clsdev;
int minor; int minor;
int id, ret; int id, ret;
mutex_lock(&dvbdev_register_lock); mutex_lock(&dvbdev_register_lock);
if ((id = dvbdev_get_free_id (adap, type)) < 0){ id = dvbdev_get_free_id(adap, type);
if (id < 0) {
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
*pdvbdev = NULL; *pdvbdev = NULL;
pr_err("%s: couldn't find free device id\n", __func__); pr_err("%s: couldn't find free device id\n", __func__);
@ -479,18 +477,44 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
} }
*pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
if (!dvbdev) {
if (!dvbdev){
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
return -ENOMEM; return -ENOMEM;
} }
dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL); /*
* When a device of the same type is probe()d more than once,
* the first allocated fops are used. This prevents memory leaks
* that can occur when the same device is probe()d repeatedly.
*/
list_for_each_entry(node, &dvbdevfops_list, list_head) {
if (node->fops->owner == adap->module &&
node->type == type && node->template == template) {
dvbdevfops = node->fops;
break;
}
}
if (!dvbdevfops){ if (!dvbdevfops) {
kfree (dvbdev); dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
mutex_unlock(&dvbdev_register_lock); if (!dvbdevfops) {
return -ENOMEM; kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock);
return -ENOMEM;
}
new_node = kzalloc(sizeof(*new_node), GFP_KERNEL);
if (!new_node) {
kfree(dvbdevfops);
kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock);
return -ENOMEM;
}
new_node->fops = dvbdevfops;
new_node->type = type;
new_node->template = template;
list_add_tail(&new_node->list_head, &dvbdevfops_list);
} }
memcpy(dvbdev, template, sizeof(struct dvb_device)); memcpy(dvbdev, template, sizeof(struct dvb_device));
@ -500,21 +524,21 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
dvbdev->adapter = adap; dvbdev->adapter = adap;
dvbdev->priv = priv; dvbdev->priv = priv;
dvbdev->fops = dvbdevfops; dvbdev->fops = dvbdevfops;
init_waitqueue_head (&dvbdev->wait_queue); init_waitqueue_head(&dvbdev->wait_queue);
dvbdevfops->owner = adap->module; dvbdevfops->owner = adap->module;
list_add_tail(&dvbdev->list_head, &adap->device_list);
list_add_tail (&dvbdev->list_head, &adap->device_list);
down_write(&minor_rwsem); down_write(&minor_rwsem);
#ifdef CONFIG_DVB_DYNAMIC_MINORS #ifdef CONFIG_DVB_DYNAMIC_MINORS
for (minor = 0; minor < MAX_DVB_MINORS; minor++) for (minor = 0; minor < MAX_DVB_MINORS; minor++)
if (dvb_minors[minor] == NULL) if (!dvb_minors[minor])
break; break;
if (minor == MAX_DVB_MINORS) { if (minor == MAX_DVB_MINORS) {
list_del (&dvbdev->list_head); if (new_node) {
kfree(dvbdevfops); list_del(&new_node->list_head);
kfree(dvbdevfops);
kfree(new_node);
}
list_del(&dvbdev->list_head);
kfree(dvbdev); kfree(dvbdev);
up_write(&minor_rwsem); up_write(&minor_rwsem);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
@ -523,46 +547,51 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
#else #else
minor = nums2minor(adap->num, type, id); minor = nums2minor(adap->num, type, id);
#endif #endif
dvbdev->minor = minor; dvbdev->minor = minor;
dvb_minors[minor] = dvb_device_get(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);
if (ret) { if (ret) {
pr_err("%s: dvb_register_media_device failed to create the mediagraph\n", pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
__func__); __func__);
if (new_node) {
list_del(&new_node->list_head);
kfree(dvbdevfops);
kfree(new_node);
}
dvb_media_device_free(dvbdev); dvb_media_device_free(dvbdev);
list_del (&dvbdev->list_head); list_del(&dvbdev->list_head);
kfree(dvbdevfops);
kfree(dvbdev); kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
return ret; return ret;
} }
mutex_unlock(&dvbdev_register_lock);
clsdev = device_create(dvb_class, adap->device, clsdev = device_create(dvb_class, adap->device,
MKDEV(DVB_MAJOR, minor), MKDEV(DVB_MAJOR, minor),
dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) { if (IS_ERR(clsdev)) {
pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n", pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
if (new_node) {
list_del(&new_node->list_head);
kfree(dvbdevfops);
kfree(new_node);
}
dvb_media_device_free(dvbdev); dvb_media_device_free(dvbdev);
list_del (&dvbdev->list_head); list_del(&dvbdev->list_head);
kfree(dvbdevfops);
kfree(dvbdev); kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock);
return PTR_ERR(clsdev); return PTR_ERR(clsdev);
} }
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
adap->num, dnames[type], id, minor, minor); adap->num, dnames[type], id, minor, minor);
mutex_unlock(&dvbdev_register_lock);
return 0; return 0;
} }
EXPORT_SYMBOL(dvb_register_device); EXPORT_SYMBOL(dvb_register_device);
void dvb_remove_device(struct dvb_device *dvbdev) void dvb_remove_device(struct dvb_device *dvbdev)
{ {
if (!dvbdev) if (!dvbdev)
@ -577,20 +606,17 @@ void dvb_remove_device(struct dvb_device *dvbdev)
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
list_del (&dvbdev->list_head); list_del(&dvbdev->list_head);
} }
EXPORT_SYMBOL(dvb_remove_device); EXPORT_SYMBOL(dvb_remove_device);
static void dvb_free_device(struct kref *ref) static void dvb_free_device(struct kref *ref)
{ {
struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref); struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
kfree (dvbdev->fops); kfree(dvbdev);
kfree (dvbdev);
} }
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev) struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
{ {
kref_get(&dvbdev->ref); kref_get(&dvbdev->ref);
@ -598,14 +624,12 @@ struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
} }
EXPORT_SYMBOL(dvb_device_get); EXPORT_SYMBOL(dvb_device_get);
void dvb_device_put(struct dvb_device *dvbdev) void dvb_device_put(struct dvb_device *dvbdev)
{ {
if (dvbdev) if (dvbdev)
kref_put(&dvbdev->ref, dvb_free_device); 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);
@ -613,7 +637,6 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
} }
EXPORT_SYMBOL(dvb_unregister_device); EXPORT_SYMBOL(dvb_unregister_device);
#ifdef CONFIG_MEDIA_CONTROLLER_DVB #ifdef CONFIG_MEDIA_CONTROLLER_DVB
static int dvb_create_io_intf_links(struct dvb_adapter *adap, static int dvb_create_io_intf_links(struct dvb_adapter *adap,
@ -646,9 +669,9 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
struct media_entity *demux = NULL, *ca = NULL; struct media_entity *demux = NULL, *ca = NULL;
struct media_link *link; struct media_link *link;
struct media_interface *intf; struct media_interface *intf;
unsigned demux_pad = 0; unsigned int demux_pad = 0;
unsigned dvr_pad = 0; unsigned int dvr_pad = 0;
unsigned ntuner = 0, ndemod = 0; unsigned int ntuner = 0, ndemod = 0;
int ret, pad_source, pad_sink; int ret, pad_source, pad_sink;
static const char *connector_name = "Television"; static const char *connector_name = "Television";
@ -719,7 +742,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
false); false);
} else { } else {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0))
pad_sink = media_get_pad_index(tuner, true, pad_sink = media_get_pad_index(tuner, MEDIA_PAD_FL_SINK,
PAD_SIGNAL_ANALOG); PAD_SIGNAL_ANALOG);
if (pad_sink < 0) if (pad_sink < 0)
return -EINVAL; return -EINVAL;
@ -741,7 +764,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
if (ntuner && ndemod) { if (ntuner && ndemod) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0))
/* NOTE: first found tuner source pad presumed correct */ /* NOTE: first found tuner source pad presumed correct */
pad_source = media_get_pad_index(tuner, false, pad_source = media_get_pad_index(tuner, MEDIA_PAD_FL_SOURCE,
PAD_SIGNAL_ANALOG); PAD_SIGNAL_ANALOG);
if (pad_source < 0) if (pad_source < 0)
return -EINVAL; return -EINVAL;
@ -781,18 +804,18 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
media_device_for_each_entity(entity, mdev) { media_device_for_each_entity(entity, mdev) {
if (entity->function == MEDIA_ENT_F_IO_DTV) { if (entity->function == MEDIA_ENT_F_IO_DTV) {
if (!strncmp(entity->name, DVR_TSOUT, if (!strncmp(entity->name, DVR_TSOUT,
strlen(DVR_TSOUT))) { strlen(DVR_TSOUT))) {
ret = media_create_pad_link(demux, ret = media_create_pad_link(demux,
++dvr_pad, ++dvr_pad,
entity, 0, 0); entity, 0, 0);
if (ret) if (ret)
return ret; return ret;
} }
if (!strncmp(entity->name, DEMUX_TSOUT, if (!strncmp(entity->name, DEMUX_TSOUT,
strlen(DEMUX_TSOUT))) { strlen(DEMUX_TSOUT))) {
ret = media_create_pad_link(demux, ret = media_create_pad_link(demux,
++demux_pad, ++demux_pad,
entity, 0, 0); entity, 0, 0);
if (ret) if (ret)
return ret; return ret;
} }
@ -850,8 +873,10 @@ EXPORT_SYMBOL_GPL(dvb_create_media_graph);
static int dvbdev_check_free_adapter_num(int num) static int dvbdev_check_free_adapter_num(int num)
{ {
struct list_head *entry; struct list_head *entry;
list_for_each(entry, &dvb_adapter_list) { list_for_each(entry, &dvb_adapter_list) {
struct dvb_adapter *adap; struct dvb_adapter *adap;
adap = list_entry(entry, struct dvb_adapter, list_head); adap = list_entry(entry, struct dvb_adapter, list_head);
if (adap->num == num) if (adap->num == num)
return 0; return 0;
@ -859,7 +884,7 @@ static int dvbdev_check_free_adapter_num(int num)
return 1; return 1;
} }
static int dvbdev_get_free_adapter_num (void) static int dvbdev_get_free_adapter_num(void)
{ {
int num = 0; int num = 0;
@ -872,7 +897,6 @@ static int dvbdev_get_free_adapter_num (void)
return -ENFILE; return -ENFILE;
} }
int dvb_register_adapter(struct dvb_adapter *adap, const char *name, int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
struct module *module, struct device *device, struct module *module, struct device *device,
short *adapter_nums) short *adapter_nums)
@ -899,8 +923,8 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
return -ENFILE; return -ENFILE;
} }
memset (adap, 0, sizeof(struct dvb_adapter)); memset(adap, 0, sizeof(struct dvb_adapter));
INIT_LIST_HEAD (&adap->device_list); INIT_LIST_HEAD(&adap->device_list);
pr_info("DVB: registering new adapter (%s)\n", name); pr_info("DVB: registering new adapter (%s)\n", name);
@ -910,13 +934,13 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
adap->device = device; adap->device = device;
adap->mfe_shared = 0; adap->mfe_shared = 0;
adap->mfe_dvbdev = NULL; adap->mfe_dvbdev = NULL;
mutex_init (&adap->mfe_lock); mutex_init(&adap->mfe_lock);
#ifdef CONFIG_MEDIA_CONTROLLER_DVB #ifdef CONFIG_MEDIA_CONTROLLER_DVB
mutex_init(&adap->mdev_lock); mutex_init(&adap->mdev_lock);
#endif #endif
list_add_tail (&adap->list_head, &dvb_adapter_list); list_add_tail(&adap->list_head, &dvb_adapter_list);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
@ -924,25 +948,26 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
} }
EXPORT_SYMBOL(dvb_register_adapter); EXPORT_SYMBOL(dvb_register_adapter);
int dvb_unregister_adapter(struct dvb_adapter *adap) int dvb_unregister_adapter(struct dvb_adapter *adap)
{ {
mutex_lock(&dvbdev_register_lock); mutex_lock(&dvbdev_register_lock);
list_del (&adap->list_head); list_del(&adap->list_head);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
return 0; return 0;
} }
EXPORT_SYMBOL(dvb_unregister_adapter); EXPORT_SYMBOL(dvb_unregister_adapter);
/* if the miracle happens and "generic_usercopy()" is included into /*
the kernel, then this can vanish. please don't make the mistake and * if the miracle happens and "generic_usercopy()" is included into
define this as video_usercopy(). this will introduce a dependency * the kernel, then this can vanish. please don't make the mistake and
to the v4l "videodev.o" module, which is unnecessary for some * define this as video_usercopy(). this will introduce a dependency
cards (ie. the budget dvb-cards don't need the v4l module...) */ * to the v4l "videodev.o" module, which is unnecessary for some
* cards (ie. the budget dvb-cards don't need the v4l module...)
*/
int dvb_usercopy(struct file *file, int dvb_usercopy(struct file *file,
unsigned int cmd, unsigned long arg, unsigned int cmd, unsigned long arg,
int (*func)(struct file *file, int (*func)(struct file *file,
unsigned int cmd, void *arg)) unsigned int cmd, void *arg))
{ {
char sbuf[128]; char sbuf[128];
void *mbuf = NULL; void *mbuf = NULL;
@ -956,7 +981,7 @@ int dvb_usercopy(struct file *file,
* For this command, the pointer is actually an integer * For this command, the pointer is actually an integer
* argument. * argument.
*/ */
parg = (void *) arg; parg = (void *)arg;
break; break;
case _IOC_READ: /* some v4l ioctls are marked wrong ... */ case _IOC_READ: /* some v4l ioctls are marked wrong ... */
case _IOC_WRITE: case _IOC_WRITE:
@ -966,7 +991,7 @@ int dvb_usercopy(struct file *file,
} else { } else {
/* too big to allocate from stack */ /* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
if (NULL == mbuf) if (!mbuf)
return -ENOMEM; return -ENOMEM;
parg = mbuf; parg = mbuf;
} }
@ -978,15 +1003,15 @@ int dvb_usercopy(struct file *file,
} }
/* call driver */ /* call driver */
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) err = func(file, cmd, parg);
if (err == -ENOIOCTLCMD)
err = -ENOTTY; err = -ENOTTY;
if (err < 0) if (err < 0)
goto out; goto out;
/* Copy results into user buffer */ /* Copy results into user buffer */
switch (_IOC_DIR(cmd)) switch (_IOC_DIR(cmd)) {
{
case _IOC_READ: case _IOC_READ:
case (_IOC_WRITE | _IOC_READ): case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
@ -998,7 +1023,6 @@ out:
kfree(mbuf); kfree(mbuf);
return err; return err;
} }
EXPORT_SYMBOL(dvb_usercopy);
#if IS_ENABLED(CONFIG_I2C) #if IS_ENABLED(CONFIG_I2C)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0))
@ -1083,13 +1107,15 @@ static int __init init_dvbdev(void)
int retval; int retval;
dev_t dev = MKDEV(DVB_MAJOR, 0); dev_t dev = MKDEV(DVB_MAJOR, 0);
if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB");
if (retval != 0) {
pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR); pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR);
return retval; return retval;
} }
cdev_init(&dvb_device_cdev, &dvb_device_fops); cdev_init(&dvb_device_cdev, &dvb_device_fops);
if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS);
if (retval != 0) {
pr_err("dvb-core: unable register character device\n"); pr_err("dvb-core: unable register character device\n");
goto error; goto error;
} }
@ -1113,12 +1139,19 @@ error:
return retval; return retval;
} }
static void __exit exit_dvbdev(void) static void __exit exit_dvbdev(void)
{ {
struct dvbdevfops_node *node, *next;
class_destroy(dvb_class); class_destroy(dvb_class);
cdev_del(&dvb_device_cdev); cdev_del(&dvb_device_cdev);
unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) {
list_del(&node->list_head);
kfree(node->fops);
kfree(node);
}
} }
subsys_initcall(init_dvbdev); subsys_initcall(init_dvbdev);

View File

@ -1643,7 +1643,7 @@ static int clear_slave(struct dvb_frontend *fe)
get_field(RXEND, &done); get_field(RXEND, &done);
get_reg(DISRXBYTES, &n); get_reg(DISRXBYTES, &n);
printk("clear: done = %u, %u fifo bytes\n", done, n); //printk("clear: done = %u, %u fifo bytes\n", done, n);
for (get_reg(DISRXBYTES, &n); n; n--) for (get_reg(DISRXBYTES, &n); n; n--)
get_reg(DISRXFIFO, &d); get_reg(DISRXFIFO, &d);
@ -1699,7 +1699,7 @@ static int recv_slave_reply(struct dvb_frontend *fe,
msleep(10); msleep(10);
} }
get_reg(DISRXBYTES, &val); get_reg(DISRXBYTES, &val);
printk("done = %u, %u fifo bytes, i=%u\n", done, val, i); //printk("done = %u, %u fifo bytes, i=%u\n", done, val, i);
if (i == to && !val) if (i == to && !val)
return -EIO; return -EIO;
if (done && !val) if (done && !val)

View File

@ -302,6 +302,7 @@ enum fe_spectral_inversion {
* @FEC_7_15: Forward Error Correction Code 7/15 * @FEC_7_15: Forward Error Correction Code 7/15
* @FEC_29_45: Forward Error Correction Code 29/45 * @FEC_29_45: Forward Error Correction Code 29/45
* @FEC_31_45: Forward Error Correction Code 31/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 {
@ -597,7 +598,7 @@ enum fe_interleaving {
#define DTV_STAT_TOTAL_BLOCK_COUNT 69 #define DTV_STAT_TOTAL_BLOCK_COUNT 69
/* Physical layer scrambling */ /* Physical layer scrambling */
#define DTV_SCRAMBLING_SEQUENCE_INDEX 70 #define DTV_SCRAMBLING_SEQUENCE_INDEX 70
#define DTV_INPUT 71 #define DTV_INPUT 71
#define DTV_MAX_COMMAND DTV_INPUT #define DTV_MAX_COMMAND DTV_INPUT

View File

@ -10,6 +10,6 @@
#define _DVBVERSION_H_ #define _DVBVERSION_H_
#define DVB_API_VERSION 5 #define DVB_API_VERSION 5
#define DVB_API_VERSION_MINOR 11 #define DVB_API_VERSION_MINOR 12
#endif /*_DVBVERSION_H_*/ #endif /*_DVBVERSION_H_*/

View File

@ -1,246 +0,0 @@
/*
* dvb_filter.h
*
* Copyright (C) 2003 Convergence 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _DVB_FILTER_H_
#define _DVB_FILTER_H_
#include <linux/slab.h>
#include "demux.h"
typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
struct dvb_filter_pes2ts {
unsigned char buf[188];
unsigned char cc;
dvb_filter_pes2ts_cb_t *cb;
void *priv;
};
void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
dvb_filter_pes2ts_cb_t *cb, void *priv);
int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
int len, int payload_start);
#define PROG_STREAM_MAP 0xBC
#define PRIVATE_STREAM1 0xBD
#define PADDING_STREAM 0xBE
#define PRIVATE_STREAM2 0xBF
#define AUDIO_STREAM_S 0xC0
#define AUDIO_STREAM_E 0xDF
#define VIDEO_STREAM_S 0xE0
#define VIDEO_STREAM_E 0xEF
#define ECM_STREAM 0xF0
#define EMM_STREAM 0xF1
#define DSM_CC_STREAM 0xF2
#define ISO13522_STREAM 0xF3
#define PROG_STREAM_DIR 0xFF
#define DVB_PICTURE_START 0x00
#define DVB_USER_START 0xb2
#define DVB_SEQUENCE_HEADER 0xb3
#define DVB_SEQUENCE_ERROR 0xb4
#define DVB_EXTENSION_START 0xb5
#define DVB_SEQUENCE_END 0xb7
#define DVB_GOP_START 0xb8
#define DVB_EXCEPT_SLICE 0xb0
#define SEQUENCE_EXTENSION 0x01
#define SEQUENCE_DISPLAY_EXTENSION 0x02
#define PICTURE_CODING_EXTENSION 0x08
#define QUANT_MATRIX_EXTENSION 0x03
#define PICTURE_DISPLAY_EXTENSION 0x07
#define I_FRAME 0x01
#define B_FRAME 0x02
#define P_FRAME 0x03
/* Initialize sequence_data */
#define INIT_HORIZONTAL_SIZE 720
#define INIT_VERTICAL_SIZE 576
#define INIT_ASPECT_RATIO 0x02
#define INIT_FRAME_RATE 0x03
#define INIT_DISP_HORIZONTAL_SIZE 540
#define INIT_DISP_VERTICAL_SIZE 576
//flags2
#define PTS_DTS_FLAGS 0xC0
#define ESCR_FLAG 0x20
#define ES_RATE_FLAG 0x10
#define DSM_TRICK_FLAG 0x08
#define ADD_CPY_FLAG 0x04
#define PES_CRC_FLAG 0x02
#define PES_EXT_FLAG 0x01
//pts_dts flags
#define PTS_ONLY 0x80
#define PTS_DTS 0xC0
#define TS_SIZE 188
#define TRANS_ERROR 0x80
#define PAY_START 0x40
#define TRANS_PRIO 0x20
#define PID_MASK_HI 0x1F
//flags
#define TRANS_SCRMBL1 0x80
#define TRANS_SCRMBL2 0x40
#define ADAPT_FIELD 0x20
#define PAYLOAD 0x10
#define COUNT_MASK 0x0F
// adaptation flags
#define DISCON_IND 0x80
#define RAND_ACC_IND 0x40
#define ES_PRI_IND 0x20
#define PCR_FLAG 0x10
#define OPCR_FLAG 0x08
#define SPLICE_FLAG 0x04
#define TRANS_PRIV 0x02
#define ADAP_EXT_FLAG 0x01
// adaptation extension flags
#define LTW_FLAG 0x80
#define PIECE_RATE 0x40
#define SEAM_SPLICE 0x20
#define MAX_PLENGTH 0xFFFF
#define MMAX_PLENGTH (256*MAX_PLENGTH)
#ifndef IPACKS
#define IPACKS 2048
#endif
struct ipack {
int size;
int found;
u8 *buf;
u8 cid;
u32 plength;
u8 plen[2];
u8 flag1;
u8 flag2;
u8 hlength;
u8 pts[5];
u16 *pid;
int mpeg;
u8 check;
int which;
int done;
void *data;
void (*func)(u8 *buf, int size, void *priv);
int count;
int repack_subids;
};
struct dvb_video_info {
u32 horizontal_size;
u32 vertical_size;
u32 aspect_ratio;
u32 framerate;
u32 video_format;
u32 bit_rate;
u32 comp_bit_rate;
u32 vbv_buffer_size;
s16 vbv_delay;
u32 CSPF;
u32 off;
};
#define OFF_SIZE 4
#define FIRST_FIELD 0
#define SECOND_FIELD 1
#define VIDEO_FRAME_PICTURE 0x03
struct mpg_picture {
int channel;
struct dvb_video_info vinfo;
u32 *sequence_gop_header;
u32 *picture_header;
s32 time_code;
int low_delay;
int closed_gop;
int broken_link;
int sequence_header_flag;
int gop_flag;
int sequence_end_flag;
u8 profile_and_level;
s32 picture_coding_parameter;
u32 matrix[32];
s8 matrix_change_flag;
u8 picture_header_parameter;
/* bit 0 - 2: bwd f code
bit 3 : fpb vector
bit 4 - 6: fwd f code
bit 7 : fpf vector */
int mpeg1_flag;
int progressive_sequence;
int sequence_display_extension_flag;
u32 sequence_header_data;
s16 last_frame_centre_horizontal_offset;
s16 last_frame_centre_vertical_offset;
u32 pts[2]; /* [0] 1st field, [1] 2nd field */
int top_field_first;
int repeat_first_field;
int progressive_frame;
int bank;
int forward_bank;
int backward_bank;
int compress;
s16 frame_centre_horizontal_offset[OFF_SIZE];
/* [0-2] 1st field, [3] 2nd field */
s16 frame_centre_vertical_offset[OFF_SIZE];
/* [0-2] 1st field, [3] 2nd field */
s16 temporal_reference[2];
/* [0] 1st field, [1] 2nd field */
s8 picture_coding_type[2];
/* [0] 1st field, [1] 2nd field */
s8 picture_structure[2];
/* [0] 1st field, [1] 2nd field */
s8 picture_display_extension_flag[2];
/* [0] 1st field, [1] 2nd field */
/* picture_display_extenion() 0:no 1:exit*/
s8 pts_flag[2];
/* [0] 1st field, [1] 2nd field */
};
struct dvb_audio_info {
int layer;
u32 bit_rate;
u32 frequency;
u32 mode;
u32 mode_extension ;
u32 emphasis;
u32 framesize;
u32 off;
};
int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr);
#endif

View File

@ -19,13 +19,11 @@
#define _DVB_NET_H_ #define _DVB_NET_H_
#include <linux/module.h> #include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <media/dvbdev.h> #include <media/dvbdev.h>
struct net_device;
#define DVB_NET_DEVICES_MAX 10 #define DVB_NET_DEVICES_MAX 10
#ifdef CONFIG_DVB_NET #ifdef CONFIG_DVB_NET
@ -41,6 +39,9 @@
* @exit: flag to indicate when the device is being removed. * @exit: flag to indicate when the device is being removed.
* @demux: pointer to &struct dmx_demux. * @demux: pointer to &struct dmx_demux.
* @ioctl_mutex: protect access to this struct. * @ioctl_mutex: protect access to this struct.
* @remove_mutex: mutex that avoids a race condition between a callback
* called when the hardware is disconnected and the
* file_operations of dvb_net.
* *
* Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network * Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network
* devices. * devices.
@ -53,6 +54,7 @@ struct dvb_net {
unsigned int exit:1; unsigned int exit:1;
struct dmx_demux *demux; struct dmx_demux *demux;
struct mutex ioctl_mutex; struct mutex ioctl_mutex;
struct mutex remove_mutex;
}; };
/** /**

View File

@ -139,7 +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 * @ref: reference count for this device
* @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.
@ -202,6 +202,21 @@ struct dvb_device {
void *priv; void *priv;
}; };
/**
* struct dvbdevfops_node - fops nodes registered in dvbdevfops_list
*
* @fops: Dynamically allocated fops for ->owner registration
* @type: type of dvb_device
* @template: dvb_device used for registration
* @list_head: list_head for dvbdevfops_list
*/
struct dvbdevfops_node {
struct file_operations *fops;
enum dvb_device_type type;
const struct dvb_device *template;
struct list_head list_head;
};
/** /**
* dvb_device_get - Increase dvb_device reference * dvb_device_get - Increase dvb_device reference
* *
@ -260,10 +275,10 @@ int dvb_register_device(struct dvb_adapter *adap,
/** /**
* dvb_remove_device - Remove a registered DVB device * dvb_remove_device - Remove a registered DVB device
* *
* @dvbdev: pointer to struct dvb_device
*
* This does not free memory. dvb_free_device() will do that when * This does not free memory. dvb_free_device() will do that when
* reference counter is empty * reference counter is empty
*
* @dvbdev: pointer to struct dvb_device
*/ */
void dvb_remove_device(struct dvb_device *dvbdev); void dvb_remove_device(struct dvb_device *dvbdev);