mirror of
				https://github.com/DigitalDevices/dddvb.git
				synced 2025-03-01 10:35:23 +00:00 
			
		
		
		
	Merge branch 'internal'
This commit is contained in:
		
							
								
								
									
										3
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
									
									
									
									
								
							@@ -14,6 +14,9 @@ libdddvb:
 | 
			
		||||
libdddvb-install:
 | 
			
		||||
	$(MAKE) -C lib install
 | 
			
		||||
 | 
			
		||||
libdddvb-clean:
 | 
			
		||||
	$(MAKE) -C lib clean
 | 
			
		||||
 | 
			
		||||
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 };
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
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,
 | 
			
		||||
@@ -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 };
 | 
			
		||||
#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)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -238,7 +238,7 @@ int main(int argc, char **argv)
 | 
			
		||||
			printf("Octopus MAXM4\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0011:
 | 
			
		||||
			fname="CIBridgeV1B_CIBridgeV1B.fpga";
 | 
			
		||||
			fname="DVBBridgeV2B_DD01_0011.fpga";
 | 
			
		||||
			printf("Octopus CI\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0012:
 | 
			
		||||
@@ -250,7 +250,7 @@ int main(int argc, char **argv)
 | 
			
		||||
			printf("Octopus PRO\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0020:
 | 
			
		||||
			fname="DVBBridgeV2B_DD01_0020.fpga";
 | 
			
		||||
			fname="DVBBridgeV2C_DD01_0020.fpga";
 | 
			
		||||
			printf("Octopus GT Mini\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0201:
 | 
			
		||||
@@ -273,6 +273,10 @@ int main(int argc, char **argv)
 | 
			
		||||
			fname="SDRModulatorV1A_DD01_0221_IQ.fpga";
 | 
			
		||||
			printf("SDRModulator IQ\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0222:
 | 
			
		||||
			fname="SDRModulatorV1A_DD01_0222_DVBT.fpga";
 | 
			
		||||
			printf("SDRModulator DVBT\n");
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			printf("UNKNOWN\n");
 | 
			
		||||
			break;
 | 
			
		||||
@@ -285,7 +289,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		printf("Using bitstream %s\n", fname);
 | 
			
		||||
 | 
			
		||||
		fsize = lseek(fh,0,SEEK_END);
 | 
			
		||||
		if( fsize > 4000000 || fsize < SectorSize )
 | 
			
		||||
		if( fsize > FlashSize/2 - 0x10000 || fsize < SectorSize )
 | 
			
		||||
		{
 | 
			
		||||
			close(fh);
 | 
			
		||||
			printf("Invalid File Size \n");
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <getopt.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;
 | 
			
		||||
	struct dvb_mod_params mp;
 | 
			
		||||
	struct dvb_mod_channel_params mc;
 | 
			
		||||
	uint32_t data;
 | 
			
		||||
	int adapter = 0, channel = 0, gain = -1;
 | 
			
		||||
	int32_t base = -1, freq = -1, rate = -1;
 | 
			
		||||
	char mod_name[128];
 | 
			
		||||
	
 | 
			
		||||
	fd = open("/dev/dvb/adapter0/mod0", O_RDONLY);
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	
 | 
			
		||||
	/* gain 0-255 */
 | 
			
		||||
	get_property(fd, MODULATOR_GAIN, &data);
 | 
			
		||||
	printf("Modulator gain = %u\n", data);
 | 
			
		||||
	set_property(fd, MODULATOR_GAIN, 100);
 | 
			
		||||
	//get_property(fd, MODULATOR_GAIN, &data);
 | 
			
		||||
	//printf("Modulator gain = %u\n", data);
 | 
			
		||||
	//set_property(fd, MODULATOR_GAIN, 100);
 | 
			
		||||
 | 
			
		||||
	get_property(fd, MODULATOR_GAIN, &data);
 | 
			
		||||
	printf("Modulator gain = %u\n", data);
 | 
			
		||||
	//get_property(fd, MODULATOR_ATTENUATOR, &data);
 | 
			
		||||
	//printf("Modulator attenuator = %u\n", data);
 | 
			
		||||
 | 
			
		||||
	get_property(fd, MODULATOR_ATTENUATOR, &data);
 | 
			
		||||
	printf("Modulator attenuator = %u\n", data);
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	get_property(fd, MODULATOR_STATUS, &data);
 | 
			
		||||
	printf("Modulator status = %u\n", data);
 | 
			
		||||
	set_property(fd, MODULATOR_STATUS, 2);
 | 
			
		||||
	if (base > 0)
 | 
			
		||||
		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);
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	//set_property(fd, MODULATOR_RESET, 0);
 | 
			
		||||
	close(fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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>
 | 
			
		||||
 *                         Marcus Metzler <mocm@metzlerbros.de>
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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>
 | 
			
		||||
 *                         Ralph Metzler <rjkm@metzlerbros.de>
 | 
			
		||||
 *
 | 
			
		||||
@@ -1105,7 +1105,7 @@ static void dummy_release(struct dvb_frontend *fe)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct dvb_frontend_ops dummy_ops = {
 | 
			
		||||
	.delsys = { SYS_DVBC_ANNEX_A },
 | 
			
		||||
	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBS, SYS_DVBS2 },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "DUMMY DVB-C/C2 DVB-T/T2",
 | 
			
		||||
		.frequency_stepsize = 166667,	/* DVB-T only */
 | 
			
		||||
@@ -1399,7 +1399,7 @@ static struct stv0910_cfg stv0910_p = {
 | 
			
		||||
	.parallel = 1,
 | 
			
		||||
	.rptlvl   = 4,
 | 
			
		||||
	.clk      = 30000000,
 | 
			
		||||
	.tsspeed  = 0x10,
 | 
			
		||||
	.tsspeed  = 0x20,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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:
 | 
			
		||||
		if (dvb->fe2)
 | 
			
		||||
			dvb_unregister_frontend(dvb->fe2);
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case 0x40:
 | 
			
		||||
		if (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,
 | 
			
		||||
		       &dvb->fe->ops.tuner_ops,
 | 
			
		||||
		       sizeof(struct dvb_tuner_ops));
 | 
			
		||||
		dvb->attached = 0x41;
 | 
			
		||||
	}
 | 
			
		||||
	dvb->attached = 0x41;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2071,7 +2072,8 @@ static void ddb_port_probe(struct ddb_port *port)
 | 
			
		||||
	/* Handle missing ports and ports without I2C */
 | 
			
		||||
 | 
			
		||||
	if (dummy_tuner && !port->nr &&
 | 
			
		||||
	    link->ids.device == 0x0005) {
 | 
			
		||||
	    (link->ids.device == 0x0005 ||
 | 
			
		||||
	     link->ids.device == 0x000a)) {
 | 
			
		||||
		port->name = "DUMMY";
 | 
			
		||||
		port->class = DDB_PORT_TUNER;
 | 
			
		||||
		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->bufregs = rm->odma_buf->base + rm->odma_buf->size * nr;
 | 
			
		||||
		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->size = OUTPUT_DMA_SIZE_SDR;
 | 
			
		||||
			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)))
 | 
			
		||||
			return -EFAULT;
 | 
			
		||||
		if (i2c.bus > dev->link[0].info->regmap->i2c->num)
 | 
			
		||||
		if (i2c.bus > dev->i2c_num)
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		if (i2c.mlen + i2c.hlen > 512)
 | 
			
		||||
			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)))
 | 
			
		||||
			return -EFAULT;
 | 
			
		||||
		if (i2c.bus > dev->link[0].info->regmap->i2c->num)
 | 
			
		||||
		if (i2c.bus > dev->i2c_num)
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		if (i2c.mlen + i2c.hlen > 250)
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
@@ -3876,6 +3878,24 @@ static ssize_t bpsnr_show(struct device *device,
 | 
			
		||||
	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,
 | 
			
		||||
			     struct device_attribute *attr, char *buf)
 | 
			
		||||
{
 | 
			
		||||
@@ -4121,6 +4141,12 @@ static struct device_attribute ddb_attrs_snr[] = {
 | 
			
		||||
	__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[] = {
 | 
			
		||||
	__ATTR_MRO(temp0, 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_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++)
 | 
			
		||||
		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]))
 | 
			
		||||
				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++)
 | 
			
		||||
		if (dev->link[i].info &&
 | 
			
		||||
		    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])
 | 
			
		||||
			pwm += 1;
 | 
			
		||||
	} else {
 | 
			
		||||
		while (pwm > 1 && temp < link->temp_tab[pwm - 2])
 | 
			
		||||
		while (pwm > 1 && temp < (link->temp_tab[pwm] - 2))
 | 
			
		||||
			pwm -= 1;
 | 
			
		||||
	}
 | 
			
		||||
	ddblwritel(link, (pwm << 8), TEMPMON_FANCONTROL);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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>
 | 
			
		||||
 *                         Marcus Metzler <mocm@metzlerbros.de>
 | 
			
		||||
 *
 | 
			
		||||
@@ -537,6 +537,16 @@ static const struct ddb_info ddb_sdr_iq = {
 | 
			
		||||
	.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 = {
 | 
			
		||||
	.type     = DDB_OCTOPRO_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(0x0220, 0x0001, ddb_sdr_atv),
 | 
			
		||||
	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 */
 | 
			
		||||
	DDB_DEVID(0x0320, 0xffff, ddb_octopro_hdin),
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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>
 | 
			
		||||
 *                         Marcus Metzler <mocm@metzlerbros.de>
 | 
			
		||||
 *
 | 
			
		||||
@@ -65,7 +65,7 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
 | 
			
		||||
	}
 | 
			
		||||
	val &= 0x70000;
 | 
			
		||||
	if (val == 0x20000)
 | 
			
		||||
		dev_err(dev->dev, "I2C bus errorx\n");
 | 
			
		||||
		dev_err(dev->dev, "I2C bus error\n");
 | 
			
		||||
	if (val)
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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>
 | 
			
		||||
 *                         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);
 | 
			
		||||
	if (stat == 0) {
 | 
			
		||||
		u32 istat = ddblreadl(link, INTERRUPT_STATUS);
 | 
			
		||||
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
	if (res && res_len)
 | 
			
		||||
 
 | 
			
		||||
@@ -114,7 +114,7 @@
 | 
			
		||||
#define MCI_CMD_STOP             (0x01)
 | 
			
		||||
#define MCI_CMD_GETSTATUS        (0x02)
 | 
			
		||||
#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_ISDBS    (0x11)
 | 
			
		||||
@@ -147,7 +147,8 @@
 | 
			
		||||
#define M4_CMD_GET_L1INFO         (0x50)
 | 
			
		||||
#define M4_CMD_GET_IDS            (0x51)
 | 
			
		||||
#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_ISDBS_TMCC     (0x55)
 | 
			
		||||
#define M4_CMD_GET_ISDBC_TSMF     (0x56)
 | 
			
		||||
@@ -179,6 +180,12 @@
 | 
			
		||||
#define M4_SIGNALINFO_FLAG_CHANGE (0x01)
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -286,27 +293,38 @@ struct mci_command {
 | 
			
		||||
			u8   retry;
 | 
			
		||||
			u32  frequency;
 | 
			
		||||
		} j83b_search;
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
			u8   flags;              //  Bit 0 : 1 = short info (1st 4 Bytes)
 | 
			
		||||
		} get_signalinfo;
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
			u8   tap;
 | 
			
		||||
			u8   rsvd;
 | 
			
		||||
			u16  point;
 | 
			
		||||
		} get_iq_symbol;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
			u8   flags;              /*  Bit 0 : 0 = VTM, 1 = SCAN.  Bit 1: Set Gain */
 | 
			
		||||
			u8   roll_off;
 | 
			
		||||
			u8   rsvd1;
 | 
			
		||||
			u8   rsvd2;              
 | 
			
		||||
			u32  frequency;
 | 
			
		||||
			u32  symbol_rate;         /* Only in VTM mode. */
 | 
			
		||||
			u16  gain;
 | 
			
		||||
			uint8_t   flags;    /* Bit 0 : 0 = VTM/SDR, 1 = SCAN,  Bit 1: Disable AGC, Bit 2: Set Gain */
 | 
			
		||||
			uint8_t   roll_off;
 | 
			
		||||
			uint8_t   rsvd1;
 | 
			
		||||
			uint8_t   rsvd2;
 | 
			
		||||
			uint32_t  frequency;
 | 
			
		||||
			uint32_t  symbol_rate; /* Only in VTM/SDR mode, SCAN Mode uses exactly 1550/24 MSymbols/s.*/
 | 
			
		||||
			uint8_t   gain;         /* Gain in 0.25 dB Steps */
 | 
			
		||||
			/* Frequency, symbolrate and gain can be schanged while running */
 | 
			
		||||
		} sx8_start_iq;
 | 
			
		||||
		
 | 
			
		||||
		struct {
 | 
			
		||||
			/* Bit 1:0 = STVVGLNA Gain.  0 = AGC, 1 = 0dB,
 | 
			
		||||
			   2 = Minimum, 3 = Maximum */
 | 
			
		||||
			u8     flags; 
 | 
			
		||||
			uint8_t   flags;
 | 
			
		||||
                        /*   Bit 0:1 Preamp Mode;  0 = Preamp AGC, 1 == Minimum (~ -17dB) ,
 | 
			
		||||
			     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;
 | 
			
		||||
		
 | 
			
		||||
		struct {
 | 
			
		||||
@@ -357,8 +375,8 @@ struct mci_result {
 | 
			
		||||
		
 | 
			
		||||
		struct {
 | 
			
		||||
			u8  standard; /* 1 = DVB-S, 2 = DVB-S2X */
 | 
			
		||||
			u8  pls_code; /* puncture rate for DVB-S */
 | 
			
		||||
			u8  roll_off;           /* 2-0: rolloff */
 | 
			
		||||
			u8  pls_code; /* PLS code for DVB-S2/S2X, puncture rate for DVB-S */
 | 
			
		||||
			u8  roll_off; /* 2-0: rolloff, 7: spectrum inversion */
 | 
			
		||||
			u8  flags;
 | 
			
		||||
			u32 frequency;         /* actual frequency 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  Rsvd0;
 | 
			
		||||
			u8  Flags;
 | 
			
		||||
			//u16 tps_cell_id;       /* Cell Identifier */
 | 
			
		||||
 | 
			
		||||
			u32 frequency;         /* actual frequency in Hz */
 | 
			
		||||
			u32 rsvd1;
 | 
			
		||||
			s16 channel_power;     /* channel power in dBm x 100 */
 | 
			
		||||
@@ -492,6 +508,7 @@ struct mci_result {
 | 
			
		||||
		
 | 
			
		||||
		struct {
 | 
			
		||||
			u8   TPSInfo[7];
 | 
			
		||||
                        // uint16_t TPS_CellID;        // Cell Identifier
 | 
			
		||||
		} DVBT_TPSInfo;
 | 
			
		||||
		
 | 
			
		||||
		struct {
 | 
			
		||||
@@ -620,6 +637,8 @@ struct mci_result {
 | 
			
		||||
			u8  SYNCD[2];
 | 
			
		||||
			u8  rsvd;
 | 
			
		||||
			u8  ISSY[3];
 | 
			
		||||
			u8  min_input_stream_id;
 | 
			
		||||
			u8  max_input_stream_id;
 | 
			
		||||
		} BBHeader;
 | 
			
		||||
		
 | 
			
		||||
		struct {
 | 
			
		||||
@@ -644,7 +663,11 @@ struct mci_result {
 | 
			
		||||
			u8   Extension[8];   // 61 bits, right aligned
 | 
			
		||||
		} 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)
 | 
			
		||||
{
 | 
			
		||||
	switch (tvp->cmd) {
 | 
			
		||||
	case MODULATOR_OUTPUT_ARI:
 | 
			
		||||
		return mod3_set_ari(mod, tvp->u.data);
 | 
			
		||||
 | 
			
		||||
	case MODULATOR_OUTPUT_RATE:
 | 
			
		||||
		return mod3_set_sample_rate(mod, tvp->u.data);
 | 
			
		||||
 | 
			
		||||
	case MODULATOR_FREQUENCY:
 | 
			
		||||
		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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	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)
 | 
			
		||||
		return -1;
 | 
			
		||||
	switch (tvp->cmd) {
 | 
			
		||||
	case MODULATOR_INFO:
 | 
			
		||||
		tvp->u.data = 2;
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case MODULATOR_GAIN:
 | 
			
		||||
		tvp->u.data = 0xff & ddbreadl(dev, RF_VGA);;
 | 
			
		||||
		tvp->u.data = 0xff & ddbreadl(dev, RF_VGA);
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case MODULATOR_ATTENUATOR:
 | 
			
		||||
@@ -1897,6 +1953,8 @@ int ddbridge_mod_init(struct ddb *dev)
 | 
			
		||||
		return mod_init_3(dev, 503250000);
 | 
			
		||||
	case 17:
 | 
			
		||||
		return mod_init_sdr_iq(dev);
 | 
			
		||||
	case 18:
 | 
			
		||||
		return mod_init_sdr_iq(dev);
 | 
			
		||||
	default:
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ static u16 calc_pcs16(struct dvb_ns_params *p, int ipv)
 | 
			
		||||
	u32 sum = 0, i;
 | 
			
		||||
	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->dip[i] << 8) | p->dip[i + 1];
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,14 @@
 | 
			
		||||
#include "ddbridge-i2c.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 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);
 | 
			
		||||
 | 
			
		||||
#define SX8_TUNER_NUM 4
 | 
			
		||||
@@ -52,6 +58,7 @@ struct sx8 {
 | 
			
		||||
 | 
			
		||||
	int                  first_time_lock;
 | 
			
		||||
	int                  started;
 | 
			
		||||
	int                  iq_started;
 | 
			
		||||
 | 
			
		||||
	u32                  bb_mode;
 | 
			
		||||
	u32                  local_frequency;
 | 
			
		||||
@@ -131,6 +138,7 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
 | 
			
		||||
				dvbs2_bits_per_symbol[
 | 
			
		||||
					state->mci.signal_info.
 | 
			
		||||
					dvbs2_signal_info.pls_code];
 | 
			
		||||
			//printk("PLS %02x\n", state->mci.signal_info.dvbs2_signal_info.pls_code);
 | 
			
		||||
		} else 
 | 
			
		||||
			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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	struct sx8 *state = fe->demodulator_priv;
 | 
			
		||||
@@ -285,13 +312,13 @@ unlock:
 | 
			
		||||
	if (sx8_base->iq_mode) {
 | 
			
		||||
		cmd.command = SX8_CMD_ENABLE_IQOUTPUT;
 | 
			
		||||
		cmd.demod = state->mci.demod;
 | 
			
		||||
		cmd.output = 0;
 | 
			
		||||
		cmd.output = p->stream_id & 7;
 | 
			
		||||
		ddb_mci_cmd(&state->mci, &cmd, NULL);
 | 
			
		||||
		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;
 | 
			
		||||
	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.dvbs2_search.flags = flags;
 | 
			
		||||
	cmd.dvbs2_search.s2_modulation_mask = modmask;
 | 
			
		||||
@@ -357,7 +384,7 @@ unlock:
 | 
			
		||||
	cmd.demod = state->mci.demod;
 | 
			
		||||
	stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
 | 
			
		||||
	if (stat)
 | 
			
		||||
		stop(fe);
 | 
			
		||||
		stop_iq(fe);
 | 
			
		||||
	ddb_mci_config(&state->mci, ts_config);
 | 
			
		||||
	return stat;
 | 
			
		||||
}
 | 
			
		||||
@@ -369,16 +396,18 @@ static int set_parameters(struct dvb_frontend *fe)
 | 
			
		||||
	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 | 
			
		||||
	u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi;
 | 
			
		||||
 | 
			
		||||
	stop(fe);
 | 
			
		||||
	
 | 
			
		||||
	isi = p->stream_id;
 | 
			
		||||
	if (isi != NO_STREAM_ID_FILTER) {
 | 
			
		||||
		iq_mode = (isi & 0x30000000) >> 28;
 | 
			
		||||
	}
 | 
			
		||||
	if (iq_mode)
 | 
			
		||||
		ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ);
 | 
			
		||||
	stop(fe);
 | 
			
		||||
	if (iq_mode < 2) {
 | 
			
		||||
		u32 mask;
 | 
			
		||||
 | 
			
		||||
		stop_iq(fe);
 | 
			
		||||
		switch (p->modulation) {
 | 
			
		||||
		case APSK_256:
 | 
			
		||||
			mask = 0x7f;
 | 
			
		||||
@@ -396,17 +425,22 @@ static int set_parameters(struct dvb_frontend *fe)
 | 
			
		||||
			mask = 0x07;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			mask = 0x03;
 | 
			
		||||
			mask = default_mod;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		stat = start(fe, 3, mask, ts_config);
 | 
			
		||||
		if (!stat) {
 | 
			
		||||
			state->started = 1;
 | 
			
		||||
			state->first_time_lock = 1;
 | 
			
		||||
			state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		stat = start_iq(fe, iq_mode & 1, 4, ts_config);
 | 
			
		||||
	}
 | 
			
		||||
	if (!stat) {
 | 
			
		||||
		state->started = 1;
 | 
			
		||||
		state->first_time_lock = 1;
 | 
			
		||||
		state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
 | 
			
		||||
		if (!stat) {
 | 
			
		||||
			state->iq_started = 1;
 | 
			
		||||
			state->first_time_lock = 1;
 | 
			
		||||
			state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return stat;
 | 
			
		||||
}
 | 
			
		||||
@@ -446,6 +480,7 @@ static int set_input(struct dvb_frontend *fe, int input)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	if (state->mci.tuner == input)
 | 
			
		||||
		return 0;
 | 
			
		||||
	stop_iq(fe);
 | 
			
		||||
	stop(fe);
 | 
			
		||||
	state->mci.tuner = p->input = input;
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -453,6 +488,7 @@ static int set_input(struct dvb_frontend *fe, int input)
 | 
			
		||||
 | 
			
		||||
static int sleep(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	stop_iq(fe);
 | 
			
		||||
	stop(fe);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ddbridge.h: Digital Devices PCIe bridge driver
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010-2017 Digital Devices GmbH
 | 
			
		||||
 *                         Ralph Metzler <rmetzler@digitaldevices.de>
 | 
			
		||||
 * Copyright (C) 2010-2019 Digital Devices GmbH
 | 
			
		||||
 *                         Marcus Metzler <mocm@metzlerbros.de>
 | 
			
		||||
 *                         Ralph Metzler <rjkm@metzlerbros.de>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * 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)
 | 
			
		||||
{
 | 
			
		||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
 | 
			
		||||
	rbuf->pread = &rbuf->pwrite;
 | 
			
		||||
	rbuf->pread = rbuf->pwrite;
 | 
			
		||||
#else
 | 
			
		||||
	/* dvb_ringbuffer_flush() counts as read operation
 | 
			
		||||
	 * 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 dvr_pad = 0;
 | 
			
		||||
	unsigned ntuner = 0, ndemod = 0;
 | 
			
		||||
	u16 source_pad = 0;
 | 
			
		||||
	int ret;
 | 
			
		||||
	static const char *connector_name = "Television";
 | 
			
		||||
 | 
			
		||||
@@ -657,8 +658,19 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 | 
			
		||||
		ret = media_device_register_entity(mdev, conn);
 | 
			
		||||
		if (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,
 | 
			
		||||
						     MEDIA_ENT_F_CONN_RF,
 | 
			
		||||
						     conn, 0,
 | 
			
		||||
@@ -666,22 +678,33 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 | 
			
		||||
						     demod, 0,
 | 
			
		||||
						     MEDIA_LNK_FL_ENABLED,
 | 
			
		||||
						     false);
 | 
			
		||||
		else
 | 
			
		||||
		} else {
 | 
			
		||||
			ret = media_create_pad_links(mdev,
 | 
			
		||||
						     MEDIA_ENT_F_CONN_RF,
 | 
			
		||||
						     conn, 0,
 | 
			
		||||
						     MEDIA_ENT_F_TUNER,
 | 
			
		||||
						     tuner, TUNER_PAD_RF_INPUT,
 | 
			
		||||
						     tuner, source_pad,
 | 
			
		||||
						     MEDIA_LNK_FL_ENABLED,
 | 
			
		||||
						     false);
 | 
			
		||||
		}
 | 
			
		||||
		if (ret)
 | 
			
		||||
			return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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,
 | 
			
		||||
					     MEDIA_ENT_F_TUNER,
 | 
			
		||||
					     tuner, TUNER_PAD_OUTPUT,
 | 
			
		||||
					     tuner, source_pad,
 | 
			
		||||
					     MEDIA_ENT_F_DTV_DEMOD,
 | 
			
		||||
					     demod, 0, MEDIA_LNK_FL_ENABLED,
 | 
			
		||||
					     false);
 | 
			
		||||
 
 | 
			
		||||
@@ -355,6 +355,7 @@ static int read_tps(struct cxd_state *state, u8 *tps)
 | 
			
		||||
/*  OFDMInfo[3] [3:0]  OFDM_NDSYM[11:8] */
 | 
			
		||||
/*  OFDMInfo[4] [7:0]  OFDM_NDSYM[7:0]  */
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm)
 | 
			
		||||
{
 | 
			
		||||
	if (state->last_status != 0x1f)
 | 
			
		||||
@@ -365,6 +366,7 @@ static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm)
 | 
			
		||||
	unfreeze_regst(state);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Read DVBT2 QAM, 
 | 
			
		||||
   Data PLP
 | 
			
		||||
@@ -390,6 +392,7 @@ static int read_t2_ofdm_info(struct cxd_state *state, u8 *ofdm)
 | 
			
		||||
 19-37 same for common PLP
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int read_t2_tlp_info(struct cxd_state *state, u8 off, u8 count, u8 *tlp)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_frontend *fe = &state->frontend;
 | 
			
		||||
	//struct dvb_frontend *fe = &state->frontend;
 | 
			
		||||
	u8 ofdm[5], modcod[2];
 | 
			
		||||
	
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_frontend *fe = &state->frontend;
 | 
			
		||||
	//struct dvb_frontend *fe = &state->frontend;
 | 
			
		||||
	u8 tps[7];
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_frontend *fe = &state->frontend;
 | 
			
		||||
	//struct dvb_frontend *fe = &state->frontend;
 | 
			
		||||
	u8 qam;
 | 
			
		||||
 | 
			
		||||
	freeze_regst(state);
 | 
			
		||||
 
 | 
			
		||||
@@ -106,6 +106,7 @@ static int lnbh25_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int lnbh25_set_tone(struct dvb_frontend *fe,
 | 
			
		||||
			   enum fe_sec_tone_mode tone)
 | 
			
		||||
{
 | 
			
		||||
@@ -113,6 +114,7 @@ static int lnbh25_set_tone(struct dvb_frontend *fe,
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int lnbh25_init(struct lnbh25 *lnbh)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -98,26 +98,6 @@ struct mxl {
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	u32 i;
 | 
			
		||||
@@ -249,6 +229,7 @@ static int write_register(struct mxl *state, u32 reg, u32 val)
 | 
			
		||||
	return stat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int write_register_block(struct mxl *state, u32 reg,
 | 
			
		||||
				u32 size, u8 *data)
 | 
			
		||||
{
 | 
			
		||||
@@ -272,6 +253,7 @@ static int write_register_block(struct mxl *state, u32 reg,
 | 
			
		||||
	mutex_unlock(&state->base->i2c_lock);
 | 
			
		||||
	return stat;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int write_firmware_block(struct mxl *state,
 | 
			
		||||
				u32 reg, u32 size, u8 *regDataPtr)
 | 
			
		||||
@@ -375,6 +357,7 @@ static int update_by_mnemonic(struct mxl *state,
 | 
			
		||||
	return stat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static void extract_from_mnemonic(u32 regAddr, u8 lsbPos, u8 width,
 | 
			
		||||
				  u32 *toAddr, u8 *toLsbPos, u8 *toWidth)
 | 
			
		||||
{
 | 
			
		||||
@@ -385,6 +368,7 @@ static void extract_from_mnemonic(u32 regAddr, u8 lsbPos, u8 width,
 | 
			
		||||
	if (toWidth)
 | 
			
		||||
		*toWidth = width;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int firmware_is_alive(struct mxl *state)
 | 
			
		||||
{
 | 
			
		||||
@@ -397,6 +381,8 @@ static int firmware_is_alive(struct mxl *state)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (hb1 == hb0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	pr_info("mxl5xx: Hydra FW alive. Hail!\n");
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -470,9 +456,9 @@ static int CfgDemodAbortTune(struct mxl *state)
 | 
			
		||||
			    &cmdBuff[0]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int reset_fec_counter(struct mxl *state)
 | 
			
		||||
{
 | 
			
		||||
	MXL_HYDRA_DEMOD_ABORT_TUNE_T abortTuneCmd;
 | 
			
		||||
	u32 demodIndex = (u32) state->demod;
 | 
			
		||||
	u8 cmdSize = sizeof(u32);
 | 
			
		||||
	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,
 | 
			
		||||
			    &cmdBuff[0]);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int send_master_cmd(struct dvb_frontend *fe,
 | 
			
		||||
			   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))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	pr_info("mxl5xx: Hydra FW alive. Hail!\n");
 | 
			
		||||
 | 
			
		||||
	/* sometimes register values are wrong shortly
 | 
			
		||||
	   after first heart beats */
 | 
			
		||||
	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_MIN6}, {XPT_NCO_COUNT_MIN7} };
 | 
			
		||||
	
 | 
			
		||||
#if 0
 | 
			
		||||
	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_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_18_PINMUX_SEL}, {PAD_MUX_DIGIO_10_PINMUX_SEL},
 | 
			
		||||
		{PAD_MUX_DIGIO_09_PINMUX_SEL}, {PAD_MUX_DIGIO_02_PINMUX_SEL}};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	demodId = state->base->ts_map[demodId];
 | 
			
		||||
	
 | 
			
		||||
@@ -1609,6 +1596,7 @@ static int config_mux(struct mxl *state)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int config_dis(struct mxl *state, u32 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,
 | 
			
		||||
			    &cmdBuff[0]);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
		u32 ber;
 | 
			
		||||
		
 | 
			
		||||
		stv090x_read_cnr(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)
 | 
			
		||||
{
 | 
			
		||||
        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;
 | 
			
		||||
        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)
 | 
			
		||||
{
 | 
			
		||||
	struct stv090x_state *state = fe->demodulator_priv;
 | 
			
		||||
	u8 tmp;
 | 
			
		||||
	//u8 tmp;
 | 
			
		||||
	u32 reg = 0;
 | 
			
		||||
	
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int write_reg_off(struct stv *state, u16 reg, u8 val)
 | 
			
		||||
{
 | 
			
		||||
	return write_reg(state, reg + state->regoff, val);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr,
 | 
			
		||||
				  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)
 | 
			
		||||
{
 | 
			
		||||
#if 0
 | 
			
		||||
	struct stv *state = fe->demodulator_priv;
 | 
			
		||||
	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(DISTXCFG, 0x3a);
 | 
			
		||||
	wait_dis(state, 0x20, 0x20);
 | 
			
		||||
#endif
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int read_regs(struct stv *state, u8 reg, u8 *val, int len)
 | 
			
		||||
{
 | 
			
		||||
	return i2c_read(state->i2c, state->adr, ®, 1, val, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static void dump_regs(struct stv *state)
 | 
			
		||||
{
 | 
			
		||||
	u8 d[11], *c = &state->reg[0];
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,16 @@ struct dvb_mod_channel_params {
 | 
			
		||||
#define MODULATOR_GAIN           35
 | 
			
		||||
#define MODULATOR_RESET          36
 | 
			
		||||
#define MODULATOR_STATUS         37
 | 
			
		||||
#define MODULATOR_INFO           38
 | 
			
		||||
#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_*/
 | 
			
		||||
 
 | 
			
		||||
@@ -13,11 +13,11 @@ install: all
 | 
			
		||||
	$(CC) $(CFLAGS) -fPIC -c $< 
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
	$(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:
 | 
			
		||||
	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_params p;
 | 
			
		||||
	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_delivery_system delsys = ~0;
 | 
			
		||||
	char *config = "config/";
 | 
			
		||||
@@ -38,16 +39,18 @@ int main(int argc, char **argv)
 | 
			
		||||
			{"frequency", required_argument, 0, 'f'},
 | 
			
		||||
			{"bandwidth", required_argument, 0, 'b'},
 | 
			
		||||
			{"symbolrate", required_argument, 0, 's'},
 | 
			
		||||
			{"source", required_argument, 0, 'l'},
 | 
			
		||||
			{"delsys", required_argument, 0, 'd'},
 | 
			
		||||
			{"id", required_argument, 0, 'i'},
 | 
			
		||||
			{"pls", required_argument, 0, 'g'},
 | 
			
		||||
			{"root", required_argument, 0, 'r'},
 | 
			
		||||
			{"num", required_argument, 0, 'n'},
 | 
			
		||||
			{"verbosity", required_argument, 0, 'v'},
 | 
			
		||||
			{"help", no_argument , 0, 'h'},
 | 
			
		||||
			{0, 0, 0, 0}
 | 
			
		||||
		};
 | 
			
		||||
                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);
 | 
			
		||||
		if (c==-1)
 | 
			
		||||
 			break;
 | 
			
		||||
@@ -65,6 +68,12 @@ int main(int argc, char **argv)
 | 
			
		||||
		case 's':
 | 
			
		||||
			symbol_rate = strtoul(optarg, NULL, 0);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'l':
 | 
			
		||||
			source = strtoul(optarg, NULL, 0);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'v':
 | 
			
		||||
			verbosity = strtoul(optarg, NULL, 0);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'g':
 | 
			
		||||
			pls = strtoul(optarg, NULL, 0);
 | 
			
		||||
			break;
 | 
			
		||||
@@ -102,7 +111,14 @@ int main(int argc, char **argv)
 | 
			
		||||
				pol = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		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);
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
@@ -124,7 +140,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dd = dddvb_init(config, 0);//0xffff);
 | 
			
		||||
	dd = dddvb_init(config, verbosity);
 | 
			
		||||
	if (!dd) {
 | 
			
		||||
		printf("dddvb_init failed\n");
 | 
			
		||||
		exit(-1);
 | 
			
		||||
@@ -141,6 +157,7 @@ int main(int argc, char **argv)
 | 
			
		||||
	}
 | 
			
		||||
	dddvb_param_init(&p);
 | 
			
		||||
	dddvb_set_frequency(&p, frequency);
 | 
			
		||||
	dddvb_set_src(&p, source);
 | 
			
		||||
	dddvb_set_bandwidth(&p, bandwidth);
 | 
			
		||||
	dddvb_set_symbol_rate(&p, symbol_rate);
 | 
			
		||||
	dddvb_set_polarization(&p, pol);
 | 
			
		||||
@@ -148,6 +165,12 @@ int main(int argc, char **argv)
 | 
			
		||||
	dddvb_set_id(&p, id);
 | 
			
		||||
	dddvb_set_pls(&p, pls);
 | 
			
		||||
	dddvb_dvb_tune(fe, &p);
 | 
			
		||||
	{
 | 
			
		||||
		uint8_t ts[188];
 | 
			
		||||
		
 | 
			
		||||
		dddvb_ca_write(dd, 0, ts, 188);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	while (1) {
 | 
			
		||||
		fe_status_t stat;
 | 
			
		||||
		int64_t str, cnr;
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,10 @@ all: libdddvb.so.1.0.1
 | 
			
		||||
%.o: %.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 $^
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
	ln -sf libdddvb.so.1.0.1 libdddvb.so.1 
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
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 <string.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
LIBDDDVB_EXPORTED uint32_t dddvb_debug;
 | 
			
		||||
LIBDDDVB_EXPORTED struct dddvb *global_dd = NULL;
 | 
			
		||||
LIBDDDVB_EXPORTED pthread_mutex_t dddvb_mutex = PTHREAD_MUTEX_INITIALIZER; 
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,10 @@
 | 
			
		||||
#include <linux/dvb/net.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <libdvben50221/en50221_stdcam.h>
 | 
			
		||||
 | 
			
		||||
#define DDDVB_MAX_DVB_FE 256
 | 
			
		||||
#define DDDVB_MAX_DVB_CA 256
 | 
			
		||||
 | 
			
		||||
#define DDDVB_MAX_SOURCE 4
 | 
			
		||||
 | 
			
		||||
@@ -74,6 +77,7 @@ struct dddvb_fe {
 | 
			
		||||
	uint32_t quality;
 | 
			
		||||
	int64_t strength;
 | 
			
		||||
	int64_t cnr;
 | 
			
		||||
	int64_t ber;
 | 
			
		||||
	int first;
 | 
			
		||||
 | 
			
		||||
	uint32_t tune;
 | 
			
		||||
@@ -85,6 +89,44 @@ struct dddvb_fe {
 | 
			
		||||
	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 {
 | 
			
		||||
	pthread_mutex_t lock;
 | 
			
		||||
	pthread_mutex_t uni_lock;
 | 
			
		||||
@@ -103,7 +145,11 @@ struct dddvb {
 | 
			
		||||
	uint32_t dvbfe_num;
 | 
			
		||||
	uint32_t scif_type;
 | 
			
		||||
 | 
			
		||||
	uint32_t dvbca_num;
 | 
			
		||||
	int exit;
 | 
			
		||||
	
 | 
			
		||||
	struct dddvb_fe dvbfe[DDDVB_MAX_DVB_FE];
 | 
			
		||||
	struct dddvb_ca dvbca[DDDVB_MAX_DVB_CA];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
int dddvb_fe_tune(struct dddvb_fe *fe, struct dddvb_params *p);
 | 
			
		||||
int dddvb_fe_start(struct dddvb_fe *fe);
 | 
			
		||||
 | 
			
		||||
int scan_dvbca(struct dddvb *dd);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* _DDDVB_H_ */
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ extern uint32_t dddvb_debug;
 | 
			
		||||
#define DEBUG_DVB     16
 | 
			
		||||
#define DEBUG_IGMP    32
 | 
			
		||||
#define DEBUG_SWITCH  64
 | 
			
		||||
#define DEBUG_CA     128
 | 
			
		||||
#define DEBUG_DEBUG  256
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,24 @@ static int get_stat(int fd, uint32_t cmd, struct dtv_fe_stats *stats)
 | 
			
		||||
	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,
 | 
			
		||||
@@ -533,6 +551,9 @@ static int open_fe(struct dddvb_fe *fe)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "dvb_quality.c"
 | 
			
		||||
 | 
			
		||||
static void get_stats(struct dddvb_fe *fe)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
	fe->stat = stat;
 | 
			
		||||
	fe->lock = (stat == 0x1f) ? 1 : 0;
 | 
			
		||||
	//calc_lq(fe);
 | 
			
		||||
	calc_lq(fe);
 | 
			
		||||
	if (!get_stat(fe->fd, DTV_STAT_SIGNAL_STRENGTH, &st)) {
 | 
			
		||||
 | 
			
		||||
		fe->strength = str = st.stat[0].svalue;
 | 
			
		||||
@@ -886,6 +907,7 @@ int dddvb_dvb_init(struct dddvb *dd)
 | 
			
		||||
	parse_config(dd, "", "scif", &scif_config);
 | 
			
		||||
	set_lnb(dd, 0, 0, 9750000, 10600000, 11700000);
 | 
			
		||||
	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 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 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) {
 | 
			
		||||
	p->param[PARAM_FREQ] = freq;
 | 
			
		||||
@@ -109,6 +113,14 @@ static inline int64_t dddvb_get_cnr(struct dddvb_fe *fe) {
 | 
			
		||||
	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) {
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
@@ -116,4 +128,10 @@ static inline void dddvb_param_init(struct dddvb_params *p) {
 | 
			
		||||
		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_ */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,37 @@
 | 
			
		||||
#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)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -2,5 +2,7 @@
 | 
			
		||||
#define _DDDVB_TOOLS_H_
 | 
			
		||||
 | 
			
		||||
time_t mtime(time_t *t);
 | 
			
		||||
int sendlen(int sock, char *buf, int len);
 | 
			
		||||
int sendstring(int sock, char *fmt, ...);
 | 
			
		||||
 | 
			
		||||
#endif /* _DDDVB_TOOLS_H_ */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user