Merge branch 'internal'

This commit is contained in:
rjkm 2022-02-16 15:55:04 +01:00
commit a5f3b75d0a
34 changed files with 1016 additions and 435 deletions

6
Kbuild
View File

@ -2,6 +2,12 @@
# Makefile for the kernel multimedia device drivers.
#
ifeq ($(KERNEL_DVB_CORE),y)
obj-y := ddbridge/ \
frontends/
else
obj-y := dvb-core/ \
ddbridge/ \
frontends/
endif

View File

@ -6,8 +6,11 @@ MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_
KBUILD_EXTMOD = $(PWD)
DDDVB_INC = "-I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux -I$(KBUILD_EXTMOD)/frontends"
ifeq ($(KERNEL_DVB_CORE),y)
DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD) -DKERNEL_DVB_CORE=y"
else
DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux"
endif
all:
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) $(MODDEFS) modules NOSTDINC_FLAGS=$(DDDVB_INC)

View File

@ -239,7 +239,31 @@ char* PunctureRates[32] = {
/* 0x07 */ "rsvd 7.0",
};
void print_info(struct mci_result *res, uint8_t demod)
int mci_bb(int dev, uint32_t link, uint8_t demod)
{
struct ddb_mci_msg msg = {
.link = link,
.cmd.command = MCI_CMD_GET_BBHEADER,
.cmd.demod = demod,
.cmd.get_bb_header.select = 0,
};
struct mci_result *res = &msg.res;
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
if (res->bb_header.valid) {
printf("MATYPE1: %02x\n", res->bb_header.matype_1);
printf("MATYPE2: %02x\n", res->bb_header.matype_2);
}
return ret;
}
void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res)
{
if (res->status == MCI_DEMOD_STOPPED) {
printf("\nDemod %u: stopped\n", demod);
@ -261,6 +285,7 @@ void print_info(struct mci_result *res, uint8_t demod)
else
printf("Demod Locked: DVB-S2\n");
printf("PLS-Code: %u\n", res->dvbs2_signal_info.pls_code);
mci_bb(dev, link, demod);
if (pls >= 250) {
pilots = 1;
modcod = S2Xrsvd[pls - 250];
@ -350,7 +375,7 @@ int mci_info(int dev, uint32_t link, uint8_t demod)
return ret;
}
print_info(&msg.res, demod);
print_info(dev, link, demod, &msg.res);
return ret;
}

View File

@ -83,100 +83,200 @@ struct param_table_entry {
};
struct param_table_entry mod_standard_table[] = {
{ .name = "GENERIC", .value = MOD_STANDARD_GENERIC },
{ .name = "DVBT_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "DVBT2_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT2_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT2_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT2_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "0", .value = MOD_STANDARD_GENERIC },
{ .name = "GENERIC", .value = MOD_STANDARD_GENERIC },
{ .name = "1", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT2_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "2", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT2_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "3", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT2_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "4", .value = MOD_STANDARD_DVBT_5 },
{ .name = "DVBT_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "DVBT2_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "8", .value = MOD_STANDARD_DVBC_8 },
{ .name = "DVBC_8", .value = MOD_STANDARD_DVBC_8 },
{ .name = "9", .value = MOD_STANDARD_DVBC_7 },
{ .name = "DVBC_7", .value = MOD_STANDARD_DVBC_7 },
{ .name = "10", .value = MOD_STANDARD_DVBC_6 },
{ .name = "DVBC_6", .value = MOD_STANDARD_DVBC_6 },
{ .name = "11", .value = MOD_STANDARD_J83B_QAM64 },
{ .name = "J83B_QAM64", .value = MOD_STANDARD_J83B_QAM64 },
{ .name = "12", .value = MOD_STANDARD_J83B_QAM256 },
{ .name = "J83B_QAM256", .value = MOD_STANDARD_J83B_QAM256 },
{ .name = "13", .value = MOD_STANDARD_ISDBC_QAM64 },
{ .name = "ISDBC_QAM64", .value = MOD_STANDARD_ISDBC_QAM64 },
{ .name = "J83C_QAM64", .value = MOD_STANDARD_ISDBC_QAM64 },
{ .name = "14", .value = MOD_STANDARD_ISDBC_QAM256 },
{ .name = "ISDBC_QAM256", .value = MOD_STANDARD_ISDBC_QAM256 },
{ .name = "J83C_QAM256", .value = MOD_STANDARD_ISDBC_QAM256 },
{ .name = NULL, .value = 0 }
};
struct param_table_entry stream_format_table[] = {
{ .name = "default", .value = MOD_FORMAT_DEFAULT },
{ .name = "IQ16", .value = MOD_FORMAT_IQ16 },
{ .name = "IQ8", .value = MOD_FORMAT_IQ8 },
{ .name = "IDX8", .value = MOD_FORMAT_IDX8 },
{ .name = "TS", .value = MOD_FORMAT_TS },
{ .name = "0", .value = MOD_FORMAT_DEFAULT },
{ .name = "default", .value = MOD_FORMAT_DEFAULT },
{ .name = "1", .value = MOD_FORMAT_IQ16 },
{ .name = "IQ16", .value = MOD_FORMAT_IQ16 },
{ .name = "2", .value = MOD_FORMAT_IQ8 },
{ .name = "IQ8", .value = MOD_FORMAT_IQ8 },
{ .name = "3", .value = MOD_FORMAT_IDX8 },
{ .name = "IDX8", .value = MOD_FORMAT_IDX8 },
{ .name = "4", .value = MOD_FORMAT_TS },
{ .name = "TS", .value = MOD_FORMAT_TS },
{ .name = NULL, .value = 0 }
};
struct param_table_entry guard_interval_table[] = {
{ .name = "1/32", .value = MOD_DVBT_GI_1_32 },
{ .name = "1/16", .value = MOD_DVBT_GI_1_16 },
{ .name = "1/8", .value = MOD_DVBT_GI_1_8 },
{ .name = "1/4", .value = MOD_DVBT_GI_1_4 },
{ .name = "0", .value = MOD_DVBT_GI_1_32 },
{ .name = "1/32", .value = MOD_DVBT_GI_1_32 },
{ .name = "1", .value = MOD_DVBT_GI_1_16 },
{ .name = "2", .value = MOD_DVBT_GI_1_8 },
{ .name = "3", .value = MOD_DVBT_GI_1_4 },
{ .name = "1/16", .value = MOD_DVBT_GI_1_16 },
{ .name = "2", .value = MOD_DVBT_GI_1_8 },
{ .name = "1/8", .value = MOD_DVBT_GI_1_8 },
{ .name = "3", .value = MOD_DVBT_GI_1_4 },
{ .name = "1/4", .value = MOD_DVBT_GI_1_4 },
{ .name = NULL, .value = 0 }
};
struct param_table_entry puncture_rate_table[] = {
{ .name = "1/2", .value = MOD_DVBT_PR_1_2 },
{ .name = "2/3", .value = MOD_DVBT_PR_2_3 },
{ .name = "3/4", .value = MOD_DVBT_PR_3_4 },
{ .name = "5/6", .value = MOD_DVBT_PR_5_6 },
{ .name = "7/8", .value = MOD_DVBT_PR_7_8 },
{ .name = "1", .value = MOD_DVBT_PR_1_2 },
{ .name = "1/2", .value = MOD_DVBT_PR_1_2 },
{ .name = "2", .value = MOD_DVBT_PR_2_3 },
{ .name = "2/3", .value = MOD_DVBT_PR_2_3 },
{ .name = "3", .value = MOD_DVBT_PR_3_4 },
{ .name = "3/4", .value = MOD_DVBT_PR_3_4 },
{ .name = "5", .value = MOD_DVBT_PR_5_6 },
{ .name = "5/6", .value = MOD_DVBT_PR_5_6 },
{ .name = "7", .value = MOD_DVBT_PR_7_8 },
{ .name = "7/8", .value = MOD_DVBT_PR_7_8 },
{ .name = NULL, .value = 0 }
};
struct param_table_entry dvbt_constellation_table[] = {
{ .name = "0", .value = MOD_DVBT_QPSK },
{ .name = "qpsk", .value = MOD_DVBT_QPSK },
{ .name = "1", .value = MOD_DVBT_16QAM },
{ .name = "16qam", .value = MOD_DVBT_16QAM },
{ .name = "qam16", .value = MOD_DVBT_16QAM },
{ .name = "2", .value = MOD_DVBT_64QAM },
{ .name = "64qam", .value = MOD_DVBT_64QAM },
{ .name = "qam64", .value = MOD_DVBT_64QAM },
{ .name = NULL, .value = 0 }
};
int parse_param(char *val,struct param_table_entry *table, int *value) {
struct param_table_entry qam_modulation_table[] = {
{ .name = "0", .value = MOD_QAM_DVBC_16 },
{ .name = "qam_dvbc_16", .value = MOD_QAM_DVBC_16 },
{ .name = "1", .value = MOD_QAM_DVBC_32 },
{ .name = "qam_dvbc_32", .value = MOD_QAM_DVBC_32 },
{ .name = "2", .value = MOD_QAM_DVBC_64 },
{ .name = "qam_dvbc_64", .value = MOD_QAM_DVBC_64 },
{ .name = "3", .value = MOD_QAM_DVBC_128 },
{ .name = "qam_dvbc_128", .value = MOD_QAM_DVBC_128 },
{ .name = "4", .value = MOD_QAM_DVBC_256 },
{ .name = "qam_dvbc_256", .value = MOD_QAM_DVBC_256 },
{ .name = "5", .value = MOD_QAM_J83B_64 },
{ .name = "qam_j83b_64", .value = MOD_QAM_J83B_64 },
{ .name = "6", .value = MOD_QAM_DVBC_256 },
{ .name = "qam_j83b_256", .value = MOD_QAM_J83B_256 },
{ .name = "7", .value = MOD_QAM_GENERIC },
{ .name = "qam_generic", .value = MOD_QAM_GENERIC },
{ .name = "8", .value = MOD_QAM_ISDBC_64 },
{ .name = "qam_isdbc_64", .value = MOD_QAM_ISDBC_64 },
{ .name = "9", .value = MOD_QAM_ISDBC_256 },
{ .name = "qam_isdbc_256", .value = MOD_QAM_ISDBC_256 },
{ .name = NULL, .value = 0 }
};
int parse_param(char *val, struct param_table_entry *table, int *value) {
if (value) {
*value = 0;
if (table) {
while (table->name) {
if( !strcasecmp(val,table->name)) {
*value = table->value;
printf("%s=%u\n", val, *value);
return 0;
}
table++;
}
}
}
printf("unknown value %s\n", val);
return -1;
}
void dump(const uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
printf("%02x ", b[i]);
else
printf(" ");
printf(" | ");
for (i = 0; i < 16; i++)
if (i + j < l)
putchar((b[i] > 31 && b[i] < 127) ? b[i] : '.');
printf("\n");
}
}
int mci_cmd(int dev, struct mci_command *cmd)
{
int ret;
struct ddb_mci_msg msg;
uint8_t status;
memset(&msg, 0, sizeof(msg));
msg.link = 0;
memcpy(&msg.cmd, cmd, sizeof(msg.cmd));
//dump((uint8_t *) &msg.cmd, sizeof(msg.cmd));
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
dprintf(2, "mci_cmd error %d\n", errno);
@ -213,9 +313,13 @@ struct mci_command msg_stream = {
.mod_channel = 1,
.mod_stream = 0,
.mod_setup_stream = {
.standard = MOD_STANDARD_DVBT_8,
.fft_size = 1,
.guard_interval = 0,
.standard = MOD_STANDARD_DVBC_8,
#if 0
.ofdm = {
.fft_size = 1,
.guard_interval = 0,
}
#endif
},
};
@ -252,7 +356,7 @@ void output_cb(void *priv, char *par, char *val)
mc->output.mod_setup_output.channel_power = (int16_t) (strtod(val, NULL) * 100.0);
} else if (!strcasecmp(par, "channels")) {
mc->output.mod_setup_output.num_channels = strtol(val, NULL, 10);
}else if (!strcasecmp(par, "unit")) {
} else if (!strcasecmp(par, "unit")) {
if (!strcasecmp(val, "DBUV")) {
mc->output.mod_setup_output.unit = MOD_UNIT_DBUV;
} else if (!strcasecmp(val, "DBM")) {
@ -278,10 +382,11 @@ void channels_cb(void *priv, char *par, char *val)
} else if (!strcasecmp(par, "channels")) {
mc->channels.mod_setup_channels[0].num_channels = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "standard")) {
if (!parse_param(val,mod_standard_table,&value))
mc->stream.mod_setup_channels[0].standard = value;
if (!parse_param(val,mod_standard_table, &value))
mc->channels.mod_setup_channels[0].standard = value;
printf("standard = %u\n", value);
} else if (!strcasecmp(par, "offset")) {
mc->channels.mod_setup_channels[0].offset = (uint32_t) (strtod(val, NULL) * 1000000.0);
mc->channels.mod_setup_channels[0].offset = (uint32_t) (strtod(val, NULL) * 1000000.0);
} else if (!strcasecmp(par, "bandwidth")) {
mc->channels.mod_setup_channels[0].bandwidth = (uint32_t) (strtod(val, NULL) * 1000000.0);
mc->channels.mod_setup_channels[0].offset =
@ -299,18 +404,23 @@ void streams_cb(void *priv, char *par, char *val)
return;
}
if (!strcasecmp(par, "fft_size")) {
mc->stream.mod_setup_stream.fft_size = strtol(val, NULL, 10);
mc->stream.mod_setup_stream.ofdm.fft_size = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "guard_interval")) {
if (!parse_param(val,guard_interval_table,&value))
mc->stream.mod_setup_stream.guard_interval = value;
if (!parse_param(val, guard_interval_table, &value))
mc->stream.mod_setup_stream.ofdm.guard_interval = value;
} else if (!strcasecmp(par, "puncture_rate")) {
if (!parse_param(val,puncture_rate_table,&value))
mc->stream.mod_setup_stream.puncture_rate = value;
if (!parse_param(val, puncture_rate_table, &value))
mc->stream.mod_setup_stream.ofdm.puncture_rate = value;
} else if (!strcasecmp(par, "constellation")) {
if (!parse_param(val,dvbt_constellation_table,&value))
mc->stream.mod_setup_stream.constellation = value;
mc->stream.mod_setup_stream.ofdm.constellation = value;
} else if (!strcasecmp(par, "cell_identifier")) {
mc->stream.mod_setup_stream.cell_identifier = strtol(val, NULL, 0);
mc->stream.mod_setup_stream.ofdm.cell_identifier = strtol(val, NULL, 0);
} else if (!strcasecmp(par, "modulation")) {
if (!parse_param(val, qam_modulation_table, &value))
mc->stream.mod_setup_stream.qam.modulation = value;
} else if (!strcasecmp(par, "rolloff")) {
mc->stream.mod_setup_stream.qam.rolloff = strtol(val, NULL, 0);
} else if (!strcasecmp(par, "standard")) {
if (!parse_param(val,mod_standard_table,&value))
mc->stream.mod_setup_stream.standard = value;
@ -329,6 +439,29 @@ void streams_cb(void *priv, char *par, char *val)
printf("invalid streams parameter: %s = %s\n", par, val);
}
int mci_lic(int dev)
{
struct ddb_mci_msg msg = {
.cmd.command = CMD_EXPORT_LICENSE,
.cmd.get_bb_header.select = 0,
};
struct mci_result *res = &msg.res;
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
if (res->bb_header.valid) {
printf("MATYPE1: %02x\n", res->bb_header.matype_1);
printf("MATYPE2: %02x\n", res->bb_header.matype_2);
}
dump(&res->license, sizeof(res->license));
return ret;
}
int main(int argc, char*argv[])
{
int fd = -1;
@ -375,18 +508,24 @@ int main(int argc, char*argv[])
printf("too many arguments\n");
exit(1);
}
snprintf(fn, 127, "/dev/ddbridge/card%u", device);
//snprintf(fn, 127, "/dev/ddbridge/card%u", device);
snprintf(fn, 127, "/dev/dvb/adapter%u/mod0", device);
fd = open(fn, O_RDWR);
if (fd < 0) {
dprintf(2, "Could not open %s\n", fn);
return -1;
}
//mci_lic(fd);
mc.fd = fd;
parse(configname, "channels", (void *) &mc, channels_cb);
if (mc.set_channels)
if (mc.set_channels) {
printf("setting channels.\n");
mci_cmd(fd, &mc.channels);
}
parse(configname, "streams", (void *) &mc, streams_cb);
parse(configname, "output", (void *) &mc, output_cb);
if (mc.set_output)
if (mc.set_output) {
printf("setting output.\n");
mci_cmd(fd, &mc.output);
}
}

View File

@ -1,12 +1,16 @@
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX -DCONFIG_DVB_CXD2099 -DCONFIG_DVB_NET
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
#mci-objs = ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o ddbridge-io.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o #mci.o
ifneq ($(KERNEL_DVB_CORE),y)
obj-$(CONFIG_DVB_OCTONET) += octonet.o
endif
#EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends
#EXTRA_CFLAGS += -Idrivers/media/common/tuners

View File

@ -11,4 +11,5 @@ obj-$(CONFIG_DVB_OCTONET) += octonet.o
ccflags-y += -Idrivers/media/dvb-core/
ccflags-y += -Idrivers/media/dvb-frontends/
ccflags-y += -Idrivers/media/tuners/
ccflags-y += --include=dd_compat.h

View File

@ -95,6 +95,70 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/****************************************************************************/
/****************************************************************************/
/* copied from dvb-core/dvbdev.c because kernel version does not export it */
int ddb_dvb_usercopy(struct file *file,
unsigned int cmd, unsigned long arg,
int (*func)(struct file *file,
unsigned int cmd, void *arg))
{
char sbuf[128];
void *mbuf = NULL;
void *parg = NULL;
int err = -EINVAL;
/* Copy arguments into temp kernel buffer */
switch (_IOC_DIR(cmd)) {
case _IOC_NONE:
/*
* For this command, the pointer is actually an integer
* argument.
*/
parg = (void *) arg;
break;
case _IOC_READ: /* some v4l ioctls are marked wrong ... */
case _IOC_WRITE:
case (_IOC_WRITE | _IOC_READ):
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
parg = sbuf;
} else {
/* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
if (NULL == mbuf)
return -ENOMEM;
parg = mbuf;
}
err = -EFAULT;
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
goto out;
break;
}
/* call driver */
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
err = -ENOTTY;
if (err < 0)
goto out;
/* Copy results into user buffer */
switch (_IOC_DIR(cmd))
{
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
err = -EFAULT;
break;
}
out:
kfree(mbuf);
return err;
}
/****************************************************************************/
struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr,
void (*handler)(void *), void *data)
{
@ -336,7 +400,7 @@ static int ddb_buffers_alloc(struct ddb *dev)
if (dma_alloc(dev->pdev,
port->input[0]->dma, 0) < 0)
return -1;
/* fallthrough */
fallthrough;
case DDB_PORT_MOD:
if (port->output->dma)
if (dma_alloc(dev->pdev,
@ -457,10 +521,11 @@ static void calc_con(struct ddb_output *output, u32 *con, u32 *con2, u32 flags)
*con2 = (nco << 16) | gap;
}
static void ddb_output_start_unlocked(struct ddb_output *output)
static int ddb_output_start_unlocked(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
u32 con = 0x11c, con2 = 0;
int err = 0;
if (output->dma) {
output->dma->cbuf = 0;
@ -469,7 +534,7 @@ static void ddb_output_start_unlocked(struct ddb_output *output)
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
}
if (output->port->class == DDB_PORT_MOD) {
ddbridge_mod_output_start(output);
err = ddbridge_mod_output_start(output);
} else {
if (output->port->input[0]->port->class == DDB_PORT_LOOP)
con = (1UL << 13) | 0x14;
@ -492,17 +557,21 @@ static void ddb_output_start_unlocked(struct ddb_output *output)
ddbwritel(dev, con | 1, TS_CONTROL(output));
if (output->dma)
output->dma->running = 1;
return err;
}
static void ddb_output_start(struct ddb_output *output)
static int ddb_output_start(struct ddb_output *output)
{
int err;
if (output->dma) {
spin_lock_irq(&output->dma->lock);
ddb_output_start_unlocked(output);
err = ddb_output_start_unlocked(output);
spin_unlock_irq(&output->dma->lock);
} else {
ddb_output_start_unlocked(output);
err = ddb_output_start_unlocked(output);
}
return err;
}
static void ddb_output_stop_unlocked(struct ddb_output *output)
@ -934,7 +1003,7 @@ static int ts_open(struct inode *inode, struct file *file)
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
ddb_input_start(input);
else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
ddb_output_start(output);
err = ddb_output_start(output);
return err;
}
@ -993,7 +1062,7 @@ static struct dvb_device dvbdev_ci = {
static long mod_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl);
return ddb_dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl);
}
static const struct file_operations mod_fops = {
@ -1446,35 +1515,35 @@ static void dvb_input_detach(struct ddb_input *input)
case 0x41:
if (dvb->fe2)
dvb_unregister_frontend(dvb->fe2);
/* fallthrough */
fallthrough;
case 0x40:
if (dvb->fe)
dvb_unregister_frontend(dvb->fe);
/* fallthrough */
fallthrough;
case 0x30:
dvb_frontend_detach(dvb->fe);
dvb->fe = NULL;
dvb->fe2 = NULL;
/* fallthrough */
fallthrough;
case 0x21:
if (input->port->dev->ns_num)
dvb_netstream_release(&dvb->dvbns);
/* fallthrough */
fallthrough;
case 0x20:
dvb_net_release(&dvb->dvbnet);
/* fallthrough */
fallthrough;
case 0x12:
dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
&dvb->hw_frontend);
dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
&dvb->mem_frontend);
/* fallthrough */
fallthrough;
case 0x11:
dvb_dmxdev_release(&dvb->dmxdev);
/* fallthrough */
fallthrough;
case 0x10:
dvb_dmx_release(&dvb->demux);
/* fallthrough */
fallthrough;
case 0x01:
break;
}
@ -1715,7 +1784,7 @@ static int dvb_input_attach(struct ddb_input *input)
osc24 = 0;
else
osc24 = 1;
/* fallthrough */
fallthrough;
case DDB_TUNER_DVBCT2_SONY_P:
case DDB_TUNER_DVBC2T2_SONY_P:
case DDB_TUNER_ISDBT_SONY_P:
@ -1732,7 +1801,7 @@ static int dvb_input_attach(struct ddb_input *input)
break;
case DDB_TUNER_DVBC2T2I_SONY:
osc24 = 1;
/* fallthrough */
fallthrough;
case DDB_TUNER_DVBCT2_SONY:
case DDB_TUNER_DVBC2T2_SONY:
case DDB_TUNER_ISDBT_SONY:
@ -2011,14 +2080,14 @@ static void ddb_port_probe(struct ddb_port *port)
return;
}
if (port->nr == 1 && dev->link[l].info->type == DDB_OCTOPUS_CI &&
if (port->nr == 1 && link->info->type == DDB_OCTOPUS_CI &&
link->info->i2c_mask == 1) {
port->name = "NO TAB";
port->class = DDB_PORT_NONE;
return;
}
if (dev->link[l].info->type == DDB_MOD) {
if (link->info->type == DDB_MOD) {
port->name = "MOD";
port->class = DDB_PORT_MOD;
return;
@ -2034,9 +2103,8 @@ static void ddb_port_probe(struct ddb_port *port)
return;
}
if (link->info->type == DDB_OCTOPUS_MCI) {
if (port->nr >= link->info->mci_ports)
return;
if ((link->info->type == DDB_OCTOPUS_MCI) &&
(port->nr < link->info->mci_ports)) {
port->name = "DUAL MCI";
port->type_name = "MCI";
port->class = DDB_PORT_TUNER;
@ -2180,7 +2248,7 @@ static int ddb_port_attach(struct ddb_port *port)
ret = ddb_ci_attach(port, ci_bitrate);
if (ret < 0)
break;
/* fallthrough */
fallthrough;
case DDB_PORT_LOOP:
ret = dvb_register_device(port->dvb[0].adap,
&port->dvb[0].dev,
@ -2580,7 +2648,7 @@ static void ddb_ports_init(struct ddb *dev)
if (!rm)
continue;
ports = info->port_num;
if ((l == 0) && (dev->link[l].info->type == DDB_MOD) &&
if ((l == 0) && (info->type == DDB_MOD) &&
(dev->link[0].ids.revision == 1)) {
ports = ddbreadl(dev, 0x260) >> 24;
}
@ -2606,6 +2674,7 @@ static void ddb_ports_init(struct ddb *dev)
port->class = DDB_PORT_CI;
port->type = DDB_CI_EXTERNAL_XO2_B;
port->name = "DuoFlex CI_B";
port->type_name = "CI_XO2_B";
port->i2c = dev->port[p - 1].i2c;
}
dev_info(dev->dev, "Port %u: Link %u, Link Port %u (TAB %u): %s\n",
@ -2627,15 +2696,16 @@ static void ddb_ports_init(struct ddb *dev)
}
if (port->class == DDB_PORT_NONE)
continue;
switch (dev->link[l].info->type) {
switch (info->type) {
case DDB_OCTOPUS_CI:
if (i >= 2) {
ddb_input_init(port, 2 + i, 0, 2 + i);
ddb_input_init(port, 4 + i, 1, 4 + i);
ddb_output_init(port, i);
break;
} /* fallthrough */
}
fallthrough;
case DDB_OCTONET:
case DDB_OCTOPUS:
case DDB_OCTOPRO:
@ -2965,7 +3035,7 @@ static int nsd_do_ioctl(struct file *file, unsigned int cmd, void *parg)
static long nsd_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return dvb_usercopy(file, cmd, arg, nsd_do_ioctl);
return ddb_dvb_usercopy(file, cmd, arg, nsd_do_ioctl);
}
static const struct file_operations nsd_fops = {
@ -3623,19 +3693,23 @@ static ssize_t snr_show(struct device *device,
struct ddb *dev = dev_get_drvdata(device);
char snr[32];
int num = attr->attr.name[3] - 0x30;
struct ddb_port *port = &dev->port[num];
struct i2c_adapter *i2c = &port->i2c->adap;
if (dev->port[num].type >= DDB_TUNER_XO2) {
if (i2c_read_regs(&dev->i2c[num].adap, 0x10, 0x10, snr, 16) < 0)
switch (port->type) {
case DDB_CI_EXTERNAL_XO2:
case DDB_TUNER_XO2 ... DDB_TUNER_DVBC2T2I_SONY:
if (i2c_read_regs(i2c, 0x10, 0x10, snr, 16) < 0)
return sprintf(buf, "NO SNR\n");
snr[16] = 0;
} else {
break;
default:
/* serial number at 0x100-0x11f */
if (i2c_read_regs16(&dev->i2c[num].adap,
0x57, 0x100, snr, 32) < 0)
if (i2c_read_regs16(&dev->i2c[num].adap,
0x50, 0x100, snr, 32) < 0)
if (i2c_read_regs16(i2c, 0x57, 0x100, snr, 32) < 0)
if (i2c_read_regs16(i2c, 0x50, 0x100, snr, 32) < 0)
return sprintf(buf, "NO SNR\n");
snr[31] = 0; /* in case it is not terminated on EEPROM */
break;
}
return sprintf(buf, "%s\n", snr);
}
@ -3646,15 +3720,17 @@ static ssize_t snr_store(struct device *device, struct device_attribute *attr,
struct ddb *dev = dev_get_drvdata(device);
int num = attr->attr.name[3] - 0x30;
u8 snr[34] = { 0x01, 0x00 };
struct ddb_port *port = &dev->port[num];
struct i2c_adapter *i2c = &port->i2c->adap;
return 0; /* NOE: remove completely? */
if (count > 31)
return -EINVAL;
if (dev->port[num].type >= DDB_TUNER_XO2)
if (port->type >= DDB_TUNER_XO2)
return -EINVAL;
memcpy(snr + 2, buf, count);
i2c_write(&dev->i2c[num].adap, 0x57, snr, 34);
i2c_write(&dev->i2c[num].adap, 0x50, snr, 34);
i2c_write(i2c, 0x57, snr, 34);
i2c_write(i2c, 0x50, snr, 34);
return count;
}
@ -4348,7 +4424,9 @@ static int ddb_init_boards(struct ddb *dev)
if (info->regmap->mci) {
if (link->info->type == DDB_OCTOPUS_MCI ||
((link->info->type == DDB_MOD) &&
(link->ids.regmapid & 0xfff0)))
(link->ids.regmapid & 0xfff0)) ||
((link->info->type == DDB_MOD) &&
(link->ids.revision == 1)))
mci_init(link);
}
}
@ -4445,7 +4523,7 @@ int ddb_exit_ddbridge(int stage, int error)
default:
case 2:
destroy_workqueue(ddb_wq);
/* fallthrough */
fallthrough;
case 1:
ddb_class_destroy();
}

View File

@ -315,6 +315,7 @@ static const struct ddb_regmap octopus_mod_2_map = {
.irq_version = 2,
.irq_base_odma = 64,
.irq_base_rate = 32,
.irq_base_mci = 10,
.output = &octopus_output,
.odma = &octopus_mod_2_odma,
.odma_buf = &octopus_mod_2_odma_buf,

View File

@ -516,7 +516,7 @@ static int base_init(struct mci_base *mci_base)
return 0;
}
struct mci_cfg ddb_max_m4_cfg = {
static struct mci_cfg ddb_max_m4_cfg = {
.type = 0,
.fe_ops = &m4_ops,
.base_size = sizeof(struct m4_base),
@ -524,3 +524,8 @@ struct mci_cfg ddb_max_m4_cfg = {
.init = init,
.base_init = base_init,
};
struct dvb_frontend *ddb_m4_attach(struct ddb_input *input, int nr, int tuner)
{
return ddb_mci_attach(input, &ddb_max_m4_cfg, nr, tuner);
}

View File

@ -309,7 +309,6 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].dev = dev;
dev->link[0].info = get_ddb_info(id->vendor, id->device,
id->subvendor, pdev->subsystem_device);
dev_info(dev->dev, "device name: %s\n", dev->link[0].info->name);
dev->regs_len = pci_resource_len(dev->pdev, 0);
dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
@ -329,10 +328,6 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].ids.hwid = ddbreadl(dev, 0);
dev->link[0].ids.regmapid = ddbreadl(dev, 4);
dev_info(dev->dev, "HW %08x REGMAP %08x FW %u.%u\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid,
(dev->link[0].ids.hwid & 0xff0000) >> 16,
dev->link[0].ids.hwid & 0xffff);
if ((dev->link[0].ids.hwid & 0xffffff) <
dev->link[0].info->hw_min) {
u32 min = dev->link[0].info->hw_min;
@ -359,16 +354,27 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
&& dev->link[0].info->version == 2) {
u32 lic = ddbreadl(dev, 0x1c) & 7;
if (dev->link[0].ids.revision == 1)
lic = ddbreadl(dev, 0x260) >> 24;
switch (lic) {
case 0:
case 4:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0000);
break;
case 1:
case 8:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0003);
break;
case 2:
case 24:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0001);
break;
case 3:
case 16:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0002);
break;
@ -376,6 +382,12 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
break;
}
}
dev_info(dev->dev, "device name: %s\n", dev->link[0].info->name);
dev_info(dev->dev, "HW %08x REGMAP %08x FW %u.%u\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid,
(dev->link[0].ids.hwid & 0xff0000) >> 16,
dev->link[0].ids.hwid & 0xffff);
stat = ddb_irq_init(dev);
if (stat < 0)
goto fail0;
@ -400,6 +412,12 @@ fail:
/****************************************************************************/
/****************************************************************************/
#ifndef PCI_DEVICE_SUB
#define PCI_DEVICE_SUB(vend, dev, subvend, subdev) \
.vendor = (vend), .device = (dev), \
.subvendor = (subvend), .subdevice = (subdev)
#endif
#define DDB_DEVICE_ANY(_device) \
{ PCI_DEVICE_SUB(0xdd01, _device, 0xdd01, PCI_ANY_ID) }

View File

@ -472,7 +472,8 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
tuner = demod & 3;
if (fmode >= 3)
tuner = 0;
dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, demod, tuner);
dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg,
demod, tuner, &dvb->set_input);
if (!dvb->fe) {
dev_err(dev->dev, "No MXL5XX found!\n");
return -ENODEV;
@ -490,13 +491,17 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd;
dvb->fe->ops.diseqc_send_burst = max_send_burst;
dvb->fe->sec_priv = input;
dvb->set_input = dvb->fe->ops.set_input;
#ifndef KERNEL_DVB_CORE
dvb->fe->ops.set_input = max_set_input;
#endif
dvb->input = tuner;
return 0;
}
/* MAX MCI related functions */
struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner,
int (**fn_set_input)(struct dvb_frontend *fe, int input));
struct dvb_frontend *ddb_m4_attach(struct ddb_input *input, int nr, int tuner);
int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
{
@ -505,25 +510,23 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
struct ddb_port *port = input->port;
struct ddb_link *link = &dev->link[port->lnr];
int demod, tuner;
struct mci_cfg cfg;
int fm = fmode;
demod = input->nr;
tuner = demod & 3;
switch (type) {
case DDB_TUNER_MCI_SX8:
cfg = ddb_max_sx8_cfg;
if (fm >= 3)
tuner = 0;
dvb->fe = ddb_sx8_attach(input, demod, tuner, &dvb->set_input);
break;
case DDB_TUNER_MCI_M4:
fm = 0;
cfg = ddb_max_m4_cfg;
dvb->fe = ddb_m4_attach(input, demod, tuner);
break;
default:
return -EINVAL;
}
dvb->fe = ddb_mci_attach(input, &cfg, demod, tuner);
if (!dvb->fe) {
dev_err(dev->dev, "No MCI card found!\n");
return -ENODEV;
@ -545,8 +548,9 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
case DDB_TUNER_MCI_M4:
break;
default:
dvb->set_input = dvb->fe->ops.set_input;
#ifndef KERNEL_DVB_CORE
dvb->fe->ops.set_input = max_set_input;
#endif
break;
}
dvb->input = tuner;

View File

@ -221,21 +221,6 @@ int ddb_mci_get_status(struct mci *mci, struct mci_result *res)
return ddb_mci_cmd_raw(mci, &cmd, 1, res, 1);
}
static void ddb_mci_print_info(struct mci *mci)
{
struct ddb_link *link = mci->base->link;
const struct ddb_regmap *regmap = link->info->regmap;
struct mci_command cmd;
struct mci_result res;
cmd.command = 0x0f;
if (ddb_mci_cmd_raw(mci, &cmd, 1, &res, 1) < 0)
return;
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
link->dev->regs + regmap->mci_buf->base + MCI_COMMAND_SIZE,
16, false);
}
int ddb_mci_get_snr(struct dvb_frontend *fe)
{
struct mci *mci = fe->demodulator_priv;

View File

@ -188,49 +188,83 @@
/********************************************************/
#define MOD_SETUP_CHANNELS (0x60)
#define MOD_SETUP_OUTPUT (0x61)
#define MOD_SETUP_STREAM (0x62)
#define MOD_SET_STREAM_CHANNEL (0x63)
#define MOD_SETUP_CHANNELS (0x60)
#define MOD_SETUP_OUTPUT (0x61)
#define MOD_SETUP_STREAM (0x62)
#define MOD_SET_STREAM_CHANNEL (0x63)
#define MOD_SETUP_FLAG_FIRST (0x01)
#define MOD_SETUP_FLAG_LAST (0x02)
#define MOD_SETUP_FLAG_VALID (0x80)
#define MOD_SETUP_FLAG_FIRST (0x01)
#define MOD_SETUP_FLAG_LAST (0x02)
#define MOD_SETUP_FLAG_VALID (0x80)
#define MOD_STANDARD_GENERIC (0x00)
#define MOD_STANDARD_DVBT_8 (0x01)
#define MOD_STANDARD_DVBT_7 (0x02)
#define MOD_STANDARD_DVBT_6 (0x03)
#define MOD_STANDARD_DVBT_5 (0x04)
#define MOD_STANDARD_GENERIC (0x00)
#define MOD_STANDARD_DVBT_8 (0x01)
#define MOD_STANDARD_DVBT_7 (0x02)
#define MOD_STANDARD_DVBT_6 (0x03)
#define MOD_STANDARD_DVBT_5 (0x04)
#define MOD_CONNECTOR_OFF (0x00)
#define MOD_CONNECTOR_F (0x01)
#define MOD_CONNECTOR_SMA (0x02)
#define MOD_STANDARD_DVBC_8 (0x08)
#define MOD_STANDARD_DVBC_7 (0x09)
#define MOD_STANDARD_DVBC_6 (0x0A)
#define MOD_UNIT_DBUV (0x00)
#define MOD_UNIT_DBM (0x01)
#define MOD_STANDARD_J83A_8 (MOD_STANDARD_DVBC_8)
#define MOD_STANDARD_J83A_7 (MOD_STANDARD_DVBC_7)
#define MOD_STANDARD_J83A_6 (MOD_STANDARD_DVBC_6)
#define MOD_FORMAT_DEFAULT (0x00)
#define MOD_FORMAT_IQ16 (0x01)
#define MOD_FORMAT_IQ8 (0x02)
#define MOD_FORMAT_IDX8 (0x03)
#define MOD_FORMAT_TS (0x04)
#define MOD_STANDARD_J83B_QAM64 (0x0B)
#define MOD_STANDARD_J83B_QAM256 (0x0C)
#define MOD_DVBT_FFT_8K (0x01)
#define MOD_DVBT_GI_1_32 (0x00)
#define MOD_DVBT_GI_1_16 (0x01)
#define MOD_DVBT_GI_1_8 (0x02)
#define MOD_DVBT_GI_1_4 (0x03)
#define MOD_STANDARD_ISDBC_QAM64 (0x0D)
#define MOD_STANDARD_ISDBC_QAM256 (0x0E)
#define MOD_DVBT_PR_1_2 (0x00)
#define MOD_DVBT_PR_2_3 (0x01)
#define MOD_DVBT_PR_3_4 (0x02)
#define MOD_DVBT_PR_5_6 (0x03)
#define MOD_DVBT_PR_7_8 (0x04)
#define MOD_STANDARD_J83C_QAM64 (MOD_STANDARD_ISDBC_QAM64 )
#define MOD_STANDARD_J83C_QAM256 (MOD_STANDARD_ISDBC_QAM256)
#define MOD_DVBT_QPSK (0x00)
#define MOD_DVBT_16QAM (0x01)
#define MOD_DVBT_64QAM (0x02)
#define MOD_CONNECTOR_OFF (0x00)
#define MOD_CONNECTOR_F (0x01)
#define MOD_CONNECTOR_SMA (0x02)
#define MOD_UNIT_DBUV (0x00)
#define MOD_UNIT_DBM (0x01)
#define MOD_FORMAT_DEFAULT (0x00)
#define MOD_FORMAT_IQ16 (0x01)
#define MOD_FORMAT_IQ8 (0x02)
#define MOD_FORMAT_IDX8 (0x03)
#define MOD_FORMAT_TS (0x04)
#define MOD_DVBT_FFT_8K (0x01)
#define MOD_DVBT_GI_1_32 (0x00)
#define MOD_DVBT_GI_1_16 (0x01)
#define MOD_DVBT_GI_1_8 (0x02)
#define MOD_DVBT_GI_1_4 (0x03)
#define MOD_DVBT_PR_1_2 (0x00)
#define MOD_DVBT_PR_2_3 (0x01)
#define MOD_DVBT_PR_3_4 (0x02)
#define MOD_DVBT_PR_5_6 (0x03)
#define MOD_DVBT_PR_7_8 (0x04)
#define MOD_DVBT_QPSK (0x00)
#define MOD_DVBT_16QAM (0x01)
#define MOD_DVBT_64QAM (0x02)
#define MOD_QAM_DVBC_16 (0x00)
#define MOD_QAM_DVBC_32 (0x01)
#define MOD_QAM_DVBC_64 (0x02)
#define MOD_QAM_DVBC_128 (0x03)
#define MOD_QAM_DVBC_256 (0x04)
#define MOD_QAM_J83B_64 (0x05)
#define MOD_QAM_J83B_256 (0x06)
#define MOD_QAM_GENERIC (0x07)
#define MOD_QAM_ISDBC_64 (0x08)
#define MOD_QAM_ISDBC_256 (0x09)
#define CMD_GET_SERIALNUMBER (0xF0)
#define CMD_EXPORT_LICENSE (0xF0)
struct mod_setup_channels {
u8 flags;
@ -242,17 +276,29 @@ struct mod_setup_channels {
u32 bandwidth; /* used only when Standard == 0 */
};
struct mod_ofdm_parameter {
u8 fft_size; /* 0 = 2K, 1 = 8K (2K not yet supported) */
u8 guard_interval; /* 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4 (DVB-T Encoding) */
u8 puncture_rate; /* 0 = 1/2, 1 = 2/3, 2 = 3/4, 3 = 5/6, 4 = 7/8 (DVB-T Encoding) */
u8 constellation; /* MOD_DVBT_QPSK, MOD_DVBT_16QAM, MOD_DVBT_64QAM */
u8 rsvd2[2]; /* Reserved for DVB-T hierarchical */
u16 cell_identifier;
};
struct mod_qam_parameter {
u8 modulation;
u8 rolloff; /* Legal values: 12,13,15,18 */
};
struct mod_setup_stream {
u8 standard;
u8 stream_format;
u8 rsvd1[2];
u32 symbol_rate; /* only used when Standard doesn't define a fixed symbol rate */
u8 fft_size; /* 0 = 2K, 1 = 8K (2K yet supported) */
u8 guard_interval; /* 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4 (DVB-T Encoding) */
u8 puncture_rate; /* 0 = 1/2, 1 = 2/3, 2 = 3/4, 3 = 5/6, 4 = 7/8 (DVB-T Encoding) */
u8 constellation;
u8 rsvd2[2]; /* Reserved for DVB-T hierarchical */
u16 cell_identifier;
union {
struct mod_ofdm_parameter ofdm;
struct mod_qam_parameter qam;
};
};
struct mod_setup_output {
@ -283,6 +329,7 @@ struct mci_command {
};
union {
u32 params[31];
u8 params8[31*4];
struct {
u8 flags; /* Bit 0: DVB-S Enabled, 1: DVB-S2 Enabled,
5: ChannelBonding, 6: FrequencyRange, 7: InputStreamID */
@ -614,8 +661,8 @@ struct mci_result {
struct {
u8 tps_info[7];
// uint16_t tps_cell_id;
} DVBT_TPSInfo;
// u16 tps_cell_id;
} dvbt_tps_info;
struct {
struct {
@ -644,7 +691,7 @@ struct mci_result {
u8 CurrentRFIndex;
u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit
u8 CRC32[4];
} DVBT2_L1Pre;
} dvbt2_l1_pre;
struct {
u8 SubSlicesPerFrame[2];
@ -656,8 +703,8 @@ struct mci_result {
u8 FEFType;
u8 FEFLength[3];
u8 FEFInterval;
} DVBT2_L1Post;
} DVBT2_L1Info;
} dvbt2_l1_post;
} dvbt2_l1_info;
struct {
u8 PLPID;
@ -677,7 +724,7 @@ struct mci_result {
u8 TimeILType;
u8 InBandAFlag;
u8 InBandBFlag_Rsvd1_Mode_StaticFlag_StaticPaddingFlag[2]; // 1,11,2,1,1
} DVBT2_PLPInfo;
} dvbt2_plp_info;
struct {
u8 NetworkID[2];
@ -735,18 +782,18 @@ struct mci_result {
} DVBC2_PLPInfo;
struct {
u8 Valid;
u8 MATYPE_1;
u8 MATYPE_2;
u8 UPL[2];
u8 DFL[2];
u8 SYNC;
u8 SYNCD[2];
u8 valid;
u8 matype_1;
u8 matype_2;
u8 upl[2];
u8 dfl[2];
u8 sync;
u8 syncd[2];
u8 rsvd;
u8 ISSY[3];
u8 issy[3];
u8 min_input_stream_id;
u8 max_input_stream_id;
} BBHeader;
} bb_header;
struct {
u8 Mode; // FFT Mode 1,2,3
@ -776,12 +823,35 @@ struct mci_result {
u8 rsvd[13];
} sx8_bist;
struct {
u8 status;
u8 offset;
u8 length;
u8 rsvd2;
u32 rsvd3[2];
u8 data[96];
} SX8_packet_filter_status;
struct {
u8 version; /* 0 = none, 1 = SX8 */
u8 flags; /* Bit 0: 1 = Tuner Valid, Bit 1: 1 = Output Valid */
u8 tuner;
u8 output;
} extended_status;
struct {
u8 reserved;
u8 serial_number[17];
} serial_number;
struct {
u8 flags;
u8 serial_number[17];
u16 code;
u8 ID[8];
u8 LK[24];
} license;
};
u32 version[3];
u8 version_rsvd;
@ -904,8 +974,6 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p);
int mci_init(struct ddb_link *link);
int mci_cmd_val(struct ddb_link *link, u32 cmd, u32 val);
extern struct mci_cfg ddb_max_sx8_cfg;
extern struct mci_cfg ddb_max_m4_cfg;
#endif
#endif

View File

@ -23,8 +23,13 @@
#include "ddbridge.h"
#include "ddbridge-io.h"
#include "ddbridge-ioctl.h"
#ifdef KERNEL_DVB_CORE
#include "../include/linux/dvb/mod.h"
#else
#include <linux/dvb/mod.h>
#endif
#include <linux/gcd.h>
/****************************************************************************/
@ -164,11 +169,6 @@ static void mod_calc_rateinc(struct ddb_mod *mod)
{
u32 ri;
dev_info(mod->port->dev->dev,
"ibitrate %llu\n", mod->ibitrate);
dev_info(mod->port->dev->dev,
"obitrate %llu\n", mod->obitrate);
if (mod->ibitrate != 0) {
u64 d = mod->obitrate - mod->ibitrate;
@ -322,14 +322,21 @@ int ddbridge_mod_output_start(struct ddb_output *output)
CHANNEL_CONTROL(output->nr));
udelay(10);
ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr));
if (dev->link[0].info->version == 2) {
switch (dev->link[0].info->version) {
case 2:
{
u32 Output = (mod->frequency - 114000000) / 8000000;
u32 KF = Symbolrate;
u32 LF = 9000000UL;
u32 d = gcd(KF, LF);
u32 checkLF;
#if 0
if (dev->link[0].ids.revision == 1) {
mod->Control |= CHANNEL_CONTROL_ENABLE_DVB;
return -EINVAL;
break;
}
#endif
ddbwritel(dev, mod->modulation - 1, CHANNEL_SETTINGS(Channel));
ddbwritel(dev, Output, CHANNEL_SETTINGS2(Channel));
@ -356,16 +363,21 @@ int ddbridge_mod_output_start(struct ddb_output *output)
CHANNEL_CONTROL_CMD_SETUP))
return -EINVAL;
mod->Control |= CHANNEL_CONTROL_ENABLE_DVB;
} else if (dev->link[0].info->version <= 1) {
break;
}
case 0:
case 1:
/* QAM: 600 601 602 903 604 = 16 32 64 128 256 */
/* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */
ddbwritel(dev, qamtab[mod->modulation],
CHANNEL_SETTINGS(output->nr));
mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ |
CHANNEL_CONTROL_ENABLE_DVB);
} else if (dev->link[0].info->version >= 16) {
break;
default:
mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ |
CHANNEL_CONTROL_ENABLE_DVB);
break;
}
if (dev->link[0].info->version < 16) {
mod_set_rateinc(dev, output->nr);
@ -1653,7 +1665,11 @@ static int mod_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
return mod_set_attenuator(mod->port->dev, tvp->u.data);
case MODULATOR_INPUT_BITRATE:
#ifdef KERNEL_DVB_CORE
return mod_set_ibitrate(mod, *(u64 *) &tvp->u.buffer.data[0]);
#else
return mod_set_ibitrate(mod, tvp->u.data64);
#endif
case MODULATOR_GAIN:
if (mod->port->dev->link[0].info->version == 2)
@ -1844,6 +1860,27 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
mod->pcr_correction = cp->pcr_correction;
break;
}
case IOCTL_DDB_MCI_CMD:
{
struct ddb_mci_msg *msg =
(struct ddb_mci_msg __user *) parg;
struct ddb_link *link;
if (dev->link[0].ids.revision != 1)
break;
if (msg->link > 3) {
ret = -EFAULT;
break;
}
link = &dev->link[msg->link];
if (!link->mci_ok) {
ret = -EFAULT;
break;
}
ret = ddb_mci_cmd_link(link, &msg->cmd, &msg->res);
break;
}
default:
ret = -EINVAL;
break;
@ -1852,6 +1889,18 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
return ret;
}
static int mod_init_2_1(struct ddb *dev, u32 Frequency)
{
int i, streams = dev->link[0].info->port_num;
dev->mod_base.frequency = Frequency;
for (i = 0; i < streams; i++) {
struct ddb_mod *mod = &dev->mod[i];
mod->port = &dev->port[i];
}
return 0;
}
static int mod_init_2(struct ddb *dev, u32 Frequency)
{
int i, status, streams = dev->link[0].info->port_num;
@ -1863,8 +1912,6 @@ static int mod_init_2(struct ddb *dev, u32 Frequency)
dev_err(dev->dev, "FSM setup failed!\n");
return -1;
}
if (dev->link[0].ids.revision == 1)
return 0;
for (i = 0; i < streams; i++) {
struct ddb_mod *mod = &dev->mod[i];
@ -2031,8 +2078,6 @@ static int mod_init_sdr_iq(struct ddb *dev)
ddbwritel(dev, 0x01, 0x240);
if (dev->link[0].ids.revision == 1)
return 0;
//mod3_set_base_frequency(dev, 602000000);
dev->mod_base.frequency = 570000000;
@ -2040,9 +2085,11 @@ static int mod_init_sdr_iq(struct ddb *dev)
struct ddb_mod *mod = &dev->mod[i];
mod->port = &dev->port[i];
ddbwritel(dev, 0x00, SDR_CHANNEL_CONTROL(i));
if (dev->link[0].ids.revision != 1)
ddbwritel(dev, 0x00, SDR_CHANNEL_CONTROL(i));
}
if (dev->link[0].ids.revision == 1)
return ret;
mod_set_sdr_attenuator(dev, 0);
udelay(10);
mod_set_sdr_gain(dev, 120);

View File

@ -23,7 +23,6 @@
#include "ddbridge.h"
#include "ddbridge-io.h"
#include "ddbridge-i2c.h"
#include "ddbridge-mci.h"
static int default_mod = 3;
@ -556,7 +555,10 @@ static int set_input(struct dvb_frontend *fe, int input)
mutex_lock(&state->lock);
stop_iq(fe);
stop(fe);
state->mci.tuner = p->input = input;
state->mci.tuner = input;
#ifndef KERNEL_DVB_CORE
p->input = input;
#endif
mutex_unlock(&state->lock);
return 0;
}
@ -582,7 +584,6 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
static struct dvb_frontend_ops sx8_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2 },
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.info = {
.name = "DVB-S/S2X",
.frequency_min_hz = 950000000,
@ -602,7 +603,10 @@ static struct dvb_frontend_ops sx8_ops = {
.tune = tune,
.release = release,
.read_status = read_status,
#ifndef KERNEL_DVB_CORE
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.set_input = set_input,
#endif
.set_lna = set_lna,
.sleep = sleep,
};
@ -612,8 +616,10 @@ static int init(struct mci *mci)
struct sx8 *state = (struct sx8 *) mci;
state->mci.demod = SX8_DEMOD_NONE;
#ifndef KERNEL_DVB_CORE
mci->fe.ops.xbar[1] = mci->nr;
mci->fe.dtv_property_cache.input = mci->tuner;
#endif
mutex_init(&state->lock);
return 0;
}
@ -625,7 +631,7 @@ static int base_init(struct mci_base *mci_base)
return 0;
}
struct mci_cfg ddb_max_sx8_cfg = {
static struct mci_cfg ddb_max_sx8_cfg = {
.type = 0,
.fe_ops = &sx8_ops,
.base_size = sizeof(struct sx8_base),
@ -633,3 +639,10 @@ struct mci_cfg ddb_max_sx8_cfg = {
.init = init,
.base_init = base_init,
};
struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner,
int (**fn_set_input)(struct dvb_frontend *fe, int input))
{
*fn_set_input = set_input;
return ddb_mci_attach(input, &ddb_max_sx8_cfg, nr, tuner);
}

View File

@ -26,6 +26,9 @@
#include <linux/net.h>
#include "dvb_netstream.h"
int ddb_dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
int (*func)(struct file *file, unsigned int cmd, void *arg));
static ssize_t ns_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
@ -211,7 +214,7 @@ static int do_ioctl(struct file *file, unsigned int cmd, void *parg)
static long ns_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return dvb_usercopy(file, cmd, arg, do_ioctl);
return ddb_dvb_usercopy(file, cmd, arg, do_ioctl);
}
static const struct file_operations ns_fops = {

View File

@ -36,7 +36,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <asm/uaccess.h>
#include <linux/dvb/ns.h>
#include "ns.h"
#include <media/dvbdev.h>

76
ddbridge/ns.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef _UAPI_DVBNS_H_
#define _UAPI_DVBNS_H_
#include <linux/types.h>
struct dvb_ns_params {
__u8 smac[6];
__u8 dmac[6];
__u8 sip[16];
__u8 dip[16];
__u16 sport;
__u16 dport;
__u16 sport2;
__u16 dport2;
__u8 ssrc[8];
__u8 flags;
__u8 qos;
__u16 vlan;
__u8 ttl;
};
#define DVB_NS_IPV6 0x01
#define DVB_NS_RTP 0x02
#define DVB_NS_RTCP 0x04
#define DVB_NS_RTP_TO 0x08
#define DVB_NS_VLAN 0x10
struct dvb_ns_rtcp {
__u8 *msg;
__u16 len;
};
struct dvb_ns_packet {
__u8 *buf;
__u8 count;
};
struct dvb_nsd_ts {
__u16 pid;
__u16 num;
__u16 input;
__u16 timeout;
__u16 len;
__u8 *ts;
__u8 mode;
__u8 table;
__u8 filter_mask;
__u8 section;
__u16 section_id;
};
struct dvb_ns_cap {
__u8 streams_max;
__u8 reserved[127];
};
#define NS_SET_NET _IOW('o', 192, struct dvb_ns_params)
#define NS_START _IO('o', 193)
#define NS_STOP _IO('o', 194)
#define NS_SET_PID _IOW('o', 195, __u16)
#define NS_SET_PIDS _IOW('o', 196, __u8 *)
#define NS_SET_RTCP_MSG _IOW('o', 197, struct dvb_ns_rtcp)
#define NSD_START_GET_TS _IOWR('o', 198, struct dvb_nsd_ts)
#define NSD_STOP_GET_TS _IOWR('o', 199, struct dvb_nsd_ts)
#define NSD_CANCEL_GET_TS _IO('o', 200)
#define NSD_POLL_GET_TS _IOWR('o', 201, struct dvb_nsd_ts)
#define NS_SET_PACKETS _IOW('o', 202, struct dvb_ns_packet)
#define NS_INSERT_PACKETS _IOW('o', 203, __u8)
#define NS_SET_CI _IOW('o', 204, __u8)
#define NS_GET_CAP _IOR('o', 204, struct dvb_ns_cap))
#endif /*_UAPI_DVBNS_H_*/

View File

@ -28,3 +28,7 @@ devices in any way.
adapter_alloc=3 is rcommended when using redirect
The ci device will then show up in the same adapter directory and most
software will then assume it belongs to the frontend in the same directory.
Redirect between cards in different IOMMU groups will not work!
Disable IOMMU if you have this problem.

View File

@ -13,4 +13,3 @@ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
obj-$(CONFIG_DVB_CORE) += dvb-core.o
EXTRA_CFLAGS += -DCONFIG_DVB_DYNAMIC_MINORS -DCONFIG_DVB_NET
#NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux

View File

@ -11,3 +11,4 @@ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
obj-$(CONFIG_DVB_CORE) += dvb-core.o
ccflags-y += -Idrivers/media/dvb-core/
ccflags-y += --include=dd_compat.h

View File

@ -766,7 +766,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
ret = dmxdev->demux->allocate_section_feed(dmxdev->demux,
secfeed,
dvb_dmxdev_section_callback);
if (ret < 0) {
if (!*secfeed) {
pr_err("DVB (%s): could not alloc feed\n",
__func__);
return ret;

View File

@ -194,10 +194,10 @@ 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,
u8 *ebuf, int ecount);
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
u8 *ebuf, int ecount);
u8 *ebuf, int ecount, u8 flags);
/**
* Safely find needle in haystack.
* findstr - Safely find needle in haystack.
*
* @haystack: Buffer to look in.
* @hlen: Number of bytes in haystack.
@ -377,7 +377,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10);
if (ret)
return ret;
ret = dvb_ca_en50221_write_data(ca, slot, buf, 2);
ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW);
if (ret != 2)
return -EIO;
ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
@ -629,8 +629,8 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
* @ca: CA instance.
* @slot: Slot to read from.
* @ebuf: If non-NULL, the data will be written to this buffer. If NULL,
* the data will be added into the buffering system as a normal
* fragment.
* the data will be added into the buffering system as a normal
* fragment.
* @ecount: Size of ebuf. Ignored if ebuf is NULL.
*
* return: Number of bytes read, or < 0 on error
@ -783,20 +783,20 @@ exit:
* @ca: CA instance.
* @slot: Slot to write 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.
*
* return: Number of bytes written, or < 0 on error.
*/
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
u8 *buf, int bytes_write)
u8 *buf, int bytes_write, u8 flags)
{
struct dvb_ca_slot *sl = &ca->slot_info[slot];
int status;
int i;
dprintk("%s\n", __func__);
flags=0;
/* sanity check */
if (bytes_write > sl->link_buf_size)
return -EINVAL;
@ -824,7 +824,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
/* OK, set HC bit */
status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
IRQEN | CMDREG_HC);
IRQEN | CMDREG_HC | flags);
if (status)
goto exit;
@ -894,7 +894,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
buf[0], (buf[1] & 0x80) == 0, bytes_write);
exit:
ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | flags);
exitnowrite:
return status;
@ -1013,7 +1013,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
/* EN50221 thread functions */
/**
* Wake up the DVB CA thread
* dvb_ca_en50221_thread_wakeup - Wake up the DVB CA thread
*
* @ca: CA instance.
*/
@ -1027,7 +1027,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
}
/**
* Update the delay used by the thread.
* dvb_ca_en50221_thread_update_delay - Update the delay used by the thread.
*
* @ca: CA instance.
*/
@ -1085,7 +1085,7 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
}
/**
* Poll if the CAM is gone.
* dvb_ca_en50221_poll_cam_gone - Poll if the CAM is gone.
*
* @ca: CA instance.
* @slot: Slot to process.
@ -1116,7 +1116,8 @@ static int dvb_ca_en50221_poll_cam_gone(struct dvb_ca_private *ca, int slot)
}
/**
* Thread state machine for one CA slot to perform the data transfer.
* dvb_ca_en50221_thread_state_machine - Thread state machine for one CA slot
* to perform the data transfer.
*
* @ca: CA instance.
* @slot: Slot to process.
@ -1268,7 +1269,7 @@ static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca,
sl->slot_state = DVB_CA_SLOTSTATE_RUNNING;
dvb_ca_en50221_thread_update_delay(ca);
pr_info("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n",
ca->dvbdev->adapter->num);
ca->dvbdev->adapter->num);
break;
case DVB_CA_SLOTSTATE_RUNNING:
@ -1347,13 +1348,14 @@ static int dvb_ca_en50221_thread(void *data)
/* EN50221 IO interface functions */
/**
* Real ioctl implementation.
* NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them.
* dvb_ca_en50221_io_do_ioctl - Real ioctl implementation.
*
* @file: File concerned.
* @cmd: IOCTL command.
* @parg: Associated argument.
*
* NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them.
*
* return: 0 on success, <0 on error.
*/
static int dvb_ca_en50221_io_do_ioctl(struct file *file,
@ -1407,7 +1409,9 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file,
err = -EINVAL;
goto out_unlock;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
slot = array_index_nospec(slot, ca->slot_count);
#endif
info->type = CA_CI_LINK;
info->flags = 0;
sl = &ca->slot_info[slot];
@ -1431,7 +1435,7 @@ out_unlock:
}
/**
* Wrapper for ioctl implementation.
* dvb_ca_en50221_io_ioctl - Wrapper for ioctl implementation.
*
* @file: File concerned.
* @cmd: IOCTL command.
@ -1446,7 +1450,7 @@ static long dvb_ca_en50221_io_ioctl(struct file *file,
}
/**
* Implementation of write() syscall.
* dvb_ca_en50221_io_write - Implementation of write() syscall.
*
* @file: File structure.
* @buf: Source buffer.
@ -1529,7 +1533,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
mutex_lock(&sl->slot_lock);
status = dvb_ca_en50221_write_data(ca, slot, fragbuf,
fraglen + 2);
fraglen + 2, 0);
mutex_unlock(&sl->slot_lock);
if (status == (fraglen + 2)) {
written = 1;
@ -1603,7 +1607,7 @@ nextslot:
}
/**
* Implementation of read() syscall.
* dvb_ca_en50221_io_read - Implementation of read() syscall.
*
* @file: File structure.
* @buf: Destination buffer.
@ -1714,7 +1718,7 @@ exit:
}
/**
* Implementation of file open syscall.
* dvb_ca_en50221_io_open - Implementation of file open syscall.
*
* @inode: Inode concerned.
* @file: File concerned.
@ -1764,7 +1768,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
}
/**
* Implementation of file close syscall.
* dvb_ca_en50221_io_release - Implementation of file close syscall.
*
* @inode: Inode concerned.
* @file: File concerned.
@ -1793,7 +1797,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
}
/**
* Implementation of poll() syscall.
* dvb_ca_en50221_io_poll - Implementation of poll() syscall.
*
* @file: File concerned.
* @wait: poll wait table.
@ -1855,7 +1859,7 @@ static const struct dvb_device dvbdev_ca = {
/* Initialisation/shutdown functions */
/**
* Initialise a new DVB CA EN50221 interface device.
* dvb_ca_en50221_init - Initialise a new DVB CA EN50221 interface device.
*
* @dvb_adapter: DVB adapter to attach the new CA device to.
* @pubca: The dvb_ca instance.
@ -1947,7 +1951,7 @@ exit:
EXPORT_SYMBOL(dvb_ca_en50221_init);
/**
* Release a DVB CA EN50221 interface device.
* dvb_ca_en50221_release - Release a DVB CA EN50221 interface device.
*
* @pubca: The associated dvb_ca instance.
*/

View File

@ -20,6 +20,7 @@
#include <linux/version.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
#include <linux/sched/signal.h>
#include <linux/nospec.h>
#else
#include <linux/sched.h>
#endif
@ -487,6 +488,10 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
if (fepriv->max_drift)
dev_warn(fe->dvb->device,
"Frontend requested software zigzag, but didn't set the frequency step size\n");
/* if we've got no parameters, just keep idling */
if (fepriv->state & FESTATE_IDLE) {
fepriv->delay = 3 * HZ;
@ -990,6 +995,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
fe->ops.info.symbol_rate_max);
return -EINVAL;
}
break;
default:
break;
}
@ -1065,108 +1071,100 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
return 0;
}
#define _DTV_CMD(n, s, b) \
[n] = { \
.name = #n, \
.cmd = n, \
.set = s,\
.buffer = b \
}
#define _DTV_CMD(n) \
[n] = #n
struct dtv_cmds_h {
char *name; /* A display name for debugging purposes */
__u32 cmd; /* A unique ID */
/* Flags */
__u32 set:1; /* Either a set or get property */
__u32 buffer:1; /* Does this property use the buffer? */
__u32 reserved:30; /* Align */
};
static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_TUNE, 1, 0),
_DTV_CMD(DTV_CLEAR, 1, 0),
static char *dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_TUNE),
_DTV_CMD(DTV_CLEAR),
/* Set */
_DTV_CMD(DTV_FREQUENCY, 1, 0),
_DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0),
_DTV_CMD(DTV_MODULATION, 1, 0),
_DTV_CMD(DTV_INVERSION, 1, 0),
_DTV_CMD(DTV_DISEQC_MASTER, 1, 1),
_DTV_CMD(DTV_SYMBOL_RATE, 1, 0),
_DTV_CMD(DTV_INNER_FEC, 1, 0),
_DTV_CMD(DTV_VOLTAGE, 1, 0),
_DTV_CMD(DTV_TONE, 1, 0),
_DTV_CMD(DTV_PILOT, 1, 0),
_DTV_CMD(DTV_ROLLOFF, 1, 0),
_DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0),
_DTV_CMD(DTV_HIERARCHY, 1, 0),
_DTV_CMD(DTV_CODE_RATE_HP, 1, 0),
_DTV_CMD(DTV_CODE_RATE_LP, 1, 0),
_DTV_CMD(DTV_GUARD_INTERVAL, 1, 0),
_DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0),
_DTV_CMD(DTV_INTERLEAVING, 1, 0),
_DTV_CMD(DTV_FREQUENCY),
_DTV_CMD(DTV_BANDWIDTH_HZ),
_DTV_CMD(DTV_MODULATION),
_DTV_CMD(DTV_INVERSION),
_DTV_CMD(DTV_DISEQC_MASTER),
_DTV_CMD(DTV_SYMBOL_RATE),
_DTV_CMD(DTV_INNER_FEC),
_DTV_CMD(DTV_VOLTAGE),
_DTV_CMD(DTV_TONE),
_DTV_CMD(DTV_PILOT),
_DTV_CMD(DTV_ROLLOFF),
_DTV_CMD(DTV_DELIVERY_SYSTEM),
_DTV_CMD(DTV_HIERARCHY),
_DTV_CMD(DTV_CODE_RATE_HP),
_DTV_CMD(DTV_CODE_RATE_LP),
_DTV_CMD(DTV_GUARD_INTERVAL),
_DTV_CMD(DTV_TRANSMISSION_MODE),
_DTV_CMD(DTV_INTERLEAVING),
_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0),
_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0),
_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0),
_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION),
_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING),
_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYER_ENABLED),
_DTV_CMD(DTV_ISDBT_LAYERA_FEC),
_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION),
_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING),
_DTV_CMD(DTV_ISDBT_LAYERB_FEC),
_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION),
_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING),
_DTV_CMD(DTV_ISDBT_LAYERC_FEC),
_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION),
_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING),
_DTV_CMD(DTV_STREAM_ID, 1, 0),
_DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY, 1, 0),
_DTV_CMD(DTV_SCRAMBLING_SEQUENCE_INDEX, 1, 0),
_DTV_CMD(DTV_LNA, 1, 0),
_DTV_CMD(DTV_INPUT, 1, 0),
_DTV_CMD(DTV_STREAM_ID),
_DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY),
_DTV_CMD(DTV_SCRAMBLING_SEQUENCE_INDEX),
_DTV_CMD(DTV_LNA),
_DTV_CMD(DTV_INPUT),
/* Get */
_DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
_DTV_CMD(DTV_API_VERSION, 0, 0),
_DTV_CMD(DTV_DISEQC_SLAVE_REPLY),
_DTV_CMD(DTV_API_VERSION),
_DTV_CMD(DTV_ENUM_DELSYS, 0, 0),
_DTV_CMD(DTV_ENUM_DELSYS),
_DTV_CMD(DTV_ATSCMH_PARADE_ID, 1, 0),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0),
_DTV_CMD(DTV_ATSCMH_PARADE_ID),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE),
_DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0),
_DTV_CMD(DTV_ATSCMH_NOG, 0, 0),
_DTV_CMD(DTV_ATSCMH_TNOG, 0, 0),
_DTV_CMD(DTV_ATSCMH_SGN, 0, 0),
_DTV_CMD(DTV_ATSCMH_PRC, 0, 0),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
_DTV_CMD(DTV_ATSCMH_FIC_VER),
_DTV_CMD(DTV_ATSCMH_NOG),
_DTV_CMD(DTV_ATSCMH_TNOG),
_DTV_CMD(DTV_ATSCMH_SGN),
_DTV_CMD(DTV_ATSCMH_PRC),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC),
_DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D),
/* Statistics API */
_DTV_CMD(DTV_STAT_SIGNAL_STRENGTH, 0, 0),
_DTV_CMD(DTV_STAT_CNR, 0, 0),
_DTV_CMD(DTV_STAT_PRE_ERROR_BIT_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_PRE_TOTAL_BIT_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_ERROR_BLOCK_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0),
_DTV_CMD(DTV_STAT_SIGNAL_STRENGTH),
_DTV_CMD(DTV_STAT_CNR),
_DTV_CMD(DTV_STAT_PRE_ERROR_BIT_COUNT),
_DTV_CMD(DTV_STAT_PRE_TOTAL_BIT_COUNT),
_DTV_CMD(DTV_STAT_POST_ERROR_BIT_COUNT),
_DTV_CMD(DTV_STAT_POST_TOTAL_BIT_COUNT),
_DTV_CMD(DTV_STAT_ERROR_BLOCK_COUNT),
_DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT),
};
static char *dtv_cmd_name(u32 cmd)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
cmd = array_index_nospec(cmd, DTV_MAX_COMMAND);
#endif
return dtv_cmds[cmd];
}
/* Synchronise the legacy tuning parameters into the cache, so that demodulator
* drivers can use a single set_frontend tuning function, regardless of whether
* it's being used for the legacy or new API, reducing code and complexity.
@ -1349,8 +1347,9 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
struct file *file)
{
int ncaps;
unsigned int len = 1;
switch(tvp->cmd) {
switch (tvp->cmd) {
case DTV_ENUM_DELSYS:
ncaps = 0;
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
@ -1358,6 +1357,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
ncaps++;
}
tvp->u.buffer.len = ncaps;
len = ncaps;
break;
case DTV_FREQUENCY:
tvp->u.data = c->frequency;
@ -1543,27 +1543,51 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
/* Fill quality measures */
case DTV_STAT_SIGNAL_STRENGTH:
tvp->u.st = c->strength;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_CNR:
tvp->u.st = c->cnr;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_PRE_ERROR_BIT_COUNT:
tvp->u.st = c->pre_bit_error;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_PRE_TOTAL_BIT_COUNT:
tvp->u.st = c->pre_bit_count;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_POST_ERROR_BIT_COUNT:
tvp->u.st = c->post_bit_error;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_POST_TOTAL_BIT_COUNT:
tvp->u.st = c->post_bit_count;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_ERROR_BLOCK_COUNT:
tvp->u.st = c->block_error;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
case DTV_STAT_TOTAL_BLOCK_COUNT:
tvp->u.st = c->block_count;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break;
default:
dev_dbg(fe->dvb->device,
@ -1572,18 +1596,13 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
return -EINVAL;
}
if (!dtv_cmds[tvp->cmd].buffer)
dev_dbg(fe->dvb->device,
"%s: GET cmd 0x%08x (%s) = 0x%08x\n",
__func__, tvp->cmd, dtv_cmds[tvp->cmd].name,
tvp->u.data);
else
dev_dbg(fe->dvb->device,
"%s: GET cmd 0x%08x (%s) len %d: %*ph\n",
__func__,
tvp->cmd, dtv_cmds[tvp->cmd].name,
tvp->u.buffer.len,
tvp->u.buffer.len, tvp->u.buffer.data);
if (len < 1)
len = 1;
dev_dbg(fe->dvb->device,
"%s: GET cmd 0x%08x (%s) len %d: %*ph\n",
__func__, tvp->cmd, dtv_cmd_name(tvp->cmd),
tvp->u.buffer.len, tvp->u.buffer.len, tvp->u.buffer.data);
return 0;
}
@ -1806,6 +1825,53 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
return emulate_delivery_system(fe, delsys);
}
static void prepare_tuning_algo_parameters(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_frontend_tune_settings fetunesettings = { 0 };
/* get frontend-specific tuning settings */
if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
fepriv->max_drift = fetunesettings.max_drift;
fepriv->step_size = fetunesettings.step_size;
} else {
/* default values */
switch (c->delivery_system) {
case SYS_DVBS:
case SYS_DVBS2:
case SYS_ISDBS:
case SYS_TURBO:
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
fepriv->min_delay = HZ / 20;
fepriv->step_size = c->symbol_rate / 16000;
fepriv->max_drift = c->symbol_rate / 2000;
break;
case SYS_DVBT:
case SYS_DVBT2:
case SYS_ISDBT:
case SYS_DTMB:
fepriv->min_delay = HZ / 20;
fepriv->step_size = dvb_frontend_get_stepsize(fe) * 2;
fepriv->max_drift = fepriv->step_size + 1;
break;
default:
/*
* FIXME: This sounds wrong! if freqency_stepsize is
* defined by the frontend, why not use it???
*/
fepriv->min_delay = HZ / 20;
fepriv->step_size = 0; /* no zigzag */
fepriv->max_drift = 0;
break;
}
}
if (dvb_override_tune_delay > 0)
fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
}
/**
* dtv_property_process_set - Sets a single DTV property
* @fe: Pointer to &struct dvb_frontend
@ -1834,7 +1900,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
else
dev_dbg(fe->dvb->device,
"%s: SET cmd 0x%08x (%s) to 0x%08x\n",
__func__, cmd, dtv_cmds[cmd].name, data);
__func__, cmd, dtv_cmd_name(cmd), data);
switch (cmd) {
case DTV_CLEAR:
/*
@ -2204,7 +2270,6 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_frontend_tune_settings fetunesettings;
u32 rolloff = 0;
if (dvb_frontend_check_parameters(fe) < 0)
@ -2282,46 +2347,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE)
c->code_rate_LP = FEC_AUTO;
/* get frontend-specific tuning settings */
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
fepriv->max_drift = fetunesettings.max_drift;
fepriv->step_size = fetunesettings.step_size;
} else {
/* default values */
switch (c->delivery_system) {
case SYS_DVBS:
case SYS_DVBS2:
case SYS_ISDBS:
case SYS_TURBO:
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
fepriv->min_delay = HZ / 20;
fepriv->step_size = c->symbol_rate / 16000;
fepriv->max_drift = c->symbol_rate / 2000;
break;
case SYS_DVBT:
case SYS_DVBT2:
case SYS_ISDBT:
case SYS_DTMB:
fepriv->min_delay = HZ / 20;
fepriv->step_size = dvb_frontend_get_stepsize(fe) * 2;
fepriv->max_drift = (dvb_frontend_get_stepsize(fe) * 2) + 1;
break;
default:
/*
* FIXME: This sounds wrong! if freqency_stepsize is
* defined by the frontend, why not use it???
*/
fepriv->min_delay = HZ / 20;
fepriv->step_size = 0; /* no zigzag */
fepriv->max_drift = 0;
break;
}
}
if (dvb_override_tune_delay > 0)
fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
prepare_tuning_algo_parameters(fe);
fepriv->state = FESTATE_RETUNE;
@ -2336,7 +2362,6 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
return 0;
}
static int dvb_get_property(struct dvb_frontend *fe, struct file *file,
struct dtv_properties *tvps)
{

View File

@ -215,7 +215,7 @@ static int ule_exthdr_padding(struct dvb_net_priv *p)
}
/*
* Handle ULE extension headers.
* Handle ULE extension headers.
* Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
* Returns: >= 0: nr. of bytes consumed by next extension header
* -1: Mandatory extension header that is not recognized or TEST SNDU; discard.
@ -553,7 +553,7 @@ static int dvb_net_ule_new_payload(struct dvb_net_ule_handle *h)
h->priv->ule_sndu_type_1 = 1;
h->ts_remain -= 1;
h->from_where += 1;
/* fallthrough */
fallthrough;
case 0:
h->new_ts = 1;
h->ts += TS_SZ;
@ -1018,7 +1018,7 @@ static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static int dvb_net_filter_sec_set(struct net_device *dev,
struct dmx_section_filter **secfilter,
u8 *mac, u8 *mac_mask)
const u8 *mac, u8 *mac_mask)
{
struct dvb_net_priv *priv = netdev_priv(dev);
int ret;
@ -1062,7 +1062,7 @@ static int dvb_net_feed_start(struct net_device *dev)
int ret = 0, i;
struct dvb_net_priv *priv = netdev_priv(dev);
struct dmx_demux *demux = priv->demux;
unsigned char *mac = (unsigned char *) dev->dev_addr;
const unsigned char *mac = (unsigned char *) dev->dev_addr;
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
mutex_lock(&priv->mutex);

View File

@ -79,13 +79,17 @@ static const char * const dnames[] = {
static const u8 minor_type[] = {
[DVB_DEVICE_VIDEO] = 0,
[DVB_DEVICE_AUDIO] = 1,
[DVB_DEVICE_SEC] = 2,
[DVB_DEVICE_SEC] = 2,
[DVB_DEVICE_FRONTEND] = 3,
[DVB_DEVICE_DEMUX] = 4,
[DVB_DEVICE_DVR] = 5,
[DVB_DEVICE_CA] = 6,
[DVB_DEVICE_NET] = 7,
[DVB_DEVICE_OSD] = 8,
[DVB_DEVICE_CI] = 9,
[DVB_DEVICE_MOD] = 10,
[DVB_DEVICE_NS] = 11,
[DVB_DEVICE_NSD] = 12,
};
#define nums2minor(num, type, id) \
@ -248,6 +252,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
if (dvbdev->adapter->conn) {
media_device_unregister_entity(dvbdev->adapter->conn);
kfree(dvbdev->adapter->conn);
dvbdev->adapter->conn = NULL;
kfree(dvbdev->adapter->conn_pads);
dvbdev->adapter->conn_pads = NULL;
@ -346,7 +351,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
if (npads) {
dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
GFP_KERNEL);
if (!dvbdev->pads){
if (!dvbdev->pads) {
kfree(dvbdev->entity);
return -ENOMEM;
}
@ -512,6 +517,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
break;
if (minor == MAX_DVB_MINORS) {
list_del (&dvbdev->list_head);
kfree(dvbdevfops);
kfree(dvbdev);
up_write(&minor_rwsem);
@ -532,6 +538,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
__func__);
dvb_media_device_free(dvbdev);
list_del (&dvbdev->list_head);
kfree(dvbdevfops);
kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock);
@ -546,6 +553,10 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
if (IS_ERR(clsdev)) {
pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
dvb_media_device_free(dvbdev);
list_del (&dvbdev->list_head);
kfree(dvbdevfops);
kfree(dvbdev);
return PTR_ERR(clsdev);
}
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
@ -687,7 +698,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
ret = media_device_register_entity(mdev, conn);
if (ret)
return ret;
if (!ntuner) {
ret = media_create_pad_links(mdev,
MEDIA_ENT_F_CONN_RF,
@ -987,7 +998,7 @@ struct i2c_client *dvb_module_probe(const char *module_name,
unsigned char addr,
void *platform_data)
{
struct i2c_client *client;
struct i2c_client *client;
struct i2c_board_info *board_info;
board_info = kzalloc(sizeof(*board_info), GFP_KERNEL);

View File

@ -4,6 +4,7 @@
ccflags-y += -I$(srctree)/drivers/media/dvb-core/
ccflags-y += -I$(srctree)/drivers/media/tuners/
ccflags-y += --include=dd_compat.h
# FIXME: RTL2832 SDR driver uses power management directly from USB IF driver
ifdef CONFIG_DVB_RTL2832_SDR

View File

@ -1566,7 +1566,7 @@ static int SetOperationMode(struct drxk_state *state, enum OperationMode oMode)
case OM_QAM_ITU_B:
status = -1;
break;
case OM_QAM_ITU_A: /* fallthrough */
case OM_QAM_ITU_A:
case OM_QAM_ITU_C:
CHK_ERROR(MPEGTSStop(state));
CHK_ERROR(PowerDownQAM(state));
@ -1589,7 +1589,7 @@ static int SetOperationMode(struct drxk_state *state, enum OperationMode oMode)
case OM_QAM_ITU_B:
status = -1;
break;
case OM_QAM_ITU_A: /* fallthrough */
case OM_QAM_ITU_A:
case OM_QAM_ITU_C:
state->m_OperationMode = oMode;
CHK_ERROR(SetQAMStandard(state,oMode));
@ -1765,7 +1765,7 @@ static int MPEGTSDtoSetup(struct drxk_state *state, enum OperationMode oMode)
fecOcRcnCtlRate = 0xC00000;
staticCLK = state->m_DVBTStaticCLK;
break;
case OM_QAM_ITU_A: /* fallthrough */
case OM_QAM_ITU_A:
case OM_QAM_ITU_C:
fecOcTmdMode = 0x0004;
fecOcRcnCtlRate = 0xD2B4EE; /* good for >63 Mb/s */
@ -2804,12 +2804,12 @@ static int DVBTScCommand(struct drxk_state *state,
case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
status = Write16_0(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
/* All commands using 1 parameters */
/* fall through */
fallthrough;
case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
case OFDM_SC_RA_RAM_CMD_USER_IO:
status = Write16_0(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
/* All commands using 0 parameters */
/* fall through */
fallthrough;
case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
case OFDM_SC_RA_RAM_CMD_NULL:
/* Write command */
@ -3218,7 +3218,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
/* try first guess DRX_FFTMODE_8K */
/* fall through */
fallthrough;
case TRANSMISSION_MODE_8K:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
break;
@ -3237,7 +3237,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
case GUARD_INTERVAL_AUTO:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
/* try first guess DRX_GUARD_1DIV4 */
/* fall through */
fallthrough;
case GUARD_INTERVAL_1_4:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
break;
@ -3265,7 +3265,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
/* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
// transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO;
//break;
/* fall through */
fallthrough;
case HIERARCHY_1:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
break;
@ -3288,7 +3288,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
/* try first guess DRX_CONSTELLATION_QAM64 */
/* fall through */
fallthrough;
case QAM_64:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
break;
@ -3311,8 +3311,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
WR16(devAddr, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI));
break;
case DRX_PRIORITY_UNKNOWN : /* fall through */
default:
case DRX_PRIORITY_UNKNOWN:
default:
return (DRX_STS_INVALID_ARG);
break;
}
@ -3332,7 +3332,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
/* try first guess DRX_CODERATE_2DIV3 */
/* fall through */
fallthrough;
case FEC_2_3 :
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
break;

View File

@ -786,7 +786,7 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
default:
break;
}
/* fallthrough */
fallthrough;
case SYS_DVBS:
switch ((MXL_HYDRA_MODULATION_E)
regData[DMD_MODULATION_SCHEME_ADDR]) {
@ -825,13 +825,15 @@ static int set_input(struct dvb_frontend *fe, int input)
struct mxl *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
state->tuner = p->input = input;
state->tuner = input;
#ifndef KERNEL_DVB_CORE
p->input = input;
#endif
return 0;
}
static struct dvb_frontend_ops mxl_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.info = {
.name = "MXL5XX",
.frequency_min_hz = 300000000,
@ -856,7 +858,10 @@ static struct dvb_frontend_ops mxl_ops = {
.read_signal_strength = read_signal_strength,
.read_ucblocks = read_ucblocks,
.get_frontend = get_frontend,
#ifndef KERNEL_DVB_CORE
.set_input = set_input,
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
#endif
.diseqc_send_master_cmd = send_master_cmd,
};
@ -1873,7 +1878,8 @@ static int probe(struct mxl *state, struct mxl5xx_cfg *cfg)
struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner)
u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int))
{
struct mxl *state;
struct mxl_base *base;
@ -1913,9 +1919,12 @@ struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
list_add(&base->mxllist, &mxllist);
}
state->fe.ops = mxl_ops;
#ifndef KERNEL_DVB_CORE
state->fe.ops.xbar[1] = demod;
state->fe.demodulator_priv = state;
state->fe.dtv_property_cache.input = tuner;
#endif
state->fe.demodulator_priv = state;
*fn_set_input = set_input;
list_add(&state->mxl, &base->mxls);
return &state->fe;

View File

@ -23,12 +23,15 @@ struct mxl5xx_cfg {
extern struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner);
u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int));
#else
static inline struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner)
u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int))
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;

31
include/dd_compat.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
#ifndef fallthrough
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
# define fallthrough do {} while (0) /* fallthrough */
#endif
#endif
#ifdef KERNEL_DVB_CORE
#define DVB_DEVICE_CI 0
#define DVB_DEVICE_MOD 6
#define DVB_DEVICE_NS 7
#define DVB_DEVICE_NSD 8
#define SYS_DVBC2 19
#define ROLLOFF_15 4
#define ROLLOFF_10 5
#define ROLLOFF_5 6
#define FEC_1_4 13
#define FEC_1_3 14
#define APSK_64 14
#define APSK_128 15
#define APSK_256 16
#endif

View File

@ -330,7 +330,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
int dvb_generic_open(struct inode *inode, struct file *file);
/**
* dvb_generic_close - Digital TV close function, used by DVB devices
* dvb_generic_release - Digital TV close function, used by DVB devices
*
* @inode: pointer to &struct inode.
* @file: pointer to &struct file.
@ -425,11 +425,12 @@ void dvb_module_release(struct i2c_client *client);
/* Legacy generic DVB attach function. */
#ifdef CONFIG_MEDIA_ATTACH
/**
* dvb_attach - attaches a DVB frontend into the DVB core.
*
* @FUNCTION: function on a frontend module to be called.
* @ARGS...: @FUNCTION arguments.
* @ARGS: @FUNCTION arguments.
*
* This ancillary function loads a frontend module in runtime and runs
* the @FUNCTION function there, with @ARGS.

View File

@ -309,20 +309,22 @@ int main(int argc, char **argv)
{"tscheck", no_argument, 0, 't'},
{"tscheck_l", required_argument, 0, 'a'},
{"nodvr", no_argument , 0, 'q'},
{"pam", no_argument , 0, 'a'},
{"pam", no_argument , 0, 'P'},
{"pam_color", no_argument , 0, 'e'},
{"help", no_argument , 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"e:c:i:f:s:d:p:hg:r:n:b:l:v:m:ota:q",
"e:c:i:f:s:d:p:hg:r:n:b:l:v:m:ota:qP",
long_options, &option_index);
if (c==-1)
break;
switch (c) {
case 'e':
odvr = 2;
color = strtoul(optarg, NULL, 0);
case 'P':
odvr = 2;
break;
case 'o':
fout = stderr;
@ -342,7 +344,7 @@ int main(int argc, char **argv)
break;
}
fprintf(fout,"performing continuity check\n");
odvr = 2;
odvr = 3;
break;
case 'c':
config = strdup(optarg);
@ -436,7 +438,10 @@ int main(int argc, char **argv)
" [-g gold_code] [-r root_code] [-i id] [-n device_num]\n"
" [-o (write dvr to stdout)]\n"
" [-l (tuner source for unicable)]\n"
" [-t [display line](continuity check)]\n"
" [-t (continuity check)]\n"
" [-a [display line] (display continuity check in line)]\n"
" [-P (output IQ diagram as pam)]\n"
" [-e [color] (use color for pam 0=green)]\n"
"\n"
" delivery_system = C,S,S2,T,T2,J83B,ISDBC,ISDBT\n"
" polarity = h/H,v/V\n"
@ -507,8 +512,8 @@ int main(int argc, char **argv)
str = dddvb_get_strength(fe);
cnr = dddvb_get_cnr(fe);
printf("stat=%02x, str=%" PRId64 ".%03udBm, "
"snr=%" PRId64 ".%03uddB \n",
printf("stat=%02x, str=%" PRId64 ".%03u dBm, "
"snr=%" PRId64 ".%03u dB\n",
stat, str/1000, abs(str%1000),
cnr/1000, abs(cnr%1000));
sleep(1);
@ -540,29 +545,28 @@ int main(int argc, char **argv)
if ((fd = open(filename ,O_RDONLY)) < 0){
fprintf(stderr,"Error opening input file:%s\n",filename);
}
if (odvr > 0){
switch (odvr){
case 1:
while(1){
read(fd,buf,BUFFSIZE);
write(fileno(stdout),buf,BUFFSIZE);
}
break;
case 2:
fprintf(stderr,"writing pamdata\n");
init_pamdata(&iq,color);
while(1){
pam_read_data(fd, &iq);
pam_write(STDOUT_FILENO, &iq);
}
break;
switch (odvr){
case 1:
while(1){
read(fd,buf,BUFFSIZE);
write(fileno(stdout),buf,BUFFSIZE);
}
} else {
break;
case 2:
fprintf(stderr,"writing pamdata\n");
init_pamdata(&iq,color);
while(1){
pam_read_data(fd, &iq);
pam_write(STDOUT_FILENO, &iq);
}
break;
case 3:
if( line >= 0 && line < 64 ){
snprintf(line_start,sizeof(line_start)-1,"\0337\033[%d;0H",line);
strncpy(line_end,"\0338",sizeof(line_end)-1);
}
tscheck(fd);
break;
}
}
}

View File

@ -111,6 +111,7 @@ static int set_fe_input(struct dddvb_fe *fe, uint32_t fr,
{ .cmd = DTV_INVERSION, .u.data = INVERSION_AUTO },
{ .cmd = DTV_SYMBOL_RATE, .u.data = sr },
{ .cmd = DTV_INNER_FEC, .u.data = FEC_AUTO },
{ .cmd = DTV_ROLLOFF, .u.data = ROLLOFF_AUTO },
};
struct dtv_properties c;
int ret;
@ -181,7 +182,7 @@ static int diseqc(int fd, int sat, int hor, int band)
return 0;
}
static int set_en50494(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
static int set_en50494(struct dddvb_fe *fe, uint32_t freq_khz, uint32_t sr,
int sat, int hor, int band,
uint32_t slot, uint32_t ubfreq,
fe_delivery_system_t ds)
@ -193,8 +194,10 @@ static int set_en50494(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
uint16_t t;
uint32_t input = 3 & (sat >> 6);
int fd = fe->fd;
uint32_t freq = (freq_khz + 2000) / 4000;
int32_t fdiff = freq_khz - freq * 1000;
t = (freq + ubfreq + 2) / 4 - 350;
t = (freq_khz / 1000 + ubfreq + 2) / 4 - 350;
hor &= 1;
cmd.msg[3] = ((t & 0x0300) >> 8) |
@ -218,7 +221,7 @@ static int set_en50494(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
cmd.msg[0], cmd.msg[1], cmd.msg[2], cmd.msg[3], cmd.msg[4]);
}
static int set_en50607(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
static int set_en50607(struct dddvb_fe *fe, uint32_t freq_khz, uint32_t sr,
int sat, int hor, int band,
uint32_t slot, uint32_t ubfreq,
fe_delivery_system_t ds)
@ -227,6 +230,8 @@ static int set_en50607(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
.msg = {0x70, 0x00, 0x00, 0x00, 0x00},
.msg_len = 4
};
uint32_t freq = (freq_khz + 500) / 1000;
int32_t fdiff = freq_khz - freq * 1000;
uint32_t t = freq - 100;
uint32_t input = 3 & (sat >> 6);
int fd = fe->fd;
@ -250,11 +255,11 @@ static int set_en50607(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
if (ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13) == -1)
perror("FE_SET_VOLTAGE failed");
set_fe_input(fe, ubfreq * 1000, sr, ds, input);
set_fe_input(fe, ubfreq * 1000 + fdiff, sr, ds, input);
dbgprintf(DEBUG_DVB, "EN50607 %02x %02x %02x %02x\n",
cmd.msg[0], cmd.msg[1], cmd.msg[2], cmd.msg[3]);
dbgprintf(DEBUG_DVB, "EN50607 freq %u sr %u hor %u\n",
freq, sr, hor);
dbgprintf(DEBUG_DVB, "EN50607 freq %u ubfreq %u fdiff %d sr %u hor %u\n",
freq, ubfreq, fdiff, sr, hor);
}
@ -288,14 +293,20 @@ static int tune_sat(struct dddvb_fe *fe)
freq = lofs - freq;
}
#endif
if (freq > 3000000) {
if (lofs)
hi = (freq > lofs) ? 1 : 0;
if (hi)
freq -= fe->lof2[lnbc];
else
freq -= fe->lof1[lnbc];
if (lofs > 10000000) {
if (hi)
freq -= fe->lof2[lnbc];
else
freq -= fe->lof1[lnbc];
} else {
if (hi)
freq = fe->lof2[lnbc] - freq;
else
freq = fe->lof1[lnbc] - freq;
}
}
dbgprintf(DEBUG_DVB, "tune_sat IF=%u\n", freq);
if (fe->first) {
@ -308,13 +319,13 @@ static int tune_sat(struct dddvb_fe *fe)
dbgprintf(DEBUG_DVB, "scif_type = %u\n", fe->scif_type);
if (fe->scif_type == 1) {
pthread_mutex_lock(&fe->dd->uni_lock);
set_en50494(fe, freq / 1000, fe->param.param[PARAM_SR],
set_en50494(fe, freq, fe->param.param[PARAM_SR],
lnb, fe->param.param[PARAM_POL], hi,
fe->scif_slot, fe->scif_freq, ds);
pthread_mutex_unlock(&fe->dd->uni_lock);
} else if (fe->scif_type == 2) {
pthread_mutex_lock(&fe->dd->uni_lock);
set_en50607(fe, freq / 1000, fe->param.param[PARAM_SR],
set_en50607(fe, freq, fe->param.param[PARAM_SR],
lnb, fe->param.param[PARAM_POL], hi,
fe->scif_slot, fe->scif_freq, ds);
pthread_mutex_unlock(&fe->dd->uni_lock);
@ -324,6 +335,7 @@ static int tune_sat(struct dddvb_fe *fe)
if (input != DDDVB_UNDEF) {
input = 3 & (input >> 6);
dbgprintf(DEBUG_DVB, "input = %u\n", input);
set_property(fe->fd, DTV_INPUT, input);
}
diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi);
set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input);