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:
commit
0cc91fbe5f
3
Makefile
3
Makefile
@ -14,6 +14,9 @@ libdddvb:
|
|||||||
libdddvb-install:
|
libdddvb-install:
|
||||||
$(MAKE) -C lib install
|
$(MAKE) -C lib install
|
||||||
|
|
||||||
|
libdddvb-clean:
|
||||||
|
$(MAKE) -C lib clean
|
||||||
|
|
||||||
dep:
|
dep:
|
||||||
DIR=`pwd`; (cd $(TOPDIR); make SUBDIRS=$$DIR dep)
|
DIR=`pwd`; (cd $(TOPDIR); make SUBDIRS=$$DIR dep)
|
||||||
|
|
||||||
|
16
apps/cit.c
16
apps/cit.c
@ -27,6 +27,7 @@ uint8_t fill[188]={0x47, 0x1f, 0xff, 0x10,
|
|||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
|
||||||
|
|
||||||
|
#if 0
|
||||||
uint8_t ts[188]={0x47, 0x0a, 0xaa, 0x00,
|
uint8_t ts[188]={0x47, 0x0a, 0xaa, 0x00,
|
||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
@ -40,6 +41,21 @@ uint8_t ts[188]={0x47, 0x0a, 0xaa, 0x00,
|
|||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
|
||||||
|
#else
|
||||||
|
uint8_t ts[188]={0x47, 0x0a, 0xaa, 0x00,
|
||||||
|
0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,
|
||||||
|
0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,
|
||||||
|
0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,
|
||||||
|
0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,
|
||||||
|
0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,
|
||||||
|
0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,
|
||||||
|
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
|
||||||
|
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
|
||||||
|
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
|
||||||
|
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
|
||||||
|
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,
|
||||||
|
0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa };
|
||||||
|
#endif
|
||||||
|
|
||||||
void proc_buf(uint8_t *buf, uint32_t *d)
|
void proc_buf(uint8_t *buf, uint32_t *d)
|
||||||
{
|
{
|
||||||
|
@ -238,7 +238,7 @@ int main(int argc, char **argv)
|
|||||||
printf("Octopus MAXM4\n");
|
printf("Octopus MAXM4\n");
|
||||||
break;
|
break;
|
||||||
case 0x0011:
|
case 0x0011:
|
||||||
fname="CIBridgeV1B_CIBridgeV1B.fpga";
|
fname="DVBBridgeV2B_DD01_0011.fpga";
|
||||||
printf("Octopus CI\n");
|
printf("Octopus CI\n");
|
||||||
break;
|
break;
|
||||||
case 0x0012:
|
case 0x0012:
|
||||||
@ -250,7 +250,7 @@ int main(int argc, char **argv)
|
|||||||
printf("Octopus PRO\n");
|
printf("Octopus PRO\n");
|
||||||
break;
|
break;
|
||||||
case 0x0020:
|
case 0x0020:
|
||||||
fname="DVBBridgeV2B_DD01_0020.fpga";
|
fname="DVBBridgeV2C_DD01_0020.fpga";
|
||||||
printf("Octopus GT Mini\n");
|
printf("Octopus GT Mini\n");
|
||||||
break;
|
break;
|
||||||
case 0x0201:
|
case 0x0201:
|
||||||
@ -273,6 +273,10 @@ int main(int argc, char **argv)
|
|||||||
fname="SDRModulatorV1A_DD01_0221_IQ.fpga";
|
fname="SDRModulatorV1A_DD01_0221_IQ.fpga";
|
||||||
printf("SDRModulator IQ\n");
|
printf("SDRModulator IQ\n");
|
||||||
break;
|
break;
|
||||||
|
case 0x0222:
|
||||||
|
fname="SDRModulatorV1A_DD01_0222_DVBT.fpga";
|
||||||
|
printf("SDRModulator DVBT\n");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("UNKNOWN\n");
|
printf("UNKNOWN\n");
|
||||||
break;
|
break;
|
||||||
@ -285,7 +289,7 @@ int main(int argc, char **argv)
|
|||||||
printf("Using bitstream %s\n", fname);
|
printf("Using bitstream %s\n", fname);
|
||||||
|
|
||||||
fsize = lseek(fh,0,SEEK_END);
|
fsize = lseek(fh,0,SEEK_END);
|
||||||
if( fsize > 4000000 || fsize < SectorSize )
|
if( fsize > FlashSize/2 - 0x10000 || fsize < SectorSize )
|
||||||
{
|
{
|
||||||
close(fh);
|
close(fh);
|
||||||
printf("Invalid File Size \n");
|
printf("Invalid File Size \n");
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#include <linux/dvb/mod.h>
|
#include <linux/dvb/mod.h>
|
||||||
|
|
||||||
@ -51,33 +52,96 @@ static int get_property(int fd, uint32_t cmd, uint32_t *data)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main(int argc, char*argv[])
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
struct dvb_mod_params mp;
|
struct dvb_mod_params mp;
|
||||||
struct dvb_mod_channel_params mc;
|
struct dvb_mod_channel_params mc;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
int adapter = 0, channel = 0, gain = -1;
|
||||||
|
int32_t base = -1, freq = -1, rate = -1;
|
||||||
|
char mod_name[128];
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int cur_optind = optind ? optind : 1;
|
||||||
|
int option_index = 0;
|
||||||
|
int c;
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"adapter", required_argument, 0, 'a'},
|
||||||
|
{"channel", required_argument, 0, 'c'},
|
||||||
|
{"gain", required_argument, 0, 'g'},
|
||||||
|
{"base", required_argument, 0, 'b'},
|
||||||
|
{"frequency", required_argument, 0, 'f'},
|
||||||
|
{"rate", required_argument, 0, 'r'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
c = getopt_long(argc, argv,
|
||||||
|
"a:c:g:b:f:r:",
|
||||||
|
long_options, &option_index);
|
||||||
|
if (c==-1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'a':
|
||||||
|
adapter = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
channel = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
gain = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
base = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
freq = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
if (!strcmp(optarg, "DVBT_8"))
|
||||||
|
rate = SYS_DVBT_8;
|
||||||
|
else if (!strcmp(optarg, "DVBT_7"))
|
||||||
|
rate = SYS_DVBT_7;
|
||||||
|
else if (!strcmp(optarg, "DVBT_6"))
|
||||||
|
rate = SYS_DVBT_6;
|
||||||
|
else if (!strcmp(optarg, "ISDBT_6"))
|
||||||
|
rate = SYS_ISDBT_6;
|
||||||
|
else rate = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (optind < argc) {
|
||||||
|
printf("too man arguments\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(mod_name, 127, "/dev/dvb/adapter%d/mod%d", adapter, channel);
|
||||||
|
fd = open(mod_name, O_RDONLY);
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
printf("Could not open modulator device.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
fd = open("/dev/dvb/adapter0/mod0", O_RDONLY);
|
|
||||||
|
|
||||||
/* gain 0-255 */
|
/* gain 0-255 */
|
||||||
get_property(fd, MODULATOR_GAIN, &data);
|
//get_property(fd, MODULATOR_GAIN, &data);
|
||||||
printf("Modulator gain = %u\n", data);
|
//printf("Modulator gain = %u\n", data);
|
||||||
set_property(fd, MODULATOR_GAIN, 100);
|
//set_property(fd, MODULATOR_GAIN, 100);
|
||||||
|
|
||||||
get_property(fd, MODULATOR_GAIN, &data);
|
//get_property(fd, MODULATOR_ATTENUATOR, &data);
|
||||||
printf("Modulator gain = %u\n", data);
|
//printf("Modulator attenuator = %u\n", data);
|
||||||
|
|
||||||
get_property(fd, MODULATOR_ATTENUATOR, &data);
|
if (base > 0)
|
||||||
printf("Modulator attenuator = %u\n", data);
|
set_property(fd, MODULATOR_BASE_FREQUENCY, base);
|
||||||
|
if (freq > 0)
|
||||||
|
set_property(fd, MODULATOR_FREQUENCY, base);
|
||||||
|
if (rate > 0)
|
||||||
|
set_property(fd, MODULATOR_OUTPUT_RATE, rate);
|
||||||
|
|
||||||
|
|
||||||
get_property(fd, MODULATOR_STATUS, &data);
|
|
||||||
printf("Modulator status = %u\n", data);
|
|
||||||
set_property(fd, MODULATOR_STATUS, 2);
|
|
||||||
|
|
||||||
|
|
||||||
//set_property(fd, MODULATOR_RESET, 0);
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* ddbridge-ci.c: Digital Devices bridge and DuoFlex CI driver
|
* ddbridge-ci.c: Digital Devices bridge and DuoFlex CI driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
* Copyright (C) 2010-2019 Digital Devices GmbH
|
||||||
* Ralph Metzler <rjkm@metzlerbros.de>
|
* Ralph Metzler <rjkm@metzlerbros.de>
|
||||||
* Marcus Metzler <mocm@metzlerbros.de>
|
* Marcus Metzler <mocm@metzlerbros.de>
|
||||||
*
|
*
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* ddbridge-core.c: Digital Devices bridge core functions
|
* ddbridge-core.c: Digital Devices bridge core functions
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2016 Digital Devices GmbH
|
* Copyright (C) 2010-2019 Digital Devices GmbH
|
||||||
* Marcus Metzler <mocm@metzlerbros.de>
|
* Marcus Metzler <mocm@metzlerbros.de>
|
||||||
* Ralph Metzler <rjkm@metzlerbros.de>
|
* Ralph Metzler <rjkm@metzlerbros.de>
|
||||||
*
|
*
|
||||||
@ -1105,7 +1105,7 @@ static void dummy_release(struct dvb_frontend *fe)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct dvb_frontend_ops dummy_ops = {
|
static struct dvb_frontend_ops dummy_ops = {
|
||||||
.delsys = { SYS_DVBC_ANNEX_A },
|
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBS, SYS_DVBS2 },
|
||||||
.info = {
|
.info = {
|
||||||
.name = "DUMMY DVB-C/C2 DVB-T/T2",
|
.name = "DUMMY DVB-C/C2 DVB-T/T2",
|
||||||
.frequency_stepsize = 166667, /* DVB-T only */
|
.frequency_stepsize = 166667, /* DVB-T only */
|
||||||
@ -1399,7 +1399,7 @@ static struct stv0910_cfg stv0910_p = {
|
|||||||
.parallel = 1,
|
.parallel = 1,
|
||||||
.rptlvl = 4,
|
.rptlvl = 4,
|
||||||
.clk = 30000000,
|
.clk = 30000000,
|
||||||
.tsspeed = 0x10,
|
.tsspeed = 0x20,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int has_lnbh25(struct i2c_adapter *i2c, u8 adr)
|
static int has_lnbh25(struct i2c_adapter *i2c, u8 adr)
|
||||||
@ -1524,6 +1524,7 @@ static void dvb_input_detach(struct ddb_input *input)
|
|||||||
case 0x41:
|
case 0x41:
|
||||||
if (dvb->fe2)
|
if (dvb->fe2)
|
||||||
dvb_unregister_frontend(dvb->fe2);
|
dvb_unregister_frontend(dvb->fe2);
|
||||||
|
/* fallthrough */
|
||||||
case 0x40:
|
case 0x40:
|
||||||
if (dvb->fe)
|
if (dvb->fe)
|
||||||
dvb_unregister_frontend(dvb->fe);
|
dvb_unregister_frontend(dvb->fe);
|
||||||
@ -1843,8 +1844,8 @@ static int dvb_input_attach(struct ddb_input *input)
|
|||||||
memcpy(&dvb->fe2->ops.tuner_ops,
|
memcpy(&dvb->fe2->ops.tuner_ops,
|
||||||
&dvb->fe->ops.tuner_ops,
|
&dvb->fe->ops.tuner_ops,
|
||||||
sizeof(struct dvb_tuner_ops));
|
sizeof(struct dvb_tuner_ops));
|
||||||
}
|
|
||||||
dvb->attached = 0x41;
|
dvb->attached = 0x41;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2071,7 +2072,8 @@ static void ddb_port_probe(struct ddb_port *port)
|
|||||||
/* Handle missing ports and ports without I2C */
|
/* Handle missing ports and ports without I2C */
|
||||||
|
|
||||||
if (dummy_tuner && !port->nr &&
|
if (dummy_tuner && !port->nr &&
|
||||||
link->ids.device == 0x0005) {
|
(link->ids.device == 0x0005 ||
|
||||||
|
link->ids.device == 0x000a)) {
|
||||||
port->name = "DUMMY";
|
port->name = "DUMMY";
|
||||||
port->class = DDB_PORT_TUNER;
|
port->class = DDB_PORT_TUNER;
|
||||||
port->type = DDB_TUNER_DUMMY;
|
port->type = DDB_TUNER_DUMMY;
|
||||||
@ -2561,7 +2563,7 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out, int irq_nr)
|
|||||||
dma->regs = rm->odma->base + rm->odma->size * nr;
|
dma->regs = rm->odma->base + rm->odma->size * nr;
|
||||||
dma->bufregs = rm->odma_buf->base + rm->odma_buf->size * nr;
|
dma->bufregs = rm->odma_buf->base + rm->odma_buf->size * nr;
|
||||||
if (io->port->dev->link[0].info->type == DDB_MOD &&
|
if (io->port->dev->link[0].info->type == DDB_MOD &&
|
||||||
io->port->dev->link[0].info->version == 3) {
|
io->port->dev->link[0].info->version >= 16) {
|
||||||
dma->num = OUTPUT_DMA_BUFS_SDR;
|
dma->num = OUTPUT_DMA_BUFS_SDR;
|
||||||
dma->size = OUTPUT_DMA_SIZE_SDR;
|
dma->size = OUTPUT_DMA_SIZE_SDR;
|
||||||
dma->div = 1;
|
dma->div = 1;
|
||||||
@ -3496,7 +3498,7 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||||||
|
|
||||||
if (copy_from_user(&i2c, parg, sizeof(i2c)))
|
if (copy_from_user(&i2c, parg, sizeof(i2c)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (i2c.bus > dev->link[0].info->regmap->i2c->num)
|
if (i2c.bus > dev->i2c_num)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (i2c.mlen + i2c.hlen > 512)
|
if (i2c.mlen + i2c.hlen > 512)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -3520,7 +3522,7 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||||||
|
|
||||||
if (copy_from_user(&i2c, parg, sizeof(i2c)))
|
if (copy_from_user(&i2c, parg, sizeof(i2c)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (i2c.bus > dev->link[0].info->regmap->i2c->num)
|
if (i2c.bus > dev->i2c_num)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (i2c.mlen + i2c.hlen > 250)
|
if (i2c.mlen + i2c.hlen > 250)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -3876,6 +3878,24 @@ static ssize_t bpsnr_show(struct device *device,
|
|||||||
return sprintf(buf, "%s\n", snr);
|
return sprintf(buf, "%s\n", snr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t gtl_snr_show(struct device *device,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ddb *dev = dev_get_drvdata(device);
|
||||||
|
int num = attr->attr.name[6] - 0x30;
|
||||||
|
char snr[16];
|
||||||
|
|
||||||
|
ddbridge_flashread(dev, num, snr, 0x10, 15);
|
||||||
|
snr[15] = 0; /* in case it is not terminated on EEPROM */
|
||||||
|
return sprintf(buf, "%s\n", snr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t gtl_snr_store(struct device *device, struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t redirect_show(struct device *device,
|
static ssize_t redirect_show(struct device *device,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
@ -4121,6 +4141,12 @@ static struct device_attribute ddb_attrs_snr[] = {
|
|||||||
__ATTR(snr3, 0664, snr_show, snr_store),
|
__ATTR(snr3, 0664, snr_show, snr_store),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct device_attribute ddb_attrs_gtl_snr[] = {
|
||||||
|
__ATTR(gtlsnr1, 0664, gtl_snr_show, gtl_snr_store),
|
||||||
|
__ATTR(gtlsnr2, 0664, gtl_snr_show, gtl_snr_store),
|
||||||
|
__ATTR(gtlsnr3, 0664, gtl_snr_show, gtl_snr_store),
|
||||||
|
};
|
||||||
|
|
||||||
static struct device_attribute ddb_attrs_ctemp[] = {
|
static struct device_attribute ddb_attrs_ctemp[] = {
|
||||||
__ATTR_MRO(temp0, ctemp_show),
|
__ATTR_MRO(temp0, ctemp_show),
|
||||||
__ATTR_MRO(temp1, ctemp_show),
|
__ATTR_MRO(temp1, ctemp_show),
|
||||||
@ -4191,6 +4217,9 @@ static void ddb_device_attrs_del(struct ddb *dev)
|
|||||||
device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]);
|
device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]);
|
||||||
device_remove_file(dev->ddb_dev, &ddb_attrs_ctemp[i]);
|
device_remove_file(dev->ddb_dev, &ddb_attrs_ctemp[i]);
|
||||||
}
|
}
|
||||||
|
if (dev->link[0].info->regmap->gtl)
|
||||||
|
for (i = 0; i < dev->link[0].info->regmap->gtl->num; i++)
|
||||||
|
device_remove_file(dev->ddb_dev, &ddb_attrs_gtl_snr[i]);
|
||||||
for (i = 0; ddb_attrs[i].attr.name; i++)
|
for (i = 0; ddb_attrs[i].attr.name; i++)
|
||||||
device_remove_file(dev->ddb_dev, &ddb_attrs[i]);
|
device_remove_file(dev->ddb_dev, &ddb_attrs[i]);
|
||||||
}
|
}
|
||||||
@ -4223,6 +4252,10 @@ static int ddb_device_attrs_add(struct ddb *dev)
|
|||||||
&ddb_attrs_led[i]))
|
&ddb_attrs_led[i]))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (dev->link[0].info->regmap->gtl)
|
||||||
|
for (i = 0; i < dev->link[0].info->regmap->gtl->num; i++)
|
||||||
|
if (device_create_file(dev->ddb_dev, &ddb_attrs_gtl_snr[i]))
|
||||||
|
goto fail;
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
if (dev->link[i].info &&
|
if (dev->link[i].info &&
|
||||||
dev->link[i].info->tempmon_irq)
|
dev->link[i].info->tempmon_irq)
|
||||||
@ -4439,7 +4472,7 @@ static void tempmon_setfan(struct ddb_link *link)
|
|||||||
while (pwm < 10 && temp >= link->temp_tab[pwm + 1])
|
while (pwm < 10 && temp >= link->temp_tab[pwm + 1])
|
||||||
pwm += 1;
|
pwm += 1;
|
||||||
} else {
|
} else {
|
||||||
while (pwm > 1 && temp < link->temp_tab[pwm - 2])
|
while (pwm > 1 && temp < (link->temp_tab[pwm] - 2))
|
||||||
pwm -= 1;
|
pwm -= 1;
|
||||||
}
|
}
|
||||||
ddblwritel(link, (pwm << 8), TEMPMON_FANCONTROL);
|
ddblwritel(link, (pwm << 8), TEMPMON_FANCONTROL);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* ddbridge-hw.c: Digital Devices device information tables
|
* ddbridge-hw.c: Digital Devices device information tables
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
* Copyright (C) 2010-2019 Digital Devices GmbH
|
||||||
* Ralph Metzler <rjkm@metzlerbros.de>
|
* Ralph Metzler <rjkm@metzlerbros.de>
|
||||||
* Marcus Metzler <mocm@metzlerbros.de>
|
* Marcus Metzler <mocm@metzlerbros.de>
|
||||||
*
|
*
|
||||||
@ -537,6 +537,16 @@ static const struct ddb_info ddb_sdr_iq = {
|
|||||||
.tempmon_irq = 8,
|
.tempmon_irq = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct ddb_info ddb_sdr_dvbt = {
|
||||||
|
.type = DDB_MOD,
|
||||||
|
.name = "Digital Devices DVBT",
|
||||||
|
.version = 18,
|
||||||
|
.regmap = &octopus_sdr_map,
|
||||||
|
.port_num = 16,
|
||||||
|
.temp_num = 1,
|
||||||
|
.tempmon_irq = 8,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct ddb_info ddb_octopro_hdin = {
|
static const struct ddb_info ddb_octopro_hdin = {
|
||||||
.type = DDB_OCTOPRO_HDIN,
|
.type = DDB_OCTOPRO_HDIN,
|
||||||
.name = "Digital Devices OctopusNet Pro HDIN",
|
.name = "Digital Devices OctopusNet Pro HDIN",
|
||||||
@ -789,7 +799,7 @@ static const struct ddb_device_id ddb_device_ids[] = {
|
|||||||
DDB_DEVID(0x0210, 0x0003, ddb_mod_fsm_8),
|
DDB_DEVID(0x0210, 0x0003, ddb_mod_fsm_8),
|
||||||
DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv),
|
DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv),
|
||||||
DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq),
|
DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq),
|
||||||
DDB_DEVID(0x0222, 0x0001, ddb_sdr_iq),
|
DDB_DEVID(0x0222, 0x0001, ddb_sdr_dvbt),
|
||||||
|
|
||||||
/* testing on OctopusNet Pro */
|
/* testing on OctopusNet Pro */
|
||||||
DDB_DEVID(0x0320, 0xffff, ddb_octopro_hdin),
|
DDB_DEVID(0x0320, 0xffff, ddb_octopro_hdin),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* ddbridge-i2c.c: Digital Devices bridge i2c driver
|
* ddbridge-i2c.c: Digital Devices bridge i2c driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
* Copyright (C) 2010-2019 Digital Devices GmbH
|
||||||
* Ralph Metzler <rjkm@metzlerbros.de>
|
* Ralph Metzler <rjkm@metzlerbros.de>
|
||||||
* Marcus Metzler <mocm@metzlerbros.de>
|
* Marcus Metzler <mocm@metzlerbros.de>
|
||||||
*
|
*
|
||||||
@ -65,7 +65,7 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
|
|||||||
}
|
}
|
||||||
val &= 0x70000;
|
val &= 0x70000;
|
||||||
if (val == 0x20000)
|
if (val == 0x20000)
|
||||||
dev_err(dev->dev, "I2C bus errorx\n");
|
dev_err(dev->dev, "I2C bus error\n");
|
||||||
if (val)
|
if (val)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* ddbridge-i2c.h: Digital Devices bridge i2c driver
|
* ddbridge-i2c.h: Digital Devices bridge i2c driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
* Copyright (C) 2010-2019 Digital Devices GmbH
|
||||||
* Marcus Metzler <mocm@metzlerbros.de>
|
* Marcus Metzler <mocm@metzlerbros.de>
|
||||||
* Ralph Metzler <rjkm@metzlerbros.de>
|
* Ralph Metzler <rjkm@metzlerbros.de>
|
||||||
*
|
*
|
||||||
|
@ -83,7 +83,17 @@ static int ddb_mci_cmd_raw_unlocked(struct mci *state,
|
|||||||
|
|
||||||
stat = wait_for_completion_timeout(&state->base->completion, HZ);
|
stat = wait_for_completion_timeout(&state->base->completion, HZ);
|
||||||
if (stat == 0) {
|
if (stat == 0) {
|
||||||
|
u32 istat = ddblreadl(link, INTERRUPT_STATUS);
|
||||||
|
|
||||||
printk("MCI timeout\n");
|
printk("MCI timeout\n");
|
||||||
|
val = ddblreadl(link, MCI_CONTROL);
|
||||||
|
if (val == 0xffffffff)
|
||||||
|
printk("Lost PCIe link!\n");
|
||||||
|
else {
|
||||||
|
printk("DDBridge IRS %08x\n", istat);
|
||||||
|
if (istat & 1)
|
||||||
|
ddblwritel(link, istat & 1, INTERRUPT_ACK);
|
||||||
|
}
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
if (res && res_len)
|
if (res && res_len)
|
||||||
|
@ -114,7 +114,7 @@
|
|||||||
#define MCI_CMD_STOP (0x01)
|
#define MCI_CMD_STOP (0x01)
|
||||||
#define MCI_CMD_GETSTATUS (0x02)
|
#define MCI_CMD_GETSTATUS (0x02)
|
||||||
#define MCI_CMD_GETSIGNALINFO (0x03)
|
#define MCI_CMD_GETSIGNALINFO (0x03)
|
||||||
#define MCI_CMD_RFPOWER (0x04)
|
//#define MCI_CMD_RFPOWER (0x04)
|
||||||
|
|
||||||
#define MCI_CMD_SEARCH_DVBS (0x10)
|
#define MCI_CMD_SEARCH_DVBS (0x10)
|
||||||
#define MCI_CMD_SEARCH_ISDBS (0x11)
|
#define MCI_CMD_SEARCH_ISDBS (0x11)
|
||||||
@ -147,7 +147,8 @@
|
|||||||
#define M4_CMD_GET_L1INFO (0x50)
|
#define M4_CMD_GET_L1INFO (0x50)
|
||||||
#define M4_CMD_GET_IDS (0x51)
|
#define M4_CMD_GET_IDS (0x51)
|
||||||
#define M4_CMD_GET_DVBT_TPS (0x52)
|
#define M4_CMD_GET_DVBT_TPS (0x52)
|
||||||
#define M4_CMD_GET_BBHEADER (0x53)
|
#define MCI_CMD_GET_BBHEADER (0x53)
|
||||||
|
#define M4_CMD_GET_BBHEADER (MCI_CMD_GET_BBHEADER)
|
||||||
#define M4_CMD_GET_ISDBT_TMCC (0x54)
|
#define M4_CMD_GET_ISDBT_TMCC (0x54)
|
||||||
#define M4_CMD_GET_ISDBS_TMCC (0x55)
|
#define M4_CMD_GET_ISDBS_TMCC (0x55)
|
||||||
#define M4_CMD_GET_ISDBC_TSMF (0x56)
|
#define M4_CMD_GET_ISDBC_TSMF (0x56)
|
||||||
@ -179,6 +180,12 @@
|
|||||||
#define M4_SIGNALINFO_FLAG_CHANGE (0x01)
|
#define M4_SIGNALINFO_FLAG_CHANGE (0x01)
|
||||||
#define M4_SIGNALINFO_FLAG_EWS (0x02)
|
#define M4_SIGNALINFO_FLAG_EWS (0x02)
|
||||||
|
|
||||||
|
#define SX8_ROLLOFF_25 1
|
||||||
|
#define SX8_ROLLOFF_20 2
|
||||||
|
#define SX8_ROLLOFF_15 5
|
||||||
|
#define SX8_ROLLOFF_10 3
|
||||||
|
#define SX8_ROLLOFF_05 4
|
||||||
|
|
||||||
#define MCI_SUCCESS(status) ((status & MCI_STATUS_UNSUPPORTED) == 0)
|
#define MCI_SUCCESS(status) ((status & MCI_STATUS_UNSUPPORTED) == 0)
|
||||||
|
|
||||||
|
|
||||||
@ -287,26 +294,37 @@ struct mci_command {
|
|||||||
u32 frequency;
|
u32 frequency;
|
||||||
} j83b_search;
|
} j83b_search;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u8 flags; // Bit 0 : 1 = short info (1st 4 Bytes)
|
||||||
|
} get_signalinfo;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u8 tap;
|
u8 tap;
|
||||||
u8 rsvd;
|
u8 rsvd;
|
||||||
u16 point;
|
u16 point;
|
||||||
} get_iq_symbol;
|
} get_iq_symbol;
|
||||||
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u8 flags; /* Bit 0 : 0 = VTM, 1 = SCAN. Bit 1: Set Gain */
|
uint8_t flags; /* Bit 0 : 0 = VTM/SDR, 1 = SCAN, Bit 1: Disable AGC, Bit 2: Set Gain */
|
||||||
u8 roll_off;
|
uint8_t roll_off;
|
||||||
u8 rsvd1;
|
uint8_t rsvd1;
|
||||||
u8 rsvd2;
|
uint8_t rsvd2;
|
||||||
u32 frequency;
|
uint32_t frequency;
|
||||||
u32 symbol_rate; /* Only in VTM mode. */
|
uint32_t symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/
|
||||||
u16 gain;
|
uint8_t gain; /* Gain in 0.25 dB Steps */
|
||||||
|
/* Frequency, symbolrate and gain can be schanged while running */
|
||||||
} sx8_start_iq;
|
} sx8_start_iq;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
/* Bit 1:0 = STVVGLNA Gain. 0 = AGC, 1 = 0dB,
|
uint8_t flags;
|
||||||
2 = Minimum, 3 = Maximum */
|
/* Bit 0:1 Preamp Mode; 0 = Preamp AGC, 1 == Minimum (~ -17dB) ,
|
||||||
u8 flags;
|
2 = Medium, 3 = Maximum gain {~ 15dB}
|
||||||
|
Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp)
|
||||||
|
Bit 4: Set RF Gain
|
||||||
|
Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled)
|
||||||
|
Bit 7: Optimize RF Gain and freeze for FFT */
|
||||||
|
uint8_t rf_gain; /* 0 .. 50 dB */
|
||||||
} sx8_input_enable;
|
} sx8_input_enable;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -357,8 +375,8 @@ struct mci_result {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
u8 standard; /* 1 = DVB-S, 2 = DVB-S2X */
|
u8 standard; /* 1 = DVB-S, 2 = DVB-S2X */
|
||||||
u8 pls_code; /* puncture rate for DVB-S */
|
u8 pls_code; /* PLS code for DVB-S2/S2X, puncture rate for DVB-S */
|
||||||
u8 roll_off; /* 2-0: rolloff */
|
u8 roll_off; /* 2-0: rolloff, 7: spectrum inversion */
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u32 frequency; /* actual frequency in Hz */
|
u32 frequency; /* actual frequency in Hz */
|
||||||
u32 symbol_rate; /* actual symbolrate in Hz */
|
u32 symbol_rate; /* actual symbolrate in Hz */
|
||||||
@ -391,8 +409,6 @@ struct mci_result {
|
|||||||
u8 modulation2; // bit 7..5: CodeRate Low, bit 4..3 Guard Interval, bit 2..1 FFT Mode
|
u8 modulation2; // bit 7..5: CodeRate Low, bit 4..3 Guard Interval, bit 2..1 FFT Mode
|
||||||
u8 Rsvd0;
|
u8 Rsvd0;
|
||||||
u8 Flags;
|
u8 Flags;
|
||||||
//u16 tps_cell_id; /* Cell Identifier */
|
|
||||||
|
|
||||||
u32 frequency; /* actual frequency in Hz */
|
u32 frequency; /* actual frequency in Hz */
|
||||||
u32 rsvd1;
|
u32 rsvd1;
|
||||||
s16 channel_power; /* channel power in dBm x 100 */
|
s16 channel_power; /* channel power in dBm x 100 */
|
||||||
@ -492,6 +508,7 @@ struct mci_result {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
u8 TPSInfo[7];
|
u8 TPSInfo[7];
|
||||||
|
// uint16_t TPS_CellID; // Cell Identifier
|
||||||
} DVBT_TPSInfo;
|
} DVBT_TPSInfo;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -620,6 +637,8 @@ struct mci_result {
|
|||||||
u8 SYNCD[2];
|
u8 SYNCD[2];
|
||||||
u8 rsvd;
|
u8 rsvd;
|
||||||
u8 ISSY[3];
|
u8 ISSY[3];
|
||||||
|
u8 min_input_stream_id;
|
||||||
|
u8 max_input_stream_id;
|
||||||
} BBHeader;
|
} BBHeader;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -644,7 +663,11 @@ struct mci_result {
|
|||||||
u8 Extension[8]; // 61 bits, right aligned
|
u8 Extension[8]; // 61 bits, right aligned
|
||||||
} ISDBS_TMCCInfo;
|
} ISDBS_TMCCInfo;
|
||||||
};
|
};
|
||||||
u32 version[4];
|
u32 version[3];
|
||||||
|
u32 version_rsvd;
|
||||||
|
u8 version_major;
|
||||||
|
u8 version_minor;
|
||||||
|
u8 version_sub;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1477,12 +1477,46 @@ static int mod3_set_ari(struct ddb_mod *mod, u32 rate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate)
|
||||||
|
{
|
||||||
|
u32 cic, inc;
|
||||||
|
|
||||||
|
switch (rate) {
|
||||||
|
case SYS_DVBT_6:
|
||||||
|
inc = 1917396114;
|
||||||
|
cic = 8;
|
||||||
|
break;
|
||||||
|
case SYS_DVBT_7:
|
||||||
|
inc = 1957341867;
|
||||||
|
cic = 7;
|
||||||
|
break;
|
||||||
|
case SYS_DVBT_8:
|
||||||
|
//rate = 8126984;
|
||||||
|
inc = 1917396114;
|
||||||
|
cic = 6;
|
||||||
|
break;
|
||||||
|
case SYS_ISDBT_6:
|
||||||
|
inc = 1988410754;
|
||||||
|
cic = 7;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
ddbwritel(mod->port->dev, inc, SDR_CHANNEL_ARICW(mod->port->nr));
|
||||||
|
ddbwritel(mod->port->dev, cic << 8, SDR_CHANNEL_CONFIG(mod->port->nr));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int mod3_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
|
static int mod3_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
|
||||||
{
|
{
|
||||||
switch (tvp->cmd) {
|
switch (tvp->cmd) {
|
||||||
case MODULATOR_OUTPUT_ARI:
|
case MODULATOR_OUTPUT_ARI:
|
||||||
return mod3_set_ari(mod, tvp->u.data);
|
return mod3_set_ari(mod, tvp->u.data);
|
||||||
|
|
||||||
|
case MODULATOR_OUTPUT_RATE:
|
||||||
|
return mod3_set_sample_rate(mod, tvp->u.data);
|
||||||
|
|
||||||
case MODULATOR_FREQUENCY:
|
case MODULATOR_FREQUENCY:
|
||||||
return mod3_set_frequency(mod, tvp->u.data);
|
return mod3_set_frequency(mod, tvp->u.data);
|
||||||
|
|
||||||
@ -1542,15 +1576,37 @@ static int mod_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mod_prop_get3(struct ddb_mod *mod, struct dtv_property *tvp)
|
||||||
|
{
|
||||||
|
struct ddb *dev = mod->port->dev;
|
||||||
|
|
||||||
|
switch (tvp->cmd) {
|
||||||
|
case MODULATOR_INFO:
|
||||||
|
tvp->u.data = dev->link[0].info->version;
|
||||||
|
return 0;
|
||||||
|
case MODULATOR_GAIN:
|
||||||
|
tvp->u.data = 0xff & ddbreadl(dev, RF_VGA);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int mod_prop_get(struct ddb_mod *mod, struct dtv_property *tvp)
|
static int mod_prop_get(struct ddb_mod *mod, struct dtv_property *tvp)
|
||||||
{
|
{
|
||||||
struct ddb *dev = mod->port->dev;
|
struct ddb *dev = mod->port->dev;
|
||||||
|
|
||||||
|
if (mod->port->dev->link[0].info->version >= 16)
|
||||||
|
return mod_prop_get3(mod, tvp);
|
||||||
if (mod->port->dev->link[0].info->version != 2)
|
if (mod->port->dev->link[0].info->version != 2)
|
||||||
return -1;
|
return -1;
|
||||||
switch (tvp->cmd) {
|
switch (tvp->cmd) {
|
||||||
|
case MODULATOR_INFO:
|
||||||
|
tvp->u.data = 2;
|
||||||
|
return 0;
|
||||||
|
|
||||||
case MODULATOR_GAIN:
|
case MODULATOR_GAIN:
|
||||||
tvp->u.data = 0xff & ddbreadl(dev, RF_VGA);;
|
tvp->u.data = 0xff & ddbreadl(dev, RF_VGA);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case MODULATOR_ATTENUATOR:
|
case MODULATOR_ATTENUATOR:
|
||||||
@ -1897,6 +1953,8 @@ int ddbridge_mod_init(struct ddb *dev)
|
|||||||
return mod_init_3(dev, 503250000);
|
return mod_init_3(dev, 503250000);
|
||||||
case 17:
|
case 17:
|
||||||
return mod_init_sdr_iq(dev);
|
return mod_init_sdr_iq(dev);
|
||||||
|
case 18:
|
||||||
|
return mod_init_sdr_iq(dev);
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ static u16 calc_pcs16(struct dvb_ns_params *p, int ipv)
|
|||||||
u32 sum = 0, i;
|
u32 sum = 0, i;
|
||||||
u16 pcs;
|
u16 pcs;
|
||||||
|
|
||||||
for (i = 0; i < ipv ? 16 : 4; i += 2) {
|
for (i = 0; i < (ipv ? 16 : 4); i += 2) {
|
||||||
sum += (p->sip[i] << 8) | p->sip[i + 1];
|
sum += (p->sip[i] << 8) | p->sip[i + 1];
|
||||||
sum += (p->dip[i] << 8) | p->dip[i + 1];
|
sum += (p->dip[i] << 8) | p->dip[i + 1];
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,14 @@
|
|||||||
#include "ddbridge-i2c.h"
|
#include "ddbridge-i2c.h"
|
||||||
#include "ddbridge-mci.h"
|
#include "ddbridge-mci.h"
|
||||||
|
|
||||||
|
static int default_mod = 3;
|
||||||
|
module_param(default_mod, int, 0444);
|
||||||
|
MODULE_PARM_DESC(default_mod, "default modulations enabled, default is 3 (1 = QPSK, 2 = 8PSK, 4 = 16APSK, ...)");
|
||||||
|
|
||||||
static const u32 MCLK = (1550000000 / 12);
|
static const u32 MCLK = (1550000000 / 12);
|
||||||
static const u32 MAX_LDPC_BITRATE = (720000000);
|
|
||||||
|
/* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */
|
||||||
|
static const u32 MAX_LDPC_BITRATE = (720000000 + 2000000);
|
||||||
static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6);
|
static const u32 MAX_DEMOD_LDPC_BITRATE = (1550000000 / 6);
|
||||||
|
|
||||||
#define SX8_TUNER_NUM 4
|
#define SX8_TUNER_NUM 4
|
||||||
@ -52,6 +58,7 @@ struct sx8 {
|
|||||||
|
|
||||||
int first_time_lock;
|
int first_time_lock;
|
||||||
int started;
|
int started;
|
||||||
|
int iq_started;
|
||||||
|
|
||||||
u32 bb_mode;
|
u32 bb_mode;
|
||||||
u32 local_frequency;
|
u32 local_frequency;
|
||||||
@ -131,6 +138,7 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
|||||||
dvbs2_bits_per_symbol[
|
dvbs2_bits_per_symbol[
|
||||||
state->mci.signal_info.
|
state->mci.signal_info.
|
||||||
dvbs2_signal_info.pls_code];
|
dvbs2_signal_info.pls_code];
|
||||||
|
//printk("PLS %02x\n", state->mci.signal_info.dvbs2_signal_info.pls_code);
|
||||||
} else
|
} else
|
||||||
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
|
sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;
|
||||||
}
|
}
|
||||||
@ -151,6 +159,25 @@ static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on)
|
|||||||
return ddb_mci_cmd(&state->mci, &cmd, NULL);
|
return ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int stop_iq(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
struct sx8 *state = fe->demodulator_priv;
|
||||||
|
struct mci_base *mci_base = state->mci.base;
|
||||||
|
struct sx8_base *sx8_base = (struct sx8_base *) mci_base;
|
||||||
|
struct mci_command cmd;
|
||||||
|
u32 input = state->mci.tuner;
|
||||||
|
|
||||||
|
if (!state->iq_started)
|
||||||
|
return -1;
|
||||||
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
|
cmd.command = SX8_CMD_STOP_IQ;
|
||||||
|
cmd.demod = state->mci.demod;
|
||||||
|
ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
|
ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL);
|
||||||
|
state->iq_started = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int stop(struct dvb_frontend *fe)
|
static int stop(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
struct sx8 *state = fe->demodulator_priv;
|
struct sx8 *state = fe->demodulator_priv;
|
||||||
@ -285,13 +312,13 @@ unlock:
|
|||||||
if (sx8_base->iq_mode) {
|
if (sx8_base->iq_mode) {
|
||||||
cmd.command = SX8_CMD_ENABLE_IQOUTPUT;
|
cmd.command = SX8_CMD_ENABLE_IQOUTPUT;
|
||||||
cmd.demod = state->mci.demod;
|
cmd.demod = state->mci.demod;
|
||||||
cmd.output = 0;
|
cmd.output = p->stream_id & 7;
|
||||||
ddb_mci_cmd(&state->mci, &cmd, NULL);
|
ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
ddb_mci_config(&state->mci, ts_config);
|
ddb_mci_config(&state->mci, ts_config);
|
||||||
}
|
}
|
||||||
if (p->stream_id != NO_STREAM_ID_FILTER && p->stream_id != 0x80000000)
|
if (p->stream_id != NO_STREAM_ID_FILTER && !(p->stream_id & 0xf0000000))
|
||||||
flags |= 0x80;
|
flags |= 0x80;
|
||||||
printk("frontend %u: tuner=%u demod=%u\n", state->mci.nr, state->mci.tuner, state->mci.demod);
|
//printk("frontend %u: tuner=%u demod=%u\n", state->mci.nr, state->mci.tuner, state->mci.demod);
|
||||||
cmd.command = MCI_CMD_SEARCH_DVBS;
|
cmd.command = MCI_CMD_SEARCH_DVBS;
|
||||||
cmd.dvbs2_search.flags = flags;
|
cmd.dvbs2_search.flags = flags;
|
||||||
cmd.dvbs2_search.s2_modulation_mask = modmask;
|
cmd.dvbs2_search.s2_modulation_mask = modmask;
|
||||||
@ -357,7 +384,7 @@ unlock:
|
|||||||
cmd.demod = state->mci.demod;
|
cmd.demod = state->mci.demod;
|
||||||
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
|
||||||
if (stat)
|
if (stat)
|
||||||
stop(fe);
|
stop_iq(fe);
|
||||||
ddb_mci_config(&state->mci, ts_config);
|
ddb_mci_config(&state->mci, ts_config);
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
@ -369,16 +396,18 @@ static int set_parameters(struct dvb_frontend *fe)
|
|||||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||||
u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi;
|
u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi;
|
||||||
|
|
||||||
stop(fe);
|
|
||||||
isi = p->stream_id;
|
isi = p->stream_id;
|
||||||
if (isi != NO_STREAM_ID_FILTER) {
|
if (isi != NO_STREAM_ID_FILTER) {
|
||||||
iq_mode = (isi & 0x30000000) >> 28;
|
iq_mode = (isi & 0x30000000) >> 28;
|
||||||
}
|
}
|
||||||
if (iq_mode)
|
if (iq_mode)
|
||||||
ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ);
|
ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ);
|
||||||
|
stop(fe);
|
||||||
if (iq_mode < 2) {
|
if (iq_mode < 2) {
|
||||||
u32 mask;
|
u32 mask;
|
||||||
|
|
||||||
|
stop_iq(fe);
|
||||||
switch (p->modulation) {
|
switch (p->modulation) {
|
||||||
case APSK_256:
|
case APSK_256:
|
||||||
mask = 0x7f;
|
mask = 0x7f;
|
||||||
@ -396,18 +425,23 @@ static int set_parameters(struct dvb_frontend *fe)
|
|||||||
mask = 0x07;
|
mask = 0x07;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mask = 0x03;
|
mask = default_mod;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
stat = start(fe, 3, mask, ts_config);
|
stat = start(fe, 3, mask, ts_config);
|
||||||
} else {
|
|
||||||
stat = start_iq(fe, iq_mode & 1, 4, ts_config);
|
|
||||||
}
|
|
||||||
if (!stat) {
|
if (!stat) {
|
||||||
state->started = 1;
|
state->started = 1;
|
||||||
state->first_time_lock = 1;
|
state->first_time_lock = 1;
|
||||||
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
|
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
stat = start_iq(fe, iq_mode & 1, 4, ts_config);
|
||||||
|
if (!stat) {
|
||||||
|
state->iq_started = 1;
|
||||||
|
state->first_time_lock = 1;
|
||||||
|
state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,6 +480,7 @@ static int set_input(struct dvb_frontend *fe, int input)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (state->mci.tuner == input)
|
if (state->mci.tuner == input)
|
||||||
return 0;
|
return 0;
|
||||||
|
stop_iq(fe);
|
||||||
stop(fe);
|
stop(fe);
|
||||||
state->mci.tuner = p->input = input;
|
state->mci.tuner = p->input = input;
|
||||||
return 0;
|
return 0;
|
||||||
@ -453,6 +488,7 @@ static int set_input(struct dvb_frontend *fe, int input)
|
|||||||
|
|
||||||
static int sleep(struct dvb_frontend *fe)
|
static int sleep(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
|
stop_iq(fe);
|
||||||
stop(fe);
|
stop(fe);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* ddbridge.h: Digital Devices PCIe bridge driver
|
* ddbridge.h: Digital Devices PCIe bridge driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2017 Digital Devices GmbH
|
* Copyright (C) 2010-2019 Digital Devices GmbH
|
||||||
* Ralph Metzler <rmetzler@digitaldevices.de>
|
* Marcus Metzler <mocm@metzlerbros.de>
|
||||||
|
* Ralph Metzler <rjkm@metzlerbros.de>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -115,7 +115,7 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
|
|||||||
void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
|
void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
|
||||||
{
|
{
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||||
rbuf->pread = &rbuf->pwrite;
|
rbuf->pread = rbuf->pwrite;
|
||||||
#else
|
#else
|
||||||
/* dvb_ringbuffer_flush() counts as read operation
|
/* dvb_ringbuffer_flush() counts as read operation
|
||||||
* smp_load_acquire() to load write pointer
|
* smp_load_acquire() to load write pointer
|
||||||
|
@ -598,6 +598,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
|
|||||||
unsigned demux_pad = 0;
|
unsigned demux_pad = 0;
|
||||||
unsigned dvr_pad = 0;
|
unsigned dvr_pad = 0;
|
||||||
unsigned ntuner = 0, ndemod = 0;
|
unsigned ntuner = 0, ndemod = 0;
|
||||||
|
u16 source_pad = 0;
|
||||||
int ret;
|
int ret;
|
||||||
static const char *connector_name = "Television";
|
static const char *connector_name = "Television";
|
||||||
|
|
||||||
@ -658,7 +659,18 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!ntuner)
|
if (!ntuner) {
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0))
|
||||||
|
if ((ret = media_get_pad_index(tuner, true,
|
||||||
|
PAD_SIGNAL_ANALOG)) < 0)
|
||||||
|
return ret;
|
||||||
|
source_pad = (u16) ret;
|
||||||
|
ret = 0;
|
||||||
|
#else
|
||||||
|
source_pad = TUNER_PAD_RF_INPUT;
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = media_create_pad_links(mdev,
|
ret = media_create_pad_links(mdev,
|
||||||
MEDIA_ENT_F_CONN_RF,
|
MEDIA_ENT_F_CONN_RF,
|
||||||
conn, 0,
|
conn, 0,
|
||||||
@ -666,22 +678,33 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
|
|||||||
demod, 0,
|
demod, 0,
|
||||||
MEDIA_LNK_FL_ENABLED,
|
MEDIA_LNK_FL_ENABLED,
|
||||||
false);
|
false);
|
||||||
else
|
} else {
|
||||||
ret = media_create_pad_links(mdev,
|
ret = media_create_pad_links(mdev,
|
||||||
MEDIA_ENT_F_CONN_RF,
|
MEDIA_ENT_F_CONN_RF,
|
||||||
conn, 0,
|
conn, 0,
|
||||||
MEDIA_ENT_F_TUNER,
|
MEDIA_ENT_F_TUNER,
|
||||||
tuner, TUNER_PAD_RF_INPUT,
|
tuner, source_pad,
|
||||||
MEDIA_LNK_FL_ENABLED,
|
MEDIA_LNK_FL_ENABLED,
|
||||||
false);
|
false);
|
||||||
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntuner && ndemod) {
|
if (ntuner && ndemod) {
|
||||||
|
|
||||||
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0))
|
||||||
|
if ((ret = media_get_pad_index(tuner, true, PAD_SIGNAL_ANALOG)) < 0)
|
||||||
|
return ret;
|
||||||
|
source_pad = (u16) ret;
|
||||||
|
ret = 0;
|
||||||
|
#else
|
||||||
|
source_pad = TUNER_PAD_OUTPUT;
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = media_create_pad_links(mdev,
|
ret = media_create_pad_links(mdev,
|
||||||
MEDIA_ENT_F_TUNER,
|
MEDIA_ENT_F_TUNER,
|
||||||
tuner, TUNER_PAD_OUTPUT,
|
tuner, source_pad,
|
||||||
MEDIA_ENT_F_DTV_DEMOD,
|
MEDIA_ENT_F_DTV_DEMOD,
|
||||||
demod, 0, MEDIA_LNK_FL_ENABLED,
|
demod, 0, MEDIA_LNK_FL_ENABLED,
|
||||||
false);
|
false);
|
||||||
|
@ -355,6 +355,7 @@ static int read_tps(struct cxd_state *state, u8 *tps)
|
|||||||
/* OFDMInfo[3] [3:0] OFDM_NDSYM[11:8] */
|
/* OFDMInfo[3] [3:0] OFDM_NDSYM[11:8] */
|
||||||
/* OFDMInfo[4] [7:0] OFDM_NDSYM[7:0] */
|
/* OFDMInfo[4] [7:0] OFDM_NDSYM[7:0] */
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm)
|
static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm)
|
||||||
{
|
{
|
||||||
if (state->last_status != 0x1f)
|
if (state->last_status != 0x1f)
|
||||||
@ -365,6 +366,7 @@ static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm)
|
|||||||
unfreeze_regst(state);
|
unfreeze_regst(state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Read DVBT2 QAM,
|
/* Read DVBT2 QAM,
|
||||||
Data PLP
|
Data PLP
|
||||||
@ -390,6 +392,7 @@ static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm)
|
|||||||
19-37 same for common PLP
|
19-37 same for common PLP
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int read_t2_tlp_info(struct cxd_state *state, u8 off, u8 count, u8 *tlp)
|
static int read_t2_tlp_info(struct cxd_state *state, u8 off, u8 count, u8 *tlp)
|
||||||
{
|
{
|
||||||
if (state->last_status != 0x1f)
|
if (state->last_status != 0x1f)
|
||||||
@ -400,6 +403,7 @@ static int read_t2_tlp_info(struct cxd_state *state, u8 off, u8 count, u8 *tlp)
|
|||||||
unfreeze_regst(state);
|
unfreeze_regst(state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void Active_to_Sleep(struct cxd_state *state)
|
static void Active_to_Sleep(struct cxd_state *state)
|
||||||
{
|
{
|
||||||
@ -2243,7 +2247,7 @@ static int get_algo(struct dvb_frontend *fe)
|
|||||||
|
|
||||||
static int get_fe_t2(struct cxd_state *state, struct dtv_frontend_properties *p)
|
static int get_fe_t2(struct cxd_state *state, struct dtv_frontend_properties *p)
|
||||||
{
|
{
|
||||||
struct dvb_frontend *fe = &state->frontend;
|
//struct dvb_frontend *fe = &state->frontend;
|
||||||
u8 ofdm[5], modcod[2];
|
u8 ofdm[5], modcod[2];
|
||||||
|
|
||||||
freeze_regst(state);
|
freeze_regst(state);
|
||||||
@ -2343,7 +2347,7 @@ static int get_fe_t2(struct cxd_state *state, struct dtv_frontend_properties *p)
|
|||||||
|
|
||||||
static int get_fe_t(struct cxd_state *state, struct dtv_frontend_properties *p)
|
static int get_fe_t(struct cxd_state *state, struct dtv_frontend_properties *p)
|
||||||
{
|
{
|
||||||
struct dvb_frontend *fe = &state->frontend;
|
//struct dvb_frontend *fe = &state->frontend;
|
||||||
u8 tps[7];
|
u8 tps[7];
|
||||||
|
|
||||||
read_tps(state, tps);
|
read_tps(state, tps);
|
||||||
@ -2444,7 +2448,7 @@ static int get_fe_t(struct cxd_state *state, struct dtv_frontend_properties *p)
|
|||||||
|
|
||||||
static int get_fe_c(struct cxd_state *state, struct dtv_frontend_properties *p)
|
static int get_fe_c(struct cxd_state *state, struct dtv_frontend_properties *p)
|
||||||
{
|
{
|
||||||
struct dvb_frontend *fe = &state->frontend;
|
//struct dvb_frontend *fe = &state->frontend;
|
||||||
u8 qam;
|
u8 qam;
|
||||||
|
|
||||||
freeze_regst(state);
|
freeze_regst(state);
|
||||||
|
@ -106,6 +106,7 @@ static int lnbh25_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int lnbh25_set_tone(struct dvb_frontend *fe,
|
static int lnbh25_set_tone(struct dvb_frontend *fe,
|
||||||
enum fe_sec_tone_mode tone)
|
enum fe_sec_tone_mode tone)
|
||||||
{
|
{
|
||||||
@ -113,6 +114,7 @@ static int lnbh25_set_tone(struct dvb_frontend *fe,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int lnbh25_init(struct lnbh25 *lnbh)
|
static int lnbh25_init(struct lnbh25 *lnbh)
|
||||||
{
|
{
|
||||||
|
@ -98,26 +98,6 @@ struct mxl {
|
|||||||
unsigned long tune_time;
|
unsigned long tune_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void le32_to_cpusn(u32 *data, u32 size)
|
|
||||||
{
|
|
||||||
u32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < size; data++, i += 4)
|
|
||||||
le32_to_cpus(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flip_data_in_dword(u32 size, u8 *d)
|
|
||||||
{
|
|
||||||
u32 i;
|
|
||||||
u8 t;
|
|
||||||
|
|
||||||
for (i = 0; i < size; i += 4) {
|
|
||||||
t = d[i + 3]; d[i + 3] = d[i]; d[i] = t;
|
|
||||||
t = d[i + 2]; d[i + 2] = d[i + 1]; d[i + 1] = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void convert_endian(u8 flag, u32 size, u8 *d)
|
static void convert_endian(u8 flag, u32 size, u8 *d)
|
||||||
{
|
{
|
||||||
u32 i;
|
u32 i;
|
||||||
@ -249,6 +229,7 @@ static int write_register(struct mxl *state, u32 reg, u32 val)
|
|||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int write_register_block(struct mxl *state, u32 reg,
|
static int write_register_block(struct mxl *state, u32 reg,
|
||||||
u32 size, u8 *data)
|
u32 size, u8 *data)
|
||||||
{
|
{
|
||||||
@ -272,6 +253,7 @@ static int write_register_block(struct mxl *state, u32 reg,
|
|||||||
mutex_unlock(&state->base->i2c_lock);
|
mutex_unlock(&state->base->i2c_lock);
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int write_firmware_block(struct mxl *state,
|
static int write_firmware_block(struct mxl *state,
|
||||||
u32 reg, u32 size, u8 *regDataPtr)
|
u32 reg, u32 size, u8 *regDataPtr)
|
||||||
@ -375,6 +357,7 @@ static int update_by_mnemonic(struct mxl *state,
|
|||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void extract_from_mnemonic(u32 regAddr, u8 lsbPos, u8 width,
|
static void extract_from_mnemonic(u32 regAddr, u8 lsbPos, u8 width,
|
||||||
u32 *toAddr, u8 *toLsbPos, u8 *toWidth)
|
u32 *toAddr, u8 *toLsbPos, u8 *toWidth)
|
||||||
{
|
{
|
||||||
@ -385,6 +368,7 @@ static void extract_from_mnemonic(u32 regAddr, u8 lsbPos, u8 width,
|
|||||||
if (toWidth)
|
if (toWidth)
|
||||||
*toWidth = width;
|
*toWidth = width;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int firmware_is_alive(struct mxl *state)
|
static int firmware_is_alive(struct mxl *state)
|
||||||
{
|
{
|
||||||
@ -397,6 +381,8 @@ static int firmware_is_alive(struct mxl *state)
|
|||||||
return 0;
|
return 0;
|
||||||
if (hb1 == hb0)
|
if (hb1 == hb0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
pr_info("mxl5xx: Hydra FW alive. Hail!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,9 +456,9 @@ static int CfgDemodAbortTune(struct mxl *state)
|
|||||||
&cmdBuff[0]);
|
&cmdBuff[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int reset_fec_counter(struct mxl *state)
|
static int reset_fec_counter(struct mxl *state)
|
||||||
{
|
{
|
||||||
MXL_HYDRA_DEMOD_ABORT_TUNE_T abortTuneCmd;
|
|
||||||
u32 demodIndex = (u32) state->demod;
|
u32 demodIndex = (u32) state->demod;
|
||||||
u8 cmdSize = sizeof(u32);
|
u8 cmdSize = sizeof(u32);
|
||||||
u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
|
u8 cmdBuff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN];
|
||||||
@ -482,6 +468,7 @@ static int reset_fec_counter(struct mxl *state)
|
|||||||
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
|
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
|
||||||
&cmdBuff[0]);
|
&cmdBuff[0]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int send_master_cmd(struct dvb_frontend *fe,
|
static int send_master_cmd(struct dvb_frontend *fe,
|
||||||
struct dvb_diseqc_master_cmd *cmd)
|
struct dvb_diseqc_master_cmd *cmd)
|
||||||
@ -1118,8 +1105,6 @@ static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len)
|
|||||||
if (!firmware_is_alive(state))
|
if (!firmware_is_alive(state))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pr_info("mxl5xx: Hydra FW alive. Hail!\n");
|
|
||||||
|
|
||||||
/* sometimes register values are wrong shortly
|
/* sometimes register values are wrong shortly
|
||||||
after first heart beats */
|
after first heart beats */
|
||||||
msleep(50);
|
msleep(50);
|
||||||
@ -1437,6 +1422,7 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId,
|
|||||||
{XPT_NCO_COUNT_MIN4}, {XPT_NCO_COUNT_MIN5},
|
{XPT_NCO_COUNT_MIN4}, {XPT_NCO_COUNT_MIN5},
|
||||||
{XPT_NCO_COUNT_MIN6}, {XPT_NCO_COUNT_MIN7} };
|
{XPT_NCO_COUNT_MIN6}, {XPT_NCO_COUNT_MIN7} };
|
||||||
|
|
||||||
|
#if 0
|
||||||
MXL_REG_FIELD_T mxl561_xpt_ts_sync[MXL_HYDRA_DEMOD_ID_6] = {
|
MXL_REG_FIELD_T mxl561_xpt_ts_sync[MXL_HYDRA_DEMOD_ID_6] = {
|
||||||
{PAD_MUX_DIGIO_25_PINMUX_SEL}, {PAD_MUX_DIGIO_20_PINMUX_SEL},
|
{PAD_MUX_DIGIO_25_PINMUX_SEL}, {PAD_MUX_DIGIO_20_PINMUX_SEL},
|
||||||
{PAD_MUX_DIGIO_17_PINMUX_SEL}, {PAD_MUX_DIGIO_11_PINMUX_SEL},
|
{PAD_MUX_DIGIO_17_PINMUX_SEL}, {PAD_MUX_DIGIO_11_PINMUX_SEL},
|
||||||
@ -1445,6 +1431,7 @@ static int config_ts(struct mxl *state, MXL_HYDRA_DEMOD_ID_E demodId,
|
|||||||
{PAD_MUX_DIGIO_26_PINMUX_SEL}, {PAD_MUX_DIGIO_19_PINMUX_SEL},
|
{PAD_MUX_DIGIO_26_PINMUX_SEL}, {PAD_MUX_DIGIO_19_PINMUX_SEL},
|
||||||
{PAD_MUX_DIGIO_18_PINMUX_SEL}, {PAD_MUX_DIGIO_10_PINMUX_SEL},
|
{PAD_MUX_DIGIO_18_PINMUX_SEL}, {PAD_MUX_DIGIO_10_PINMUX_SEL},
|
||||||
{PAD_MUX_DIGIO_09_PINMUX_SEL}, {PAD_MUX_DIGIO_02_PINMUX_SEL}};
|
{PAD_MUX_DIGIO_09_PINMUX_SEL}, {PAD_MUX_DIGIO_02_PINMUX_SEL}};
|
||||||
|
#endif
|
||||||
|
|
||||||
demodId = state->base->ts_map[demodId];
|
demodId = state->base->ts_map[demodId];
|
||||||
|
|
||||||
@ -1609,6 +1596,7 @@ static int config_mux(struct mxl *state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int config_dis(struct mxl *state, u32 id)
|
static int config_dis(struct mxl *state, u32 id)
|
||||||
{
|
{
|
||||||
MXL_HYDRA_DISEQC_ID_E diseqcId = id;
|
MXL_HYDRA_DISEQC_ID_E diseqcId = id;
|
||||||
@ -1630,6 +1618,7 @@ static int config_dis(struct mxl *state, u32 id)
|
|||||||
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
|
return send_command(state, cmdSize + MXL_HYDRA_CMD_HEADER_SIZE,
|
||||||
&cmdBuff[0]);
|
&cmdBuff[0]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg)
|
static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg)
|
||||||
{
|
{
|
||||||
|
@ -3644,7 +3644,6 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
|
|||||||
|
|
||||||
{
|
{
|
||||||
u16 val;
|
u16 val;
|
||||||
u32 ber;
|
|
||||||
|
|
||||||
stv090x_read_cnr(fe, &val);
|
stv090x_read_cnr(fe, &val);
|
||||||
stv090x_read_signal_strength(fe, &val);
|
stv090x_read_signal_strength(fe, &val);
|
||||||
@ -3657,7 +3656,7 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
|
|||||||
static int stv090x_read_ber(struct dvb_frontend *fe, u32 *ber)
|
static int stv090x_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||||
{
|
{
|
||||||
struct stv090x_state *state = fe->demodulator_priv;
|
struct stv090x_state *state = fe->demodulator_priv;
|
||||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
//struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||||
u32 reg, h, m, l;
|
u32 reg, h, m, l;
|
||||||
enum fe_status status;
|
enum fe_status status;
|
||||||
|
|
||||||
@ -5075,7 +5074,7 @@ static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir,
|
|||||||
static int stv090x_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
static int stv090x_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
||||||
{
|
{
|
||||||
struct stv090x_state *state = fe->demodulator_priv;
|
struct stv090x_state *state = fe->demodulator_priv;
|
||||||
u8 tmp;
|
//u8 tmp;
|
||||||
u32 reg = 0;
|
u32 reg = 0;
|
||||||
|
|
||||||
if (state->rec_mode == 2) {
|
if (state->rec_mode == 2) {
|
||||||
|
@ -150,10 +150,12 @@ static int write_reg(struct stv *state, u16 reg, u8 val)
|
|||||||
return (i2c_transfer(state->base->i2c, &msg, 1) == 1) ? 0 : -1;
|
return (i2c_transfer(state->base->i2c, &msg, 1) == 1) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int write_reg_off(struct stv *state, u16 reg, u8 val)
|
static int write_reg_off(struct stv *state, u16 reg, u8 val)
|
||||||
{
|
{
|
||||||
return write_reg(state, reg + state->regoff, val);
|
return write_reg(state, reg + state->regoff, val);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr,
|
static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr,
|
||||||
u16 reg, u8 *val, int len)
|
u16 reg, u8 *val, int len)
|
||||||
@ -1639,6 +1641,7 @@ static int recv_slave_reply(struct dvb_frontend *fe,
|
|||||||
|
|
||||||
static int send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst)
|
static int send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
struct stv *state = fe->demodulator_priv;
|
struct stv *state = fe->demodulator_priv;
|
||||||
u8 value;
|
u8 value;
|
||||||
|
|
||||||
@ -1653,6 +1656,7 @@ static int send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst)
|
|||||||
set_reg(DISTXFIFO, value);
|
set_reg(DISTXFIFO, value);
|
||||||
set_reg(DISTXCFG, 0x3a);
|
set_reg(DISTXCFG, 0x3a);
|
||||||
wait_dis(state, 0x20, 0x20);
|
wait_dis(state, 0x20, 0x20);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,12 +100,12 @@ static int read_reg(struct stv *state, u8 reg, u8 *val)
|
|||||||
return i2c_read(state->i2c, state->adr, ®, 1, val, 1);
|
return i2c_read(state->i2c, state->adr, ®, 1, val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int read_regs(struct stv *state, u8 reg, u8 *val, int len)
|
static int read_regs(struct stv *state, u8 reg, u8 *val, int len)
|
||||||
{
|
{
|
||||||
return i2c_read(state->i2c, state->adr, ®, 1, val, len);
|
return i2c_read(state->i2c, state->adr, ®, 1, val, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void dump_regs(struct stv *state)
|
static void dump_regs(struct stv *state)
|
||||||
{
|
{
|
||||||
u8 d[11], *c = &state->reg[0];
|
u8 d[11], *c = &state->reg[0];
|
||||||
|
@ -32,6 +32,16 @@ struct dvb_mod_channel_params {
|
|||||||
#define MODULATOR_GAIN 35
|
#define MODULATOR_GAIN 35
|
||||||
#define MODULATOR_RESET 36
|
#define MODULATOR_RESET 36
|
||||||
#define MODULATOR_STATUS 37
|
#define MODULATOR_STATUS 37
|
||||||
|
#define MODULATOR_INFO 38
|
||||||
#define MODULATOR_OUTPUT_ARI 64
|
#define MODULATOR_OUTPUT_ARI 64
|
||||||
|
#define MODULATOR_OUTPUT_RATE 65
|
||||||
|
|
||||||
|
enum mod_output_rate {
|
||||||
|
SYS_DVBT_6 = 0,
|
||||||
|
SYS_DVBT_7,
|
||||||
|
SYS_DVBT_8,
|
||||||
|
SYS_ISDBT_6 = 16,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /*_UAPI_DVBMOD_H_*/
|
#endif /*_UAPI_DVBMOD_H_*/
|
||||||
|
@ -13,11 +13,11 @@ install: all
|
|||||||
$(CC) $(CFLAGS) -fPIC -c $<
|
$(CC) $(CFLAGS) -fPIC -c $<
|
||||||
|
|
||||||
dddvb_test: dddvb_test.o
|
dddvb_test: dddvb_test.o
|
||||||
$(CC) -o dddvb_test $< -L ./src -l dddvb -l pthread
|
$(CC) -o dddvb_test $< -L ./src -l dddvb -l pthread -l dvben50221 -l dvbapi -l ucsi
|
||||||
|
|
||||||
ddzap: ddzap.o
|
ddzap: ddzap.o
|
||||||
$(CC) -o ddzap $< -L ./src -l dddvb -l pthread
|
$(CC) -o ddzap $< -L ./src -l dddvb -l pthread -l dvben50221 -l dvbapi -l ucsi
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
make -C ./src clean
|
make -C ./src clean
|
||||||
rm *.o
|
-rm -f *.o
|
||||||
|
31
lib/ddzap.c
31
lib/ddzap.c
@ -24,7 +24,8 @@ int main(int argc, char **argv)
|
|||||||
struct dddvb_fe *fe;
|
struct dddvb_fe *fe;
|
||||||
struct dddvb_params p;
|
struct dddvb_params p;
|
||||||
uint32_t bandwidth = 8000000, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF;
|
uint32_t bandwidth = 8000000, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF;
|
||||||
uint32_t id = DDDVB_UNDEF, pls = DDDVB_UNDEF, num = DDDVB_UNDEF;
|
uint32_t id = DDDVB_UNDEF, pls = DDDVB_UNDEF, num = DDDVB_UNDEF, source = 0;
|
||||||
|
uint32_t verbosity = 0;
|
||||||
enum fe_code_rate fec = FEC_AUTO;
|
enum fe_code_rate fec = FEC_AUTO;
|
||||||
enum fe_delivery_system delsys = ~0;
|
enum fe_delivery_system delsys = ~0;
|
||||||
char *config = "config/";
|
char *config = "config/";
|
||||||
@ -38,16 +39,18 @@ int main(int argc, char **argv)
|
|||||||
{"frequency", required_argument, 0, 'f'},
|
{"frequency", required_argument, 0, 'f'},
|
||||||
{"bandwidth", required_argument, 0, 'b'},
|
{"bandwidth", required_argument, 0, 'b'},
|
||||||
{"symbolrate", required_argument, 0, 's'},
|
{"symbolrate", required_argument, 0, 's'},
|
||||||
|
{"source", required_argument, 0, 'l'},
|
||||||
{"delsys", required_argument, 0, 'd'},
|
{"delsys", required_argument, 0, 'd'},
|
||||||
{"id", required_argument, 0, 'i'},
|
{"id", required_argument, 0, 'i'},
|
||||||
{"pls", required_argument, 0, 'g'},
|
{"pls", required_argument, 0, 'g'},
|
||||||
{"root", required_argument, 0, 'r'},
|
{"root", required_argument, 0, 'r'},
|
||||||
{"num", required_argument, 0, 'n'},
|
{"num", required_argument, 0, 'n'},
|
||||||
|
{"verbosity", required_argument, 0, 'v'},
|
||||||
{"help", no_argument , 0, 'h'},
|
{"help", no_argument , 0, 'h'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
c = getopt_long(argc, argv,
|
c = getopt_long(argc, argv,
|
||||||
"c:i:f:s:d:p:hg:r:n:b:",
|
"c:i:f:s:d:p:hg:r:n:b:l:v:",
|
||||||
long_options, &option_index);
|
long_options, &option_index);
|
||||||
if (c==-1)
|
if (c==-1)
|
||||||
break;
|
break;
|
||||||
@ -65,6 +68,12 @@ int main(int argc, char **argv)
|
|||||||
case 's':
|
case 's':
|
||||||
symbol_rate = strtoul(optarg, NULL, 0);
|
symbol_rate = strtoul(optarg, NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
case 'l':
|
||||||
|
source = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbosity = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
pls = strtoul(optarg, NULL, 0);
|
pls = strtoul(optarg, NULL, 0);
|
||||||
break;
|
break;
|
||||||
@ -102,7 +111,14 @@ int main(int argc, char **argv)
|
|||||||
pol = 0;
|
pol = 0;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
printf("no help yet\n");
|
printf("ddzap [-d delivery_system] [-p polarity] [-c config_dir] [-f frequency(Hz)]\n"
|
||||||
|
" [-b bandwidth(Hz)] [-s symbol_rate(Hz)]\n"
|
||||||
|
" [-g gold_code] [-r root_code] [-i id] [-n device_num]\n"
|
||||||
|
"\n"
|
||||||
|
" delivery_system = C,S,S2,T,T2,J83B,ISDBC,ISDBT\n"
|
||||||
|
" polarity = h,v\n"
|
||||||
|
" polarity = h,v\n"
|
||||||
|
"\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -124,7 +140,7 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dd = dddvb_init(config, 0);//0xffff);
|
dd = dddvb_init(config, verbosity);
|
||||||
if (!dd) {
|
if (!dd) {
|
||||||
printf("dddvb_init failed\n");
|
printf("dddvb_init failed\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@ -141,6 +157,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
dddvb_param_init(&p);
|
dddvb_param_init(&p);
|
||||||
dddvb_set_frequency(&p, frequency);
|
dddvb_set_frequency(&p, frequency);
|
||||||
|
dddvb_set_src(&p, source);
|
||||||
dddvb_set_bandwidth(&p, bandwidth);
|
dddvb_set_bandwidth(&p, bandwidth);
|
||||||
dddvb_set_symbol_rate(&p, symbol_rate);
|
dddvb_set_symbol_rate(&p, symbol_rate);
|
||||||
dddvb_set_polarization(&p, pol);
|
dddvb_set_polarization(&p, pol);
|
||||||
@ -148,6 +165,12 @@ int main(int argc, char **argv)
|
|||||||
dddvb_set_id(&p, id);
|
dddvb_set_id(&p, id);
|
||||||
dddvb_set_pls(&p, pls);
|
dddvb_set_pls(&p, pls);
|
||||||
dddvb_dvb_tune(fe, &p);
|
dddvb_dvb_tune(fe, &p);
|
||||||
|
{
|
||||||
|
uint8_t ts[188];
|
||||||
|
|
||||||
|
dddvb_ca_write(dd, 0, ts, 188);
|
||||||
|
|
||||||
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
fe_status_t stat;
|
fe_status_t stat;
|
||||||
int64_t str, cnr;
|
int64_t str, cnr;
|
||||||
|
@ -5,10 +5,10 @@ all: libdddvb.so.1.0.1
|
|||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(LIB_FLAGS) $(CFLAGS) -c $<
|
$(CC) $(LIB_FLAGS) $(CFLAGS) -c $<
|
||||||
|
|
||||||
libdddvb.a: dvb.o dddvb.o tools.o config.o
|
libdddvb.a: dvb.o dddvb.o tools.o config.o ca.o
|
||||||
$(AR) -cvq libdddvb.a $^
|
$(AR) -cvq libdddvb.a $^
|
||||||
|
|
||||||
libdddvb.so.1.0.1: dvb.o dddvb.o tools.o config.o
|
libdddvb.so.1.0.1: dvb.o dddvb.o tools.o config.o ca.o
|
||||||
$(CC) $(LIB_FLAGS) $(CFLAGS) -shared -Wl,-soname,libdddvb.so.1 -o libdddvb.so.1.0.1 $^ -lc
|
$(CC) $(LIB_FLAGS) $(CFLAGS) -shared -Wl,-soname,libdddvb.so.1 -o libdddvb.so.1.0.1 $^ -lc
|
||||||
ln -sf libdddvb.so.1.0.1 libdddvb.so.1
|
ln -sf libdddvb.so.1.0.1 libdddvb.so.1
|
||||||
ln -sf libdddvb.so.1.0.1 libdddvb.so
|
ln -sf libdddvb.so.1.0.1 libdddvb.so
|
||||||
@ -17,4 +17,4 @@ dddvb_test: dddvb_test.o
|
|||||||
$(CC) -o dddvb_test $< -L . -l dddvb
|
$(CC) -o dddvb_test $< -L . -l dddvb
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm *.o
|
-rm -f *.o
|
||||||
|
645
lib/src/ca.c
Normal file
645
lib/src/ca.c
Normal file
@ -0,0 +1,645 @@
|
|||||||
|
#include "libdddvb.h"
|
||||||
|
#include "dddvb.h"
|
||||||
|
#include "tools.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include <linux/dvb/dmx.h>
|
||||||
|
#include <linux/dvb/frontend.h>
|
||||||
|
#include <linux/dvb/video.h>
|
||||||
|
#include <linux/dvb/net.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/ethernet.h>
|
||||||
|
#include <net/if_arp.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
|
#define MMI_STATE_CLOSED 0
|
||||||
|
#define MMI_STATE_OPEN 1
|
||||||
|
#define MMI_STATE_ENQ 2
|
||||||
|
#define MMI_STATE_MENU 3
|
||||||
|
|
||||||
|
|
||||||
|
int set_nonblock(int fd)
|
||||||
|
{
|
||||||
|
int fl = fcntl(fd, F_GETFL);
|
||||||
|
|
||||||
|
if (fl < 0)
|
||||||
|
return fl;
|
||||||
|
return fcntl(fd, F_SETFL, fl | O_NONBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
int streamsock(const char *port, int family, struct sockaddr *sadr)
|
||||||
|
{
|
||||||
|
int one=1, sock;
|
||||||
|
struct addrinfo *ais, *ai, hints = {
|
||||||
|
.ai_flags = AI_PASSIVE,
|
||||||
|
.ai_family = family,
|
||||||
|
.ai_socktype = SOCK_STREAM,
|
||||||
|
.ai_protocol = 0, .ai_addrlen = 0,
|
||||||
|
.ai_addr = NULL, .ai_canonname = NULL, .ai_next = NULL,
|
||||||
|
};
|
||||||
|
if (getaddrinfo(NULL, port, &hints, &ais) < 0)
|
||||||
|
return -1;
|
||||||
|
for (ai = ais; ai; ai = ai->ai_next) {
|
||||||
|
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||||
|
if (sock == -1)
|
||||||
|
continue;
|
||||||
|
if (!setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) &&
|
||||||
|
!bind(sock, ai->ai_addr, ai->ai_addrlen)) {
|
||||||
|
*sadr = *ai->ai_addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close(sock);
|
||||||
|
sock = -1;
|
||||||
|
}
|
||||||
|
freeaddrinfo(ais);
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ai_callback(void *arg, uint8_t slot_id, uint16_t session_number,
|
||||||
|
uint8_t application_type, uint16_t application_manufacturer,
|
||||||
|
uint16_t manufacturer_code, uint8_t menu_string_length,
|
||||||
|
uint8_t *menu_string)
|
||||||
|
{
|
||||||
|
struct dddvb_ca *ca = arg;
|
||||||
|
|
||||||
|
dbgprintf(DEBUG_CA, "Application type: %02x\n", application_type);
|
||||||
|
dbgprintf(DEBUG_CA, "Application manufacturer: %04x\n", application_manufacturer);
|
||||||
|
dbgprintf(DEBUG_CA, "Manufacturer code: %04x\n", manufacturer_code);
|
||||||
|
dbgprintf(DEBUG_CA, "Menu string: %.*s\n", menu_string_length, menu_string);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ca_info_callback(void *arg, uint8_t slot_id, uint16_t snum,
|
||||||
|
uint32_t id_count, uint16_t *ids)
|
||||||
|
{
|
||||||
|
struct dddvb_ca *ca = arg;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
dbgprintf(DEBUG_CA, "CAM supports the following ca system ids:\n");
|
||||||
|
for (i = 0; i < id_count; i++) {
|
||||||
|
dbgprintf(DEBUG_CA, " 0x%04x\n", ids[i]);
|
||||||
|
}
|
||||||
|
ca->resource_ready = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int handle_pmt(struct dvbca *ca, uint8_t *buf, int size)
|
||||||
|
{
|
||||||
|
int listmgmt = CA_LIST_MANAGEMENT_ONLY;
|
||||||
|
uint8_t capmt[4096];
|
||||||
|
struct section *section = section_codec(buf, size);
|
||||||
|
struct section_ext *section_ext = section_ext_decode(section, 0);
|
||||||
|
struct mpeg_pmt_section *pmt = mpeg_pmt_section_codec(section_ext);
|
||||||
|
|
||||||
|
dbgprintf(DEBUG_CA, "handle pmt\n");
|
||||||
|
if (section_ext->version_number == ca->ca_pmt_version &&
|
||||||
|
ca->pmt == ca->pmt_old)
|
||||||
|
return;
|
||||||
|
if (ca->pmt != ca->pmt_old) {
|
||||||
|
ca->pmt_old = ca->pmt;
|
||||||
|
ca->sentpmt = 0;
|
||||||
|
}
|
||||||
|
if (ca->resource_ready) {
|
||||||
|
ca->data_pmt_version = pmt->head.version_number;
|
||||||
|
|
||||||
|
if (ca->sentpmt) {
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_UPDATE;
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
ca->sentpmt = 1;
|
||||||
|
dbgprintf(DEBUG_CA, "set ca_pmt\n");
|
||||||
|
|
||||||
|
if ((size = en50221_ca_format_pmt(pmt, capmt, sizeof(capmt), ca->moveca, listmgmt,
|
||||||
|
CA_PMT_CMD_ID_OK_DESCRAMBLING)) < 0) {
|
||||||
|
dbgprintf(DEBUG_CA, "Failed to format PMT\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (en50221_app_ca_pmt(ca->stdcam->ca_resource, ca->stdcam->ca_session_number, capmt, size)) {
|
||||||
|
dbgprintf(DEBUG_CA, "Failed to send PMT\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void handle_tdt(struct dddvb_ca *ca)
|
||||||
|
{
|
||||||
|
struct section *section;
|
||||||
|
struct dvb_tdt_section *tdt;
|
||||||
|
uint8_t sec[4096];
|
||||||
|
time_t dvb_time;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (ca->stdcam == NULL)
|
||||||
|
return;
|
||||||
|
if (ca->stdcam->dvbtime == NULL)
|
||||||
|
return;
|
||||||
|
len = getsec(ca->input, 0x14, 0, 0x70, sec);
|
||||||
|
if (len < 0)
|
||||||
|
return;
|
||||||
|
dbgprintf(DEBUG_CA, "got tdt\n");
|
||||||
|
|
||||||
|
section = section_codec(sec, len);
|
||||||
|
if (section == NULL)
|
||||||
|
return;
|
||||||
|
tdt = dvb_tdt_section_codec(section);
|
||||||
|
if (tdt == NULL)
|
||||||
|
return;
|
||||||
|
dvb_time = dvbdate_to_unixtime(tdt->utc_time);
|
||||||
|
|
||||||
|
dbgprintf(DEBUG_CA, "set dvbtime\n");
|
||||||
|
if (ca->stdcam->dvbtime)
|
||||||
|
ca->stdcam->dvbtime(ca->stdcam, dvb_time);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int handle_pmts(struct dddvb_ca *ca)
|
||||||
|
{
|
||||||
|
int listmgmt = CA_LIST_MANAGEMENT_ONLY;
|
||||||
|
uint8_t sec[4096], capmt[4096];
|
||||||
|
struct section *section;
|
||||||
|
struct section_ext *section_ext;
|
||||||
|
struct mpeg_pmt_section *pmt;
|
||||||
|
int i, size, num, len;
|
||||||
|
|
||||||
|
if (!ca->resource_ready)
|
||||||
|
return 0;
|
||||||
|
dbgprintf(DEBUG_CA, "handle pmts\n");
|
||||||
|
for (i = num = 0; i < MAX_PMT; i++)
|
||||||
|
if (ca->pmt[i])
|
||||||
|
num++;
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
len = -1;//getsec(ca->input, ca->pmt[i] & 0xffff, ca->pmt[i] >> 16, 2, sec);
|
||||||
|
if (len < 0)
|
||||||
|
continue;
|
||||||
|
section = section_codec(sec, len);
|
||||||
|
section_ext = section_ext_decode(section, 0);
|
||||||
|
pmt = mpeg_pmt_section_codec(section_ext);
|
||||||
|
|
||||||
|
ca->ca_pmt_version[i] = section_ext->version_number;
|
||||||
|
if (ca->sentpmt) {
|
||||||
|
//return 0;
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_UPDATE;
|
||||||
|
} else {
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_ONLY;
|
||||||
|
if (num > 1) {
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_MORE;
|
||||||
|
if (i == 0)
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_FIRST;
|
||||||
|
if (i == num - 1)
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_LAST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbgprintf(DEBUG_CA, "set ca_pmt\n");
|
||||||
|
|
||||||
|
if ((size = en50221_ca_format_pmt(pmt, capmt, sizeof(capmt), ca->moveca, listmgmt,
|
||||||
|
CA_PMT_CMD_ID_OK_DESCRAMBLING)) < 0) {
|
||||||
|
dbgprintf(DEBUG_CA, "Failed to format PMT\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//dump(capmt, size);
|
||||||
|
if (en50221_app_ca_pmt(ca->stdcam->ca_resource, ca->stdcam->ca_session_number, capmt, size)) {
|
||||||
|
dbgprintf(DEBUG_CA, "Failed to send PMT\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num)
|
||||||
|
ca->sentpmt = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
|
||||||
|
{
|
||||||
|
int listmgmt = CA_LIST_MANAGEMENT_ONLY;
|
||||||
|
uint8_t sec[4096], capmt[4096];
|
||||||
|
struct section *section;
|
||||||
|
struct section_ext *section_ext;
|
||||||
|
struct mpeg_pmt_section *pmt;
|
||||||
|
int i, size, num, len;
|
||||||
|
|
||||||
|
if (!ca->resource_ready)
|
||||||
|
return -EBUSY;
|
||||||
|
for (i = 0; i < MAX_PMT; i++)
|
||||||
|
if (!pmts[i])
|
||||||
|
break;
|
||||||
|
num = i;
|
||||||
|
dbgprintf(DEBUG_CA, "handle %d pmts\n", num);
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
memcpy(sec, pmts[i], 3);
|
||||||
|
len = ((sec[1] & 0x0f) << 8) | sec[2];
|
||||||
|
len += 3;
|
||||||
|
memcpy(sec, pmts[i], len);
|
||||||
|
section = section_codec(sec, len);
|
||||||
|
section_ext = section_ext_decode(section, 0);
|
||||||
|
pmt = mpeg_pmt_section_codec(section_ext);
|
||||||
|
|
||||||
|
ca->ca_pmt_version[i] = section_ext->version_number;
|
||||||
|
if (ca->sentpmt) {
|
||||||
|
//return 0;
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_UPDATE;
|
||||||
|
} else {
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_ONLY;
|
||||||
|
if (num > 1) {
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_MORE;
|
||||||
|
if (i == 0)
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_FIRST;
|
||||||
|
if (i == num - 1)
|
||||||
|
listmgmt = CA_LIST_MANAGEMENT_LAST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbgprintf(DEBUG_CA, "set ca_pmt\n");
|
||||||
|
|
||||||
|
if ((size = en50221_ca_format_pmt(pmt, capmt, sizeof(capmt), ca->moveca, listmgmt,
|
||||||
|
CA_PMT_CMD_ID_OK_DESCRAMBLING)) < 0) {
|
||||||
|
dbgprintf(DEBUG_CA, "Failed to format PMT\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//dump(capmt, size);
|
||||||
|
if (en50221_app_ca_pmt(ca->stdcam->ca_resource, ca->stdcam->ca_session_number, capmt, size)) {
|
||||||
|
dbgprintf(DEBUG_CA, "Failed to send PMT\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num)
|
||||||
|
ca->sentpmt = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void proc_csock_msg(struct dddvb_ca *ca, uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
if (*buf == '\r') {
|
||||||
|
return;
|
||||||
|
} else if (*buf == '\n') {
|
||||||
|
switch(ca->mmi_state) {
|
||||||
|
case MMI_STATE_CLOSED:
|
||||||
|
case MMI_STATE_OPEN:
|
||||||
|
if ((ca->mmi_bufp == 0) && (ca->resource_ready)) {
|
||||||
|
en50221_app_ai_entermenu(ca->stdcam->ai_resource,
|
||||||
|
ca->stdcam->ai_session_number);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMI_STATE_ENQ:
|
||||||
|
if (ca->mmi_bufp == 0) {
|
||||||
|
en50221_app_mmi_answ(ca->stdcam->mmi_resource,
|
||||||
|
ca->stdcam->mmi_session_number,
|
||||||
|
MMI_ANSW_ID_CANCEL, NULL, 0);
|
||||||
|
} else {
|
||||||
|
en50221_app_mmi_answ(ca->stdcam->mmi_resource,
|
||||||
|
ca->stdcam->mmi_session_number,
|
||||||
|
MMI_ANSW_ID_ANSWER,
|
||||||
|
ca->mmi_buf, ca->mmi_bufp);
|
||||||
|
}
|
||||||
|
ca->mmi_state = MMI_STATE_OPEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMI_STATE_MENU:
|
||||||
|
ca->mmi_buf[ca->mmi_bufp] = 0;
|
||||||
|
en50221_app_mmi_menu_answ(ca->stdcam->mmi_resource,
|
||||||
|
ca->stdcam->mmi_session_number,
|
||||||
|
atoi(ca->mmi_buf));
|
||||||
|
ca->mmi_state = MMI_STATE_OPEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ca->mmi_bufp = 0;
|
||||||
|
} else {
|
||||||
|
if (ca->mmi_bufp < (sizeof(ca->mmi_buf) - 1)) {
|
||||||
|
ca->mmi_buf[ca->mmi_bufp++] = *buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int proc_csock(struct dddvb_ca *ca)
|
||||||
|
{
|
||||||
|
uint8_t buf[1024];
|
||||||
|
int len, i, res;
|
||||||
|
|
||||||
|
if (ca->stdcam == NULL)
|
||||||
|
return -1;
|
||||||
|
while ((len = recv(ca->sock, buf, 1, 0)) >= 0) {
|
||||||
|
if (len == 0)
|
||||||
|
goto release;
|
||||||
|
if (len < 0) {
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
goto release;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
proc_csock_msg(ca, buf, len);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
release:
|
||||||
|
close(ca->sock);
|
||||||
|
ca->sock = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void handle_ci(struct dddvb_ca *ca)
|
||||||
|
{
|
||||||
|
uint8_t sec[4096];
|
||||||
|
uint32_t pmt_count, tdt_count;
|
||||||
|
int len;
|
||||||
|
int sock, i;
|
||||||
|
struct sockaddr sadr;
|
||||||
|
char port[6];
|
||||||
|
|
||||||
|
snprintf(port, sizeof(port), "%u", (uint16_t) (8888 + ca->nr));
|
||||||
|
sock = streamsock(port, AF_INET, &sadr);
|
||||||
|
if (listen(sock, 4) < 0) {
|
||||||
|
dbgprintf(DEBUG_CA, "listen error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ca->sock = -1;
|
||||||
|
|
||||||
|
while (1) {//!ca->exit) {
|
||||||
|
struct timeval timeout;
|
||||||
|
uint32_t count = 0;
|
||||||
|
int num;
|
||||||
|
int mfd;
|
||||||
|
fd_set fds;
|
||||||
|
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 200000;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
if (ca->sock < 0) {
|
||||||
|
FD_SET(sock, &fds);
|
||||||
|
num = select(sock + 1, &fds, NULL, NULL, &timeout);
|
||||||
|
} else {
|
||||||
|
FD_SET(ca->sock, &fds);
|
||||||
|
num = select(ca->sock + 1, &fds, NULL, NULL, &timeout);
|
||||||
|
}
|
||||||
|
if (num > 0) {
|
||||||
|
if (ca->sock < 0) {
|
||||||
|
if (FD_ISSET(sock, &fds)) {
|
||||||
|
socklen_t len;
|
||||||
|
struct sockaddr cadr;
|
||||||
|
|
||||||
|
ca->sock = accept(sock, &cadr, &len);
|
||||||
|
if (ca->sock >= 0) {
|
||||||
|
set_nonblock(ca->sock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (FD_ISSET(ca->sock, &fds)) {
|
||||||
|
proc_csock(ca);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ca->mutex);
|
||||||
|
if (!ca->state) {
|
||||||
|
pthread_mutex_unlock(&ca->mutex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ca->setpmt) {
|
||||||
|
dbgprintf(DEBUG_CA, "got new PMT %08x\n", ca->pmt_new);
|
||||||
|
memcpy(ca->pmt, ca->pmt_new, sizeof(ca->pmt));
|
||||||
|
memset(ca->pmt_old, 0, sizeof(ca->pmt_old));
|
||||||
|
for (i = 0; i < MAX_PMT; i++)
|
||||||
|
ca->ca_pmt_version[i] = -1;
|
||||||
|
ca->sentpmt = 0;
|
||||||
|
ca->setpmt = 0;
|
||||||
|
pmt_count = 0;
|
||||||
|
tdt_count = 0;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&ca->mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (!ca->sentpmt)
|
||||||
|
handle_pmts(ca);
|
||||||
|
else {
|
||||||
|
pmt_count++;
|
||||||
|
if (pmt_count == 10) {
|
||||||
|
//handle_pmts(ca);
|
||||||
|
pmt_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
tdt_count++;
|
||||||
|
if (tdt_count == 10) {
|
||||||
|
//handle_tdt(ca);
|
||||||
|
tdt_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int set_pmt(struct dddvb_ca *ca, uint32_t *pmt)
|
||||||
|
{
|
||||||
|
dbgprintf(DEBUG_CA, "set_pmt %08x %08x %08x\n", pmt[0], pmt[1], pmt[2]);
|
||||||
|
pthread_mutex_lock(&ca->mutex);
|
||||||
|
ca->setpmt = 1;
|
||||||
|
memcpy(ca->pmt_new, pmt, sizeof(ca->pmt_new));
|
||||||
|
pthread_mutex_unlock(&ca->mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ci_poll(struct dddvb_ca *ca)
|
||||||
|
{
|
||||||
|
while (!ca->dd->exit) {
|
||||||
|
ca->stdcam->poll(ca->stdcam);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int mmi_close_callback(void *arg, uint8_t slot_id, uint16_t snum,
|
||||||
|
uint8_t cmd_id, uint8_t delay)
|
||||||
|
{
|
||||||
|
struct dddvb_ca *ca = arg;
|
||||||
|
|
||||||
|
ca->mmi_state = MMI_STATE_CLOSED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mmi_display_control_callback(void *arg, uint8_t slot_id, uint16_t snum,
|
||||||
|
uint8_t cmd_id, uint8_t mmi_mode)
|
||||||
|
{
|
||||||
|
struct dddvb_ca *ca = arg;
|
||||||
|
struct en50221_app_mmi_display_reply_details reply;
|
||||||
|
|
||||||
|
if (cmd_id != MMI_DISPLAY_CONTROL_CMD_ID_SET_MMI_MODE) {
|
||||||
|
en50221_app_mmi_display_reply(ca->stdcam->mmi_resource, snum,
|
||||||
|
MMI_DISPLAY_REPLY_ID_UNKNOWN_CMD_ID, &reply);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we only support high level mode
|
||||||
|
if (mmi_mode != MMI_MODE_HIGH_LEVEL) {
|
||||||
|
en50221_app_mmi_display_reply(ca->stdcam->mmi_resource, snum,
|
||||||
|
MMI_DISPLAY_REPLY_ID_UNKNOWN_MMI_MODE, &reply);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.u.mode_ack.mmi_mode = mmi_mode;
|
||||||
|
en50221_app_mmi_display_reply(ca->stdcam->mmi_resource, snum,
|
||||||
|
MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK, &reply);
|
||||||
|
ca->mmi_state = MMI_STATE_OPEN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mmi_enq_callback(void *arg, uint8_t slot_id, uint16_t snum,
|
||||||
|
uint8_t blind_answer, uint8_t expected_answer_length,
|
||||||
|
uint8_t *text, uint32_t text_size)
|
||||||
|
{
|
||||||
|
struct dddvb_ca *ca = arg;
|
||||||
|
|
||||||
|
if (ca->sock >= 0) {
|
||||||
|
sendstring(ca->sock, "%.*s: ", text_size, text);
|
||||||
|
}
|
||||||
|
//mmi_enq_blind = blind_answer;
|
||||||
|
//mmi_enq_length = expected_answer_length;
|
||||||
|
ca->mmi_state = MMI_STATE_ENQ;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mmi_menu_callback(void *arg, uint8_t slot_id, uint16_t snum,
|
||||||
|
struct en50221_app_mmi_text *title,
|
||||||
|
struct en50221_app_mmi_text *sub_title,
|
||||||
|
struct en50221_app_mmi_text *bottom,
|
||||||
|
uint32_t item_count, struct en50221_app_mmi_text *items,
|
||||||
|
uint32_t item_raw_length, uint8_t *items_raw)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
struct dddvb_ca *ca = arg;
|
||||||
|
|
||||||
|
if (ca->sock >= 0) {
|
||||||
|
if (title->text_length)
|
||||||
|
sendstring(ca->sock, "%.*s\n", title->text_length, title->text);
|
||||||
|
if (sub_title->text_length)
|
||||||
|
sendstring(ca->sock, "%.*s\n", sub_title->text_length, sub_title->text);
|
||||||
|
for (i = 0; i < item_count; i++)
|
||||||
|
sendstring(ca->sock, "%i. %.*s\n", i + 1, items[i].text_length, items[i].text);
|
||||||
|
if (bottom->text_length)
|
||||||
|
sendstring(ca->sock, "%.*s\n", bottom->text_length, bottom->text);
|
||||||
|
}
|
||||||
|
ca->mmi_state = MMI_STATE_MENU;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int init_ca_stack(struct dddvb_ca *ca)
|
||||||
|
{
|
||||||
|
ca->tl = en50221_tl_create(1, 16);
|
||||||
|
if (ca->tl == NULL) {
|
||||||
|
dbgprintf(DEBUG_CA, "Failed to create transport layer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ca->sl = en50221_sl_create(ca->tl, 16);
|
||||||
|
if (ca->sl == NULL) {
|
||||||
|
dbgprintf(DEBUG_CA, "Failed to create session layer\n");
|
||||||
|
en50221_tl_destroy(ca->tl);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ca->stdcam = en50221_stdcam_llci_create(ca->fd, 0, ca->tl, ca->sl);
|
||||||
|
if (!ca->stdcam) {
|
||||||
|
dbgprintf(DEBUG_CA, "Failed to create stdcam\n");
|
||||||
|
en50221_sl_destroy(ca->sl);
|
||||||
|
en50221_tl_destroy(ca->tl);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ca->stdcam->ai_resource) {
|
||||||
|
en50221_app_ai_register_callback(ca->stdcam->ai_resource, ai_callback, ca);
|
||||||
|
}
|
||||||
|
if (ca->stdcam->ca_resource) {
|
||||||
|
en50221_app_ca_register_info_callback(ca->stdcam->ca_resource, ca_info_callback, ca);
|
||||||
|
}
|
||||||
|
if (ca->stdcam->mmi_resource) {
|
||||||
|
en50221_app_mmi_register_close_callback(ca->stdcam->mmi_resource, mmi_close_callback, ca);
|
||||||
|
en50221_app_mmi_register_display_control_callback(ca->stdcam->mmi_resource,
|
||||||
|
mmi_display_control_callback, ca);
|
||||||
|
en50221_app_mmi_register_enq_callback(ca->stdcam->mmi_resource, mmi_enq_callback, ca);
|
||||||
|
en50221_app_mmi_register_menu_callback(ca->stdcam->mmi_resource, mmi_menu_callback, ca);
|
||||||
|
en50221_app_mmi_register_list_callback(ca->stdcam->mmi_resource, mmi_menu_callback, ca);
|
||||||
|
} else {
|
||||||
|
dbgprintf(DEBUG_CA,
|
||||||
|
"CAM Menus are not supported by this interface hardware\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int init_ca(struct dddvb *dd, int a, int f, int fd)
|
||||||
|
{
|
||||||
|
struct dddvb_ca *ca;
|
||||||
|
char fname[80];
|
||||||
|
|
||||||
|
ca = &dd->dvbca[dd->dvbca_num];
|
||||||
|
ca->dd = dd;
|
||||||
|
ca->anum = a;
|
||||||
|
ca->fnum = f;
|
||||||
|
ca->nr = dd->dvbca_num + 1;
|
||||||
|
ca->fd = fd;
|
||||||
|
pthread_mutex_init(&ca->mutex, 0);
|
||||||
|
|
||||||
|
init_ca_stack(ca);
|
||||||
|
|
||||||
|
pthread_create(&ca->poll_pt, NULL, (void *) ci_poll, ca);
|
||||||
|
pthread_create(&ca->pt, NULL, (void *) handle_ci, ca);
|
||||||
|
|
||||||
|
sprintf(fname, "/dev/dvb/adapter%d/ci%d", a, f);
|
||||||
|
ca->ci_wfd = open(fname, O_WRONLY);
|
||||||
|
ca->ci_rfd = open(fname, O_RDONLY | O_NONBLOCK);
|
||||||
|
dd->dvbca_num++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dddvb_ca_write(struct dddvb *dd, uint32_t nr, uint8_t *buf, uint32_t len)
|
||||||
|
{
|
||||||
|
struct dddvb_ca *ca = &dd->dvbca[nr];
|
||||||
|
|
||||||
|
return write(ca->ci_wfd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dddvb_ca_read(struct dddvb *dd, uint32_t nr, uint8_t *buf, uint32_t len)
|
||||||
|
{
|
||||||
|
struct dddvb_ca *ca = &dd->dvbca[nr];
|
||||||
|
|
||||||
|
return read(ca->ci_rfd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dddvb_ca_set_pmts(struct dddvb *dd, uint32_t nr, uint8_t **pmts)
|
||||||
|
{
|
||||||
|
struct dddvb_ca *ca = &dd->dvbca[nr];
|
||||||
|
|
||||||
|
dbgprintf(DEBUG_CA, "ca_set_pmt\n");
|
||||||
|
return set_pmts(ca, pmts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int scan_dvbca(struct dddvb *dd)
|
||||||
|
{
|
||||||
|
int a, f, fd;
|
||||||
|
char fname[80];
|
||||||
|
|
||||||
|
for (a = 0; a < 16; a++) {
|
||||||
|
for (f = 0; f < 16; f++) {
|
||||||
|
sprintf(fname, "/dev/dvb/adapter%d/ca%d", a, f);
|
||||||
|
fd = open(fname, O_RDWR);
|
||||||
|
if (fd >= 0) {
|
||||||
|
init_ca(dd, a, f, fd);
|
||||||
|
//close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbgprintf(DEBUG_CA, "Found %d CA interfaces\n", dd->dvbca_num);
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,6 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
LIBDDDVB_EXPORTED uint32_t dddvb_debug;
|
LIBDDDVB_EXPORTED uint32_t dddvb_debug;
|
||||||
LIBDDDVB_EXPORTED struct dddvb *global_dd = NULL;
|
LIBDDDVB_EXPORTED struct dddvb *global_dd = NULL;
|
||||||
LIBDDDVB_EXPORTED pthread_mutex_t dddvb_mutex = PTHREAD_MUTEX_INITIALIZER;
|
LIBDDDVB_EXPORTED pthread_mutex_t dddvb_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
@ -13,7 +13,10 @@
|
|||||||
#include <linux/dvb/net.h>
|
#include <linux/dvb/net.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <libdvben50221/en50221_stdcam.h>
|
||||||
|
|
||||||
#define DDDVB_MAX_DVB_FE 256
|
#define DDDVB_MAX_DVB_FE 256
|
||||||
|
#define DDDVB_MAX_DVB_CA 256
|
||||||
|
|
||||||
#define DDDVB_MAX_SOURCE 4
|
#define DDDVB_MAX_SOURCE 4
|
||||||
|
|
||||||
@ -74,6 +77,7 @@ struct dddvb_fe {
|
|||||||
uint32_t quality;
|
uint32_t quality;
|
||||||
int64_t strength;
|
int64_t strength;
|
||||||
int64_t cnr;
|
int64_t cnr;
|
||||||
|
int64_t ber;
|
||||||
int first;
|
int first;
|
||||||
|
|
||||||
uint32_t tune;
|
uint32_t tune;
|
||||||
@ -85,6 +89,44 @@ struct dddvb_fe {
|
|||||||
struct dddvb_status status;
|
struct dddvb_status status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dddvb_ca {
|
||||||
|
struct dddvb *dd;
|
||||||
|
struct osstrm *stream;
|
||||||
|
int fd;
|
||||||
|
int ci_rfd;
|
||||||
|
int ci_wfd;
|
||||||
|
uint32_t type;
|
||||||
|
int anum;
|
||||||
|
int fnum;
|
||||||
|
int state;
|
||||||
|
int nr;
|
||||||
|
int input;
|
||||||
|
|
||||||
|
pthread_t pt;
|
||||||
|
pthread_t poll_pt;
|
||||||
|
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
|
struct en50221_transport_layer *tl;
|
||||||
|
struct en50221_session_layer *sl;
|
||||||
|
struct en50221_stdcam *stdcam;
|
||||||
|
int resource_ready;
|
||||||
|
int sentpmt;
|
||||||
|
int moveca;
|
||||||
|
int ca_pmt_version[MAX_PMT];
|
||||||
|
int data_pmt_version;
|
||||||
|
|
||||||
|
int setpmt;
|
||||||
|
uint32_t pmt[MAX_PMT];
|
||||||
|
uint32_t pmt_new[MAX_PMT];
|
||||||
|
uint32_t pmt_old[MAX_PMT];
|
||||||
|
|
||||||
|
int mmi_state;
|
||||||
|
uint8_t mmi_buf[16];
|
||||||
|
int mmi_bufp;
|
||||||
|
int sock;
|
||||||
|
};
|
||||||
|
|
||||||
struct dddvb {
|
struct dddvb {
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
pthread_mutex_t uni_lock;
|
pthread_mutex_t uni_lock;
|
||||||
@ -103,7 +145,11 @@ struct dddvb {
|
|||||||
uint32_t dvbfe_num;
|
uint32_t dvbfe_num;
|
||||||
uint32_t scif_type;
|
uint32_t scif_type;
|
||||||
|
|
||||||
|
uint32_t dvbca_num;
|
||||||
|
int exit;
|
||||||
|
|
||||||
struct dddvb_fe dvbfe[DDDVB_MAX_DVB_FE];
|
struct dddvb_fe dvbfe[DDDVB_MAX_DVB_FE];
|
||||||
|
struct dddvb_ca dvbca[DDDVB_MAX_DVB_CA];
|
||||||
};
|
};
|
||||||
|
|
||||||
int dddvb_dvb_init(struct dddvb *dd);
|
int dddvb_dvb_init(struct dddvb *dd);
|
||||||
@ -112,7 +158,7 @@ int parse_config(struct dddvb *dd, char *name, char *sec,
|
|||||||
void dddvb_fe_handle(struct dddvb_fe *fe);
|
void dddvb_fe_handle(struct dddvb_fe *fe);
|
||||||
int dddvb_fe_tune(struct dddvb_fe *fe, struct dddvb_params *p);
|
int dddvb_fe_tune(struct dddvb_fe *fe, struct dddvb_params *p);
|
||||||
int dddvb_fe_start(struct dddvb_fe *fe);
|
int dddvb_fe_start(struct dddvb_fe *fe);
|
||||||
|
int scan_dvbca(struct dddvb *dd);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _DDDVB_H_ */
|
#endif /* _DDDVB_H_ */
|
||||||
|
@ -14,6 +14,7 @@ extern uint32_t dddvb_debug;
|
|||||||
#define DEBUG_DVB 16
|
#define DEBUG_DVB 16
|
||||||
#define DEBUG_IGMP 32
|
#define DEBUG_IGMP 32
|
||||||
#define DEBUG_SWITCH 64
|
#define DEBUG_SWITCH 64
|
||||||
|
#define DEBUG_CA 128
|
||||||
#define DEBUG_DEBUG 256
|
#define DEBUG_DEBUG 256
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,6 +80,24 @@ static int get_stat(int fd, uint32_t cmd, struct dtv_fe_stats *stats)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_stat_num(int fd, uint32_t cmd, struct dtv_fe_stats *stats, int num)
|
||||||
|
{
|
||||||
|
struct dtv_property p;
|
||||||
|
struct dtv_properties c;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
p.cmd = cmd;
|
||||||
|
c.num = num;
|
||||||
|
c.props = &p;
|
||||||
|
ret = ioctl(fd, FE_GET_PROPERTY, &c);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "FE_GET_PROPERTY returned %d\n", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(stats, &p.u.st, num*sizeof(struct dtv_fe_stats));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int set_fe_input(struct dddvb_fe *fe, uint32_t fr,
|
static int set_fe_input(struct dddvb_fe *fe, uint32_t fr,
|
||||||
@ -533,6 +551,9 @@ static int open_fe(struct dddvb_fe *fe)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "dvb_quality.c"
|
||||||
|
|
||||||
static void get_stats(struct dddvb_fe *fe)
|
static void get_stats(struct dddvb_fe *fe)
|
||||||
{
|
{
|
||||||
uint16_t sig = 0, snr = 0;
|
uint16_t sig = 0, snr = 0;
|
||||||
@ -545,7 +566,7 @@ static void get_stats(struct dddvb_fe *fe)
|
|||||||
ioctl(fe->fd, FE_READ_STATUS, &stat);
|
ioctl(fe->fd, FE_READ_STATUS, &stat);
|
||||||
fe->stat = stat;
|
fe->stat = stat;
|
||||||
fe->lock = (stat == 0x1f) ? 1 : 0;
|
fe->lock = (stat == 0x1f) ? 1 : 0;
|
||||||
//calc_lq(fe);
|
calc_lq(fe);
|
||||||
if (!get_stat(fe->fd, DTV_STAT_SIGNAL_STRENGTH, &st)) {
|
if (!get_stat(fe->fd, DTV_STAT_SIGNAL_STRENGTH, &st)) {
|
||||||
|
|
||||||
fe->strength = str = st.stat[0].svalue;
|
fe->strength = str = st.stat[0].svalue;
|
||||||
@ -886,6 +907,7 @@ int dddvb_dvb_init(struct dddvb *dd)
|
|||||||
parse_config(dd, "", "scif", &scif_config);
|
parse_config(dd, "", "scif", &scif_config);
|
||||||
set_lnb(dd, 0, 0, 9750000, 10600000, 11700000);
|
set_lnb(dd, 0, 0, 9750000, 10600000, 11700000);
|
||||||
parse_config(dd, "", "LNB", &lnb_config);
|
parse_config(dd, "", "LNB", &lnb_config);
|
||||||
|
scan_dvbca(dd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
388
lib/src/dvb_quality.c
Normal file
388
lib/src/dvb_quality.c
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
static int32_t Log10x100(uint32_t x)
|
||||||
|
{
|
||||||
|
static uint32_t LookupTable[100] = {
|
||||||
|
101157945, 103514217, 105925373, 108392691, 110917482,
|
||||||
|
113501082, 116144861, 118850223, 121618600, 124451461, // 800.5 - 809.5
|
||||||
|
127350308, 130316678, 133352143, 136458314, 139636836,
|
||||||
|
142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5
|
||||||
|
160324539, 164058977, 167880402, 171790839, 175792361,
|
||||||
|
179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5
|
||||||
|
201836636, 206538016, 211348904, 216271852, 221309471,
|
||||||
|
226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5
|
||||||
|
254097271, 260015956, 266072506, 272270131, 278612117,
|
||||||
|
285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5
|
||||||
|
319889511, 327340695, 334965439, 342767787, 350751874,
|
||||||
|
358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5
|
||||||
|
402717034, 412097519, 421696503, 431519077, 441570447,
|
||||||
|
451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5
|
||||||
|
506990708, 518800039, 530884444, 543250331, 555904257,
|
||||||
|
568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5
|
||||||
|
638263486, 653130553, 668343918, 683911647, 699841996,
|
||||||
|
716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5
|
||||||
|
803526122, 822242650, 841395142, 860993752, 881048873,
|
||||||
|
901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5
|
||||||
|
};
|
||||||
|
int32_t y = 800;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if( x == 0 ) return 0;
|
||||||
|
|
||||||
|
if( x >= 1000000000 ) {
|
||||||
|
x /= 10;
|
||||||
|
y += 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (x < 100000000 ) {
|
||||||
|
x *= 10;
|
||||||
|
y -= 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( i < 100 && x > LookupTable[i] ) i += 1;
|
||||||
|
y += i;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t berq_rs(uint32_t BERNumerator, uint32_t BERDenominator)
|
||||||
|
{
|
||||||
|
int32_t LogBER = Log10x100(BERDenominator) - Log10x100(BERNumerator);
|
||||||
|
int32_t BERQual = 100;
|
||||||
|
|
||||||
|
if ( BERNumerator == 0 )
|
||||||
|
return 100;
|
||||||
|
if (LogBER < 700) {
|
||||||
|
if (LogBER < 300)
|
||||||
|
BERQual = 0;
|
||||||
|
else
|
||||||
|
BERQual = (LogBER + 5) / 5 - 40;
|
||||||
|
}
|
||||||
|
return BERQual;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t berq_bch(uint32_t BERNumerator, uint32_t BERDenominator)
|
||||||
|
{
|
||||||
|
int32_t LogBER = Log10x100(BERDenominator) - Log10x100(BERNumerator);
|
||||||
|
int32_t BERQual = 100;
|
||||||
|
|
||||||
|
if (BERNumerator == 0 )
|
||||||
|
return 100;
|
||||||
|
if (LogBER < 700) {
|
||||||
|
if( LogBER < 400 )
|
||||||
|
BERQual = 0;
|
||||||
|
else
|
||||||
|
BERQual = 40;
|
||||||
|
}
|
||||||
|
return BERQual;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t ber_quality(struct dddvb_fe *fe)
|
||||||
|
{
|
||||||
|
struct dtv_fe_stats ber;
|
||||||
|
|
||||||
|
get_stat(fe->fd, DTV_STAT_PRE_ERROR_BIT_COUNT, &ber);
|
||||||
|
get_stat(fe->fd, DTV_STAT_PRE_TOTAL_BIT_COUNT, &ber);
|
||||||
|
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t dvbsq(uint32_t snr, uint32_t fec,
|
||||||
|
uint32_t ber_num, uint32_t ber_den)
|
||||||
|
{
|
||||||
|
int32_t SignalToNoiseRel = -1000;
|
||||||
|
int32_t Quality = 0;
|
||||||
|
int32_t BERQuality = berq_rs(ber_num, ber_den);
|
||||||
|
|
||||||
|
// SNR Values for quasi errorfree reception from Nordig 2.2
|
||||||
|
static const int32_t DVBS_SN[] = {
|
||||||
|
// 1/2 2/3 3/4 5/6 7/8
|
||||||
|
0, 38, 56, 67, 0, 77, 0, 84
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fec >= FEC_NONE && fec <= FEC_7_8 )
|
||||||
|
SignalToNoiseRel = snr / 100 - DVBS_SN[fec];
|
||||||
|
|
||||||
|
if( SignalToNoiseRel < -70 )
|
||||||
|
Quality = 0;
|
||||||
|
else if( SignalToNoiseRel < 30 )
|
||||||
|
Quality = ((SignalToNoiseRel + 70) * BERQuality) / 100;
|
||||||
|
else
|
||||||
|
Quality = BERQuality;
|
||||||
|
return Quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t dvbs2q(int32_t snr, uint32_t fec, uint32_t mod,
|
||||||
|
uint32_t ber_num, uint32_t ber_den)
|
||||||
|
{
|
||||||
|
static const int32_t DVBS2_SN_QPSK[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5
|
||||||
|
0, 20, 41, 50, 57, 62, 0, 0, 72, 0, 32, 74, 7,
|
||||||
|
};
|
||||||
|
static const int32_t DVBS2_SN_8PSK[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5
|
||||||
|
0, 0, 76, 89, 0, 104, 0, 0, 117, 0, 65, 120, 0,
|
||||||
|
};
|
||||||
|
static const int32_t DVBS2_SN_16APSK[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5
|
||||||
|
0, 0, 100, 112, 120, 126, 0, 0, 139, 0, 0, 141, 0,
|
||||||
|
};
|
||||||
|
static const int32_t DVBS2_SN_32APSK[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5
|
||||||
|
0, 0, 0, 137, 146, 153, 0, 0, 167, 0, 0, 171, 0,
|
||||||
|
};
|
||||||
|
int32_t BERQuality = berq_bch(ber_num, ber_den);
|
||||||
|
int32_t Quality = 0;
|
||||||
|
int32_t SignalToNoiseRel = -1000, snc = 0;
|
||||||
|
|
||||||
|
if (fec > FEC_2_5 )
|
||||||
|
return 0;
|
||||||
|
switch (mod) {
|
||||||
|
case QPSK:
|
||||||
|
snc = DVBS2_SN_QPSK[fec];
|
||||||
|
break;
|
||||||
|
case PSK_8:
|
||||||
|
snc = DVBS2_SN_8PSK[fec];
|
||||||
|
break;
|
||||||
|
case APSK_16:
|
||||||
|
snc = DVBS2_SN_16APSK[fec];
|
||||||
|
break;
|
||||||
|
case APSK_32:
|
||||||
|
snc = DVBS2_SN_32APSK[fec];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SignalToNoiseRel = snr / 100 - snc;
|
||||||
|
|
||||||
|
if (SignalToNoiseRel < -30 )
|
||||||
|
Quality = 0;
|
||||||
|
else if( SignalToNoiseRel < 30 )
|
||||||
|
Quality = ((SignalToNoiseRel + 30) * BERQuality) / 60;
|
||||||
|
else
|
||||||
|
Quality = 100;
|
||||||
|
return Quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t dvbcq(int32_t snr, uint32_t mod,
|
||||||
|
uint32_t ber_num, uint32_t ber_den)
|
||||||
|
{
|
||||||
|
int32_t SignalToNoiseRel = 0;
|
||||||
|
int32_t Quality = 0;
|
||||||
|
int32_t BERQuality = berq_rs(ber_num, ber_den);
|
||||||
|
|
||||||
|
switch (mod) {
|
||||||
|
case QAM_16: SignalToNoiseRel = snr - 200; break;
|
||||||
|
case QAM_32: SignalToNoiseRel = snr - 230; break;
|
||||||
|
case QAM_64: SignalToNoiseRel = snr - 260; break;
|
||||||
|
case QAM_128: SignalToNoiseRel = snr - 290; break;
|
||||||
|
case QAM_256: SignalToNoiseRel = snr - 320; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SignalToNoiseRel < -70)
|
||||||
|
Quality = 0;
|
||||||
|
else if (SignalToNoiseRel < 30)
|
||||||
|
Quality = ((SignalToNoiseRel + 70) * BERQuality) / 100;
|
||||||
|
else
|
||||||
|
Quality = BERQuality;
|
||||||
|
return Quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t dvbtq(int32_t snr, uint32_t mod, uint32_t fec,
|
||||||
|
uint32_t ber_num, uint32_t ber_den)
|
||||||
|
{
|
||||||
|
int32_t Quality = 0;
|
||||||
|
int32_t BERQuality = berq_rs(ber_num, ber_den);
|
||||||
|
int32_t SignalToNoiseRel = -1000, snc = 0;
|
||||||
|
|
||||||
|
// SNR Values for quasi error free reception from Nordig 2.2
|
||||||
|
static const int32_t DVBT_SN_QPSK[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5
|
||||||
|
0, 51, 69, 79, 0, 89, 0, 97, 0, 0, 0, 0, 0,
|
||||||
|
};
|
||||||
|
static const int32_t DVBT_SN_QAM16[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5
|
||||||
|
0, 108, 131, 146, 0, 156, 0, 160, 0, 0, 0, 0, 0,
|
||||||
|
};
|
||||||
|
static const int32_t DVBT_SN_QAM64[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5
|
||||||
|
0, 165, 187, 202, 0, 216, 0, 225, 0, 0, 0, 0, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fec > FEC_2_5 )
|
||||||
|
return 0;
|
||||||
|
switch (mod) {
|
||||||
|
case QPSK:
|
||||||
|
snc = DVBT_SN_QPSK[fec];
|
||||||
|
break;
|
||||||
|
case QAM_16:
|
||||||
|
snc = DVBT_SN_QAM16[fec];
|
||||||
|
break;
|
||||||
|
case QAM_64:
|
||||||
|
snc = DVBT_SN_QAM64[fec];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SignalToNoiseRel = snr / 100 - snc;
|
||||||
|
|
||||||
|
if (SignalToNoiseRel < -70 )
|
||||||
|
Quality = 0;
|
||||||
|
else if (SignalToNoiseRel < 30)
|
||||||
|
Quality = ((SignalToNoiseRel + 70) * BERQuality)/100;
|
||||||
|
else
|
||||||
|
Quality = BERQuality;
|
||||||
|
|
||||||
|
return Quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t dvbt2q(int32_t snr, uint32_t mod, uint32_t fec, uint32_t trans, uint32_t pilot,
|
||||||
|
uint32_t ber_num, uint32_t ber_den)
|
||||||
|
{
|
||||||
|
int32_t Quality = 0;
|
||||||
|
int32_t BERQuality = berq_bch(ber_num, ber_den);
|
||||||
|
int32_t SignalToNoiseRel = -1000, snc = 0;
|
||||||
|
|
||||||
|
static const int32_t QE_SN_16K_QPSK[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5 1/4 1/3
|
||||||
|
0, 32, 59, 68, 74, 80, 0, 0, 0, 0, 49, 0, 24, 0, 15 };
|
||||||
|
static const int32_t QE_SN_16K_16QAM[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5 1/4 1/3
|
||||||
|
0, 82,116,130,136,141, 0, 0, 0, 0, 104, 0, 74, 0, 62 };
|
||||||
|
static const int32_t QE_SN_16K_64QAM[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5 1/4 1/3
|
||||||
|
0,123,165,181,190,197, 0, 0, 0, 0, 151, 0,114, 0,101 };
|
||||||
|
static const int32_t QE_SN_16K_256QAM[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5 1/4 1/3
|
||||||
|
0,164,211,232,246,255, 0, 0, 0, 0, 202, 0,153, 0,137 };
|
||||||
|
static const int32_t QE_SN_64K_QPSK[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5 1/4 1/3
|
||||||
|
0, 35, 56, 66, 72, 77, 0, 0, 0, 0, 47, 0, 22, 0, 13 };
|
||||||
|
static const int32_t QE_SN_64K_16QAM[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5 1/4 1/3
|
||||||
|
0, 87,114,125,133,138, 0, 0, 0, 0, 101, 0, 72, 0, 60 };
|
||||||
|
static const int32_t QE_SN_64K_64QAM[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5 1/4 1/3
|
||||||
|
0,130,162,177,187,194, 0, 0, 0, 0, 148, 0,111, 0, 98 };
|
||||||
|
static const int32_t QE_SN_64K_256QAM[] = {
|
||||||
|
// 1/2 2/3 3/4 4/5 5/6 6/7 7/8 8/9 AUT 3/5 9/10 2/5 1/4 1/3
|
||||||
|
0,170,208,229,243,251, 0, 0, 0, 0, 194, 0,148, 0,132 };
|
||||||
|
|
||||||
|
if (trans == TRANSMISSION_MODE_16K) {
|
||||||
|
switch (mod) {
|
||||||
|
case QPSK:
|
||||||
|
snc = QE_SN_16K_QPSK[fec];
|
||||||
|
break;
|
||||||
|
case QAM_16:
|
||||||
|
snc = QE_SN_16K_16QAM[fec];
|
||||||
|
break;
|
||||||
|
case QAM_64:
|
||||||
|
snc = QE_SN_16K_64QAM[fec];
|
||||||
|
break;
|
||||||
|
case QAM_256:
|
||||||
|
snc = QE_SN_16K_256QAM[fec];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (trans == TRANSMISSION_MODE_C3780 + 1) { /* TRANSMISSION_MODE_64K */
|
||||||
|
switch (mod) {
|
||||||
|
case QPSK:
|
||||||
|
snc = QE_SN_64K_QPSK[fec];
|
||||||
|
break;
|
||||||
|
case QAM_16:
|
||||||
|
snc = QE_SN_64K_16QAM[fec];
|
||||||
|
break;
|
||||||
|
case QAM_64:
|
||||||
|
snc = QE_SN_64K_64QAM[fec];
|
||||||
|
break;
|
||||||
|
case QAM_256:
|
||||||
|
snc = QE_SN_64K_256QAM[fec];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snc) {
|
||||||
|
SignalToNoiseRel = snr - snc;
|
||||||
|
#if 0 //FIXME
|
||||||
|
if (PilotPattern >= DVBT2_PP3 &&
|
||||||
|
PilotPattern <= DVBT2_PP4 )
|
||||||
|
SignalToNoiseRel += 5;
|
||||||
|
else if
|
||||||
|
( PilotPattern >= DVBT2_PP5 && PilotPattern <= DVBT2_PP8 )
|
||||||
|
SignalToNoiseRel += 10;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if( SignalToNoiseRel < -30 )
|
||||||
|
Quality = 0;
|
||||||
|
else if (SignalToNoiseRel < 30 )
|
||||||
|
Quality = ((SignalToNoiseRel + 30) * BERQuality)/60;
|
||||||
|
else
|
||||||
|
Quality = 100;
|
||||||
|
|
||||||
|
return Quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void calc_lq(struct dddvb_fe *fe)
|
||||||
|
{
|
||||||
|
struct dtv_fe_stats st;
|
||||||
|
int64_t str, snr;
|
||||||
|
uint32_t mod, fec, ber_num, ber_den, trans, pilot = 0, quality = 0;
|
||||||
|
|
||||||
|
get_stat(fe->fd, DTV_STAT_SIGNAL_STRENGTH, &st);
|
||||||
|
str = st.stat[0].svalue;
|
||||||
|
dbgprintf(DEBUG_DVB, "fe%d: str=%lld\n", fe->nr, str);
|
||||||
|
fe->strength = str;
|
||||||
|
str = (str * 48) / 10000 + 344;
|
||||||
|
if (str < 0)
|
||||||
|
str = 0;
|
||||||
|
if (str > 255)
|
||||||
|
str = 255;
|
||||||
|
fe->level = str;
|
||||||
|
// str: 0-255: -25dbm = 224, -65dbm = 32
|
||||||
|
// qual: 0-15 15=BER<2*10^-4 PER<10^-7
|
||||||
|
get_stat(fe->fd, DTV_STAT_CNR, &st);
|
||||||
|
snr = st.stat[0].svalue;
|
||||||
|
fe->cnr = snr;
|
||||||
|
get_property(fe->fd, DTV_INNER_FEC, &fec);
|
||||||
|
fe->param.param[PARAM_FEC] = fec;
|
||||||
|
get_property(fe->fd, DTV_MODULATION, &mod);
|
||||||
|
fe->param.param[PARAM_MTYPE] = mod;
|
||||||
|
|
||||||
|
get_stat(fe->fd, DTV_STAT_PRE_ERROR_BIT_COUNT, &st);
|
||||||
|
ber_num = st.stat[0].uvalue;
|
||||||
|
get_stat(fe->fd, DTV_STAT_PRE_TOTAL_BIT_COUNT, &st);
|
||||||
|
ber_den = st.stat[0].uvalue;
|
||||||
|
|
||||||
|
dbgprintf(DEBUG_DVB, "fe%d: snr=%lld ber=%llu/%llu\n",
|
||||||
|
fe->nr, snr, ber_num, ber_den);
|
||||||
|
dbgprintf(DEBUG_DVB, "fe%d: fec=%u mod=%u\n", fe->nr, fec, mod);
|
||||||
|
switch (fe->n_param.param[PARAM_MSYS]) {
|
||||||
|
case SYS_DVBS:
|
||||||
|
quality = dvbsq(snr, fec, ber_num, ber_den);
|
||||||
|
break;
|
||||||
|
case SYS_DVBS2:
|
||||||
|
quality = dvbs2q(snr, fec, mod, ber_num, ber_den);
|
||||||
|
break;
|
||||||
|
case SYS_DVBC_ANNEX_A:
|
||||||
|
quality = dvbcq(snr, mod, ber_num, ber_den);
|
||||||
|
break;
|
||||||
|
case SYS_DVBT:
|
||||||
|
quality = dvbtq(snr, mod, fec, ber_num, ber_den);
|
||||||
|
break;
|
||||||
|
case SYS_DVBT2:
|
||||||
|
get_property(fe->fd, DTV_TRANSMISSION_MODE, &trans);
|
||||||
|
dbgprintf(DEBUG_DVB, "fe%d: trans=%u pilot=%u\n", fe->nr, trans, pilot);
|
||||||
|
quality = dvbt2q(snr, mod, fec, trans, pilot, ber_num, ber_den);
|
||||||
|
break;
|
||||||
|
case SYS_DVBC2:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fe->quality = quality;
|
||||||
|
dbgprintf(DEBUG_DVB, "fe%d: level=%u quality=%u\n", fe->nr, fe->level, fe->quality);
|
||||||
|
}
|
||||||
|
|
@ -60,6 +60,10 @@ LIBDDDVB_EXPORTED struct dddvb *dddvb_init(char *config, uint32_t flags);
|
|||||||
LIBDDDVB_EXPORTED int dddvb_dvb_tune(struct dddvb_fe *fe, struct dddvb_params *p);
|
LIBDDDVB_EXPORTED int dddvb_dvb_tune(struct dddvb_fe *fe, struct dddvb_params *p);
|
||||||
LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc(struct dddvb *dd, uint32_t type);
|
LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc(struct dddvb *dd, uint32_t type);
|
||||||
LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc_num(struct dddvb *dd, uint32_t type, uint32_t num);
|
LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc_num(struct dddvb *dd, uint32_t type, uint32_t num);
|
||||||
|
LIBDDDVB_EXPORTED int dddvb_ca_write(struct dddvb *dd, uint32_t nr, uint8_t *buf, uint32_t len);
|
||||||
|
LIBDDDVB_EXPORTED int dddvb_ca_read(struct dddvb *dd, uint32_t nr, uint8_t *buf, uint32_t len);
|
||||||
|
LIBDDDVB_EXPORTED int dddvb_ca_set_pmts(struct dddvb *dd, uint32_t nr, uint8_t **pmts);
|
||||||
|
|
||||||
|
|
||||||
static inline void dddvb_set_frequency(struct dddvb_params *p, uint32_t freq) {
|
static inline void dddvb_set_frequency(struct dddvb_params *p, uint32_t freq) {
|
||||||
p->param[PARAM_FREQ] = freq;
|
p->param[PARAM_FREQ] = freq;
|
||||||
@ -109,6 +113,14 @@ static inline int64_t dddvb_get_cnr(struct dddvb_fe *fe) {
|
|||||||
return fe->cnr;
|
return fe->cnr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int64_t dddvb_get_ber(struct dddvb_fe *fe) {
|
||||||
|
return fe->ber;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint32_t dddvb_get_quality(struct dddvb_fe *fe) {
|
||||||
|
return fe->quality;
|
||||||
|
};
|
||||||
|
|
||||||
static inline void dddvb_param_init(struct dddvb_params *p) {
|
static inline void dddvb_param_init(struct dddvb_params *p) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -116,4 +128,10 @@ static inline void dddvb_param_init(struct dddvb_params *p) {
|
|||||||
p->param[i] = DDDVB_UNDEF;
|
p->param[i] = DDDVB_UNDEF;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static inline int dddvb_ca_write(struct dddvb *dd, uint32_t nr, uint8_t *buf, uint32_t len) {
|
||||||
|
return ca_write(dd, nr, buf, len);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _LIBDDDVB_H_ */
|
#endif /* _LIBDDDVB_H_ */
|
||||||
|
@ -1,4 +1,37 @@
|
|||||||
#include "time.h"
|
#include "time.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
|
||||||
|
int sendlen(int sock, char *buf, int len)
|
||||||
|
{
|
||||||
|
int done, todo;
|
||||||
|
|
||||||
|
for (todo = len; todo; todo -= done, buf += done)
|
||||||
|
if ((done = send(sock, buf, todo, 0)) < 0) {
|
||||||
|
printf("sendlen error\n");
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sendstring(int sock, char *fmt, ...)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
uint8_t buf[2048];
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
len = vsnprintf(buf, sizeof(buf), fmt, args);
|
||||||
|
if (len <= 0 || len >= sizeof(buf))
|
||||||
|
return 0;
|
||||||
|
sendlen(sock, buf, len);
|
||||||
|
va_end(args);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
time_t mtime(time_t *t)
|
time_t mtime(time_t *t)
|
||||||
{
|
{
|
||||||
|
@ -2,5 +2,7 @@
|
|||||||
#define _DDDVB_TOOLS_H_
|
#define _DDDVB_TOOLS_H_
|
||||||
|
|
||||||
time_t mtime(time_t *t);
|
time_t mtime(time_t *t);
|
||||||
|
int sendlen(int sock, char *buf, int len);
|
||||||
|
int sendstring(int sock, char *fmt, ...);
|
||||||
|
|
||||||
#endif /* _DDDVB_TOOLS_H_ */
|
#endif /* _DDDVB_TOOLS_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user