mirror of
				https://github.com/DigitalDevices/dddvb.git
				synced 2025-03-01 10:35:23 +00:00 
			
		
		
		
	Merge branch 'master' of https://github.com/DigitalDevices/dddvb
This commit is contained in:
		
							
								
								
									
										10
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile
									
									
									
									
									
								
							@@ -2,10 +2,15 @@ kernelver ?= $(shell uname -r)
 | 
			
		||||
KDIR	?= /lib/modules/$(kernelver)/build
 | 
			
		||||
PWD	:= $(shell pwd)
 | 
			
		||||
 | 
			
		||||
MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CXD2099=m CONFIG_DVB_LNBP21=m  CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m CONFIG_DVB_STV0367=m CONFIG_DVB_TDA18212=m CONFIG_DVB_STV0367DD=m CONFIG_DVB_TDA18212DD=m CONFIG_DVB_OCTONET=m CONFIG_DVB_CXD2843=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6111=m CONFIG_DVB_LNBH25=m CONFIG_DVB_MXL5XX=m CONFIG_DVB_NET=m
 | 
			
		||||
MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CXD2099=m CONFIG_DVB_LNBP21=m  CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m CONFIG_DVB_STV0367=m CONFIG_DVB_TDA18212=m CONFIG_DVB_STV0367DD=m CONFIG_DVB_TDA18212DD=m CONFIG_DVB_OCTONET=m CONFIG_DVB_CXD2843=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6111=m CONFIG_DVB_LNBH25=m CONFIG_DVB_MXL5XX=m CONFIG_DVB_NET=y DDDVB=y
 | 
			
		||||
 | 
			
		||||
KBUILD_EXTMOD = $(PWD)
 | 
			
		||||
 | 
			
		||||
DDDVB_INC = "-I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux -I$(KBUILD_EXTMOD)/frontends"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
all: 
 | 
			
		||||
	$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) $(MODDEFS) modules
 | 
			
		||||
	$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) $(MODDEFS) modules NOSTDINC_FLAGS=$(DDDVB_INC)
 | 
			
		||||
	$(MAKE) -C apps
 | 
			
		||||
 | 
			
		||||
libdddvb:
 | 
			
		||||
@@ -22,6 +27,7 @@ dep:
 | 
			
		||||
 | 
			
		||||
install: all
 | 
			
		||||
	$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) modules_install
 | 
			
		||||
	depmod -a
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -rf */.*.o.d */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										101
									
								
								apps/flashprog.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								apps/flashprog.c
									
									
									
									
									
								
							@@ -32,16 +32,18 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include "flash.h"
 | 
			
		||||
#include "flash.c"
 | 
			
		||||
 | 
			
		||||
void get_id(int ddb, struct ddb_id *ddbid) {
 | 
			
		||||
void get_ddid(int ddb, struct ddb_id *ddbid) {
 | 
			
		||||
	uint8_t id[4];
 | 
			
		||||
 | 
			
		||||
	if (ioctl(ddb, IOCTL_DDB_ID, ddbid)>=0)
 | 
			
		||||
		return;
 | 
			
		||||
	memset(ddbid, 0, sizeof(*ddbid));
 | 
			
		||||
	flashread(ddb, id, 0, 4);
 | 
			
		||||
	flashread(ddb, linknr, id, 0, 4);
 | 
			
		||||
	printf("%02x %02x %02x %02x\n", 
 | 
			
		||||
	       id[0], id[1], id[2], id[3]);
 | 
			
		||||
	ddbid->subvendor=(id[0] << 8) | id[1];
 | 
			
		||||
@@ -70,6 +72,7 @@ int sure()
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	char ddbname[80];
 | 
			
		||||
	char *flashname;
 | 
			
		||||
	int type = 0;
 | 
			
		||||
	struct ddb_id ddbid;
 | 
			
		||||
	uint8_t *buffer;
 | 
			
		||||
@@ -145,10 +148,10 @@ int main(int argc, char **argv)
 | 
			
		||||
		printf("Could not open device\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	Flash = flashdetect(ddb, &SectorSize, &FlashSize);
 | 
			
		||||
	Flash = flashdetect(ddb, &SectorSize, &FlashSize, &flashname);
 | 
			
		||||
 | 
			
		||||
	get_id(ddb, &ddbid);
 | 
			
		||||
#if 1
 | 
			
		||||
	get_ddid(ddb, &ddbid);
 | 
			
		||||
#if 0
 | 
			
		||||
	printf("%04x %04x %04x %04x %08x %08x\n",
 | 
			
		||||
	       ddbid.vendor, ddbid.device,
 | 
			
		||||
	       ddbid.subvendor, ddbid.subdevice,
 | 
			
		||||
@@ -156,7 +159,7 @@ int main(int argc, char **argv)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (dump) {
 | 
			
		||||
		flashdump(ddb, dump, 128);
 | 
			
		||||
		flashdump(ddb, linknr, dump, 128);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -202,89 +205,13 @@ int main(int argc, char **argv)
 | 
			
		||||
	} else {
 | 
			
		||||
		int fh, i;
 | 
			
		||||
		int fsize;
 | 
			
		||||
		char *name;
 | 
			
		||||
 | 
			
		||||
		if (!fname) 
 | 
			
		||||
		switch (ddbid.device) {
 | 
			
		||||
		case 0x0002:
 | 
			
		||||
			fname="DVBBridgeV1A_DVBBridgeV1A.bit";
 | 
			
		||||
			printf("Octopus 35\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0003:
 | 
			
		||||
			fname="DVBBridgeV1B_DVBBridgeV1B.fpga";
 | 
			
		||||
			printf("Octopus\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0005:
 | 
			
		||||
			fname="DVBBridgeV2A_DD01_0005_STD.fpga";
 | 
			
		||||
			printf("Octopus Classic\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0006:
 | 
			
		||||
			fname="DVBBridgeV2A_DD01_0006_STD.fpga";
 | 
			
		||||
			printf("CineS2 V7\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0007:
 | 
			
		||||
			fname="DVBBridgeV2A_DD01_0007_MXL.fpga";
 | 
			
		||||
			printf("Octopus 4/8\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0008:
 | 
			
		||||
			fname="DVBBridgeV2A_DD01_0008_CXD.fpga";
 | 
			
		||||
			printf("Octopus 4/8\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0009:
 | 
			
		||||
			fname="DVBBridgeV2A_DD01_0009_SX8.fpga";
 | 
			
		||||
			printf("Octopus MAXSX8\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x000a:
 | 
			
		||||
			fname="DVBBridgeV2A_DD01_000A_M4.fpga";
 | 
			
		||||
			printf("Octopus MAXM4\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x000b:
 | 
			
		||||
			fname="DVBBridgeV2A_DD01_000B_SX8.fpga";
 | 
			
		||||
			printf("Octopus MAXSX8 Basic\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0011:
 | 
			
		||||
			fname="DVBBridgeV2B_DD01_0011.fpga";
 | 
			
		||||
			printf("Octopus CI\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0012:
 | 
			
		||||
			fname="DVBBridgeV2B_DD01_0012_STD.fpga";
 | 
			
		||||
			printf("Octopus CI\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0013:
 | 
			
		||||
			fname="DVBBridgeV2B_DD01_0013_PRO.fpga";
 | 
			
		||||
			printf("Octopus PRO\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0020:
 | 
			
		||||
			fname="DVBBridgeV2C_DD01_0020.fpga";
 | 
			
		||||
			printf("Octopus GT Mini\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0201:
 | 
			
		||||
			fname="DVBModulatorV1B_DVBModulatorV1B.bit";
 | 
			
		||||
			printf("Modulator\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0203:
 | 
			
		||||
			fname="DVBModulatorV1B_DD01_0203.fpga";
 | 
			
		||||
			printf("Modulator Test\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0210:
 | 
			
		||||
			fname="DVBModulatorV2A_DD01_0210.fpga";
 | 
			
		||||
			printf("Modulator V2\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0220:
 | 
			
		||||
			fname="SDRModulatorV1A_DD01_0220.fpga";
 | 
			
		||||
			printf("SDRModulator ATV\n");
 | 
			
		||||
			break;
 | 
			
		||||
		case 0x0221:
 | 
			
		||||
			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;
 | 
			
		||||
		}
 | 
			
		||||
			fname = devid2fname(ddbid.device, &name);
 | 
			
		||||
		if (name)
 | 
			
		||||
			printf("Card: %s\n", name);
 | 
			
		||||
		
 | 
			
		||||
		fh = open(fname, O_RDONLY);
 | 
			
		||||
		if (fh < 0 ) {
 | 
			
		||||
			printf("File %s not found \n", fname);
 | 
			
		||||
 
 | 
			
		||||
@@ -6,10 +6,10 @@ install: all
 | 
			
		||||
	install -m 0755 octokey $(DESTDIR)/usr/bin
 | 
			
		||||
	install -m 0755 ddflash $(DESTDIR)/usr/bin
 | 
			
		||||
 | 
			
		||||
ddflash: ddflash.c
 | 
			
		||||
ddflash: ddflash.c flash.h flash.c
 | 
			
		||||
	$(CC) -o ddflash ddflash.c
 | 
			
		||||
 | 
			
		||||
ddtest: ddtest.c
 | 
			
		||||
ddtest: ddtest.c flash.h flash.c
 | 
			
		||||
	$(CC) -o ddtest ddtest.c
 | 
			
		||||
 | 
			
		||||
octonet: octonet.c
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
#include "flash.h"
 | 
			
		||||
#include "flash.c"
 | 
			
		||||
 | 
			
		||||
static int reboot(uint32_t off)
 | 
			
		||||
{
 | 
			
		||||
@@ -55,540 +56,6 @@ static int reboot(uint32_t off)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ddflash {
 | 
			
		||||
	int fd;
 | 
			
		||||
	struct ddb_id id;
 | 
			
		||||
	uint32_t version;
 | 
			
		||||
 | 
			
		||||
	uint32_t flash_type;
 | 
			
		||||
	uint32_t sector_size;
 | 
			
		||||
	uint32_t size;
 | 
			
		||||
 | 
			
		||||
	uint32_t bufsize;
 | 
			
		||||
	uint32_t block_erase;
 | 
			
		||||
 | 
			
		||||
	uint8_t *buffer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int flashwrite_pagemode(struct ddflash *ddf, int dev, uint32_t FlashOffset,
 | 
			
		||||
			uint8_t LockBits, uint32_t fw_off)
 | 
			
		||||
{
 | 
			
		||||
	int err = 0;
 | 
			
		||||
	uint8_t cmd[260];
 | 
			
		||||
	int i, j;
 | 
			
		||||
	uint32_t flen, blen;
 | 
			
		||||
	
 | 
			
		||||
	blen = flen = lseek(dev, 0, SEEK_END) - fw_off;
 | 
			
		||||
	if (blen % 0xff)
 | 
			
		||||
		blen = (blen + 0xff) & 0xffffff00; 
 | 
			
		||||
	printf("blen = %u, flen = %u\n", blen, flen);
 | 
			
		||||
	    
 | 
			
		||||
	do {
 | 
			
		||||
		cmd[0] = 0x50;  // EWSR
 | 
			
		||||
		err = flashio(ddf->fd, cmd, 1, NULL, 0);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			break;
 | 
			
		||||
		
 | 
			
		||||
		cmd[0] = 0x01;  // WRSR
 | 
			
		||||
		cmd[1] = 0x00;  // BPx = 0, Unlock all blocks
 | 
			
		||||
		err = flashio(ddf->fd, cmd, 2, NULL, 0);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			break;
 | 
			
		||||
		
 | 
			
		||||
		for (i = 0; i < flen; i += 4096) {
 | 
			
		||||
			if ((i & 0xFFFF) == 0)
 | 
			
		||||
				printf(" Erase    %08x\n", FlashOffset + i);
 | 
			
		||||
			
 | 
			
		||||
			cmd[0] = 0x06;  // WREN
 | 
			
		||||
			err = flashio(ddf->fd, cmd, 1, NULL, 0);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
			cmd[0] = 0x20;  // Sector erase ( 4Kb)
 | 
			
		||||
			cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
 | 
			
		||||
			cmd[2] = ( (( FlashOffset + i ) >>  8) & 0xFF );
 | 
			
		||||
			cmd[3] = 0x00;
 | 
			
		||||
			err = flashio(ddf->fd, cmd, 4, NULL, 0);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			while (1) {
 | 
			
		||||
				cmd[0] = 0x05;  // RDRS
 | 
			
		||||
				err = flashio(ddf->fd, cmd, 1, &cmd[0], 1);
 | 
			
		||||
				if (err < 0)
 | 
			
		||||
					break;
 | 
			
		||||
				if ((cmd[0] & 0x01) == 0)
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			break;
 | 
			
		||||
		
 | 
			
		||||
		for (j = blen - 256; j >= 0; j -= 256 ) {
 | 
			
		||||
			uint32_t len = 256; 
 | 
			
		||||
			ssize_t rlen;
 | 
			
		||||
			
 | 
			
		||||
			if (lseek(dev, j + fw_off, SEEK_SET) < 0) {
 | 
			
		||||
				printf("seek error\n");
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
			if (flen - j < 256) {
 | 
			
		||||
				len = flen - j;
 | 
			
		||||
				memset(ddf->buffer, 0xff, 256);
 | 
			
		||||
			}
 | 
			
		||||
			rlen = read(dev, ddf->buffer, len);
 | 
			
		||||
			if (rlen < 0 || rlen != len) {
 | 
			
		||||
				printf("file read error %d,%d at %u\n", rlen, errno, j);
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
			printf ("write %u bytes at %08x\n", len, j);
 | 
			
		||||
			
 | 
			
		||||
			
 | 
			
		||||
			if ((j & 0xFFFF) == 0)
 | 
			
		||||
				printf(" Programm %08x\n", FlashOffset + j);
 | 
			
		||||
			
 | 
			
		||||
			cmd[0] = 0x06;  // WREN
 | 
			
		||||
			err = flashio(ddf->fd, cmd, 1, NULL, 0);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
			cmd[0] = 0x02;  // PP
 | 
			
		||||
			cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF );
 | 
			
		||||
			cmd[2] = ( (( FlashOffset + j ) >>  8) & 0xFF );
 | 
			
		||||
			cmd[3] = 0x00;
 | 
			
		||||
			memcpy(&cmd[4], ddf->buffer, 256);
 | 
			
		||||
			err = flashio(ddf->fd, cmd, 260, NULL, 0);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
			while(1) {
 | 
			
		||||
				cmd[0] = 0x05;  // RDRS
 | 
			
		||||
				err = flashio(ddf->fd, cmd,1, &cmd[0], 1);
 | 
			
		||||
				if (err < 0)
 | 
			
		||||
					break;
 | 
			
		||||
				if ((cmd[0] & 0x01) == 0)
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			break;
 | 
			
		||||
		
 | 
			
		||||
		cmd[0] = 0x50;  // EWSR
 | 
			
		||||
		err = flashio(ddf->fd, cmd, 1, NULL, 0);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			break;
 | 
			
		||||
		
 | 
			
		||||
		cmd[0] = 0x01;  // WRSR
 | 
			
		||||
		cmd[1] = LockBits;  // BPx = 0, Lock all blocks
 | 
			
		||||
		err = flashio(ddf->fd, cmd, 2, NULL, 0);
 | 
			
		||||
	} while(0);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int flashwrite_SSTI(struct ddflash *ddf, int fs, uint32_t FlashOffset, uint32_t maxlen, uint32_t fw_off)
 | 
			
		||||
{
 | 
			
		||||
    int err = 0;
 | 
			
		||||
    uint8_t cmd[6];
 | 
			
		||||
    int i, j;
 | 
			
		||||
    uint32_t flen, blen;
 | 
			
		||||
 | 
			
		||||
    blen = flen = lseek(fs, 0, SEEK_END) - fw_off;
 | 
			
		||||
    if (blen % 0xfff)
 | 
			
		||||
	    blen = (blen + 0xfff) & 0xfffff000; 
 | 
			
		||||
    printf("blen = %u, flen = %u\n", blen, flen);
 | 
			
		||||
    do {
 | 
			
		||||
#if 1
 | 
			
		||||
	    cmd[0] = 0x50;  // EWSR
 | 
			
		||||
	    err = flashio(ddf->fd, cmd, 1, NULL, 0);
 | 
			
		||||
	    if (err < 0) 
 | 
			
		||||
		    break;
 | 
			
		||||
 | 
			
		||||
	    cmd[0] = 0x01;  // WRSR
 | 
			
		||||
	    cmd[1] = 0x00;  // BPx = 0, Unlock all blocks
 | 
			
		||||
	    err = flashio(ddf->fd, cmd, 2, NULL, 0);
 | 
			
		||||
	    if (err < 0 )
 | 
			
		||||
		    break;
 | 
			
		||||
	    
 | 
			
		||||
	    for (i = 0; i < flen; i += 4096) {
 | 
			
		||||
		    if ((i & 0xFFFF) == 0 )
 | 
			
		||||
			    printf("Erase %08x\n", FlashOffset + i);
 | 
			
		||||
		    cmd[0] = 0x06;  // WREN
 | 
			
		||||
		    err = flashio(ddf->fd, cmd, 1, NULL, 0);
 | 
			
		||||
		    if (err < 0 )
 | 
			
		||||
			    break;
 | 
			
		||||
		    
 | 
			
		||||
		    cmd[0] = 0x20;  // Sector erase ( 4Kb)
 | 
			
		||||
		    cmd[1] = (((FlashOffset + i ) >> 16) & 0xFF);
 | 
			
		||||
		    cmd[2] = (((FlashOffset + i ) >>  8) & 0xFF);
 | 
			
		||||
		    cmd[3] = 0x00;
 | 
			
		||||
		    err = flashio(ddf->fd,cmd,4,NULL,0);
 | 
			
		||||
		    if (err < 0 )
 | 
			
		||||
			    break;
 | 
			
		||||
		    
 | 
			
		||||
		    while(1) {
 | 
			
		||||
			    cmd[0] = 0x05;  // RDRS
 | 
			
		||||
			    err = flashio(ddf->fd,cmd,1,&cmd[0],1);
 | 
			
		||||
			    if (err < 0 ) break;
 | 
			
		||||
			    if ((cmd[0] & 0x01) == 0 ) break;
 | 
			
		||||
		    }
 | 
			
		||||
		    if (err < 0 ) break;
 | 
			
		||||
	    }
 | 
			
		||||
	    if (err < 0 ) 
 | 
			
		||||
		    break;
 | 
			
		||||
#endif
 | 
			
		||||
	    for (j = blen - 4096; j >= 0; j -= 4096 ) {
 | 
			
		||||
		    uint32_t len = 4096; 
 | 
			
		||||
		    ssize_t rlen;
 | 
			
		||||
		    
 | 
			
		||||
		    if (lseek(fs, j + fw_off, SEEK_SET) < 0) {
 | 
			
		||||
			    printf("seek error\n");
 | 
			
		||||
			    return -1;
 | 
			
		||||
		    }
 | 
			
		||||
		    if (flen - j < 4096) {
 | 
			
		||||
			    len = flen - j;
 | 
			
		||||
			    memset(ddf->buffer, 0xff, 4096);
 | 
			
		||||
		    }
 | 
			
		||||
   		    rlen = read(fs, ddf->buffer, len);
 | 
			
		||||
		    if (rlen < 0 || rlen != len) {
 | 
			
		||||
			    printf("file read error %d,%d at %u\n", rlen, errno, j);
 | 
			
		||||
			    return -1;
 | 
			
		||||
		    }
 | 
			
		||||
		    printf ("write %u bytes at %08x\n", len, j);
 | 
			
		||||
 | 
			
		||||
		    if ((j & 0xFFFF) == 0 )
 | 
			
		||||
			    printf(" Program  %08x\n",FlashOffset + j);
 | 
			
		||||
#if 1		    
 | 
			
		||||
		    for (i = 0; i < 4096; i += 2) {
 | 
			
		||||
			    if (i == 0) {
 | 
			
		||||
				    cmd[0] = 0x06;  // WREN
 | 
			
		||||
				    err = flashio(ddf->fd, cmd, 1, NULL, 0);
 | 
			
		||||
				    if (err < 0 ) 
 | 
			
		||||
					    break;
 | 
			
		||||
				    
 | 
			
		||||
				    cmd[0] = 0xAD;  // AAI
 | 
			
		||||
				    cmd[1] = ((( FlashOffset + j ) >> 16) & 0xFF );
 | 
			
		||||
				    cmd[2] = ((( FlashOffset + j ) >>  8) & 0xFF );
 | 
			
		||||
				    cmd[3] = 0x00;
 | 
			
		||||
				    cmd[4] = ddf->buffer[i];
 | 
			
		||||
				    cmd[5] = ddf->buffer[i + 1];
 | 
			
		||||
				    err = flashio(ddf->fd,cmd,6,NULL,0);
 | 
			
		||||
			    } else {
 | 
			
		||||
				    cmd[0] = 0xAD;  // AAI
 | 
			
		||||
				    cmd[1] = ddf->buffer[i];
 | 
			
		||||
				    cmd[2] = ddf->buffer[i + 1];
 | 
			
		||||
				    err = flashio(ddf->fd,cmd,3,NULL,0);
 | 
			
		||||
			    }
 | 
			
		||||
			    if (err < 0 ) 
 | 
			
		||||
				    break;
 | 
			
		||||
			    
 | 
			
		||||
			    while(1) {
 | 
			
		||||
				    cmd[0] = 0x05;  // RDRS
 | 
			
		||||
				    err = flashio(ddf->fd,cmd,1,&cmd[0],1);
 | 
			
		||||
				    if (err < 0 ) break;
 | 
			
		||||
				    if ((cmd[0] & 0x01) == 0 ) break;
 | 
			
		||||
			    }
 | 
			
		||||
			    if (err < 0 ) 
 | 
			
		||||
				    break;
 | 
			
		||||
		    }
 | 
			
		||||
		    if (err < 0)
 | 
			
		||||
			    break;
 | 
			
		||||
		    
 | 
			
		||||
		    cmd[0] = 0x04;  // WDIS
 | 
			
		||||
		    err = flashio(ddf->fd, cmd, 1, NULL, 0);
 | 
			
		||||
		    if (err < 0 ) 
 | 
			
		||||
			    break;
 | 
			
		||||
#endif
 | 
			
		||||
	    }
 | 
			
		||||
	    if (err < 0 ) break;
 | 
			
		||||
	    
 | 
			
		||||
	    cmd[0] = 0x50;  // EWSR
 | 
			
		||||
	    err = flashio(ddf->fd,cmd,1,NULL,0);
 | 
			
		||||
	    if (err < 0 ) break;
 | 
			
		||||
	    
 | 
			
		||||
	    cmd[0] = 0x01;  // WRSR
 | 
			
		||||
	    cmd[1] = 0x1C;  // BPx = 0, Lock all blocks
 | 
			
		||||
	    err = flashio(ddf->fd,cmd,2,NULL,0);
 | 
			
		||||
    } while(0);
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int flashwrite(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off)
 | 
			
		||||
{
 | 
			
		||||
	switch (ddf->flash_type) {
 | 
			
		||||
        case SSTI_SST25VF016B: 
 | 
			
		||||
        case SSTI_SST25VF032B: 
 | 
			
		||||
		return flashwrite_SSTI(ddf, fs, addr, maxlen, fw_off);
 | 
			
		||||
        case SSTI_SST25VF064C:
 | 
			
		||||
		return flashwrite_pagemode(ddf, fs, addr, 0x3c, fw_off);
 | 
			
		||||
	case SPANSION_S25FL116K: 
 | 
			
		||||
	case SPANSION_S25FL132K: 
 | 
			
		||||
	case SPANSION_S25FL164K: 
 | 
			
		||||
		return flashwrite_pagemode(ddf, fs, addr, 0x1c, fw_off);
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off)
 | 
			
		||||
{
 | 
			
		||||
	off_t off;
 | 
			
		||||
	uint32_t len;
 | 
			
		||||
	int i, j, rlen;
 | 
			
		||||
	uint8_t buf[256], buf2[256];
 | 
			
		||||
	int bl = sizeof(buf);
 | 
			
		||||
	
 | 
			
		||||
	off = lseek(fs, 0, SEEK_END);
 | 
			
		||||
	if (off < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
	len = off - fw_off;
 | 
			
		||||
	lseek(fs, fw_off, SEEK_SET);
 | 
			
		||||
	if (len > maxlen) {
 | 
			
		||||
		printf("file too big\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	printf("flash file len %u, compare to %08x in flash\n", len, addr);
 | 
			
		||||
	for (j = 0; j < len; j += bl, addr += bl) {
 | 
			
		||||
		if (len - j < bl)
 | 
			
		||||
			bl = len - j;
 | 
			
		||||
		flashread(ddf->fd, buf, addr, bl);
 | 
			
		||||
		rlen = read(fs, buf2, bl);
 | 
			
		||||
		if (rlen < 0 || rlen != bl) {
 | 
			
		||||
			printf("read error\n");
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
			
 | 
			
		||||
		if (memcmp(buf, buf2, bl)) {
 | 
			
		||||
			printf("flash differs at %08x (offset %u)\n", addr, j);
 | 
			
		||||
			dump(buf, 32);
 | 
			
		||||
			dump(buf2, 32);
 | 
			
		||||
			return addr;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	printf("flash same as file\n");
 | 
			
		||||
	return -2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int flash_detect(struct ddflash *ddf)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t cmd = 0x9F;
 | 
			
		||||
	uint8_t id[3];
 | 
			
		||||
	
 | 
			
		||||
	int r = flashio(ddf->fd, &cmd, 1, id, 3);
 | 
			
		||||
	if (r < 0)
 | 
			
		||||
		return r;
 | 
			
		||||
	
 | 
			
		||||
	if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x41) {
 | 
			
		||||
		ddf->flash_type = SSTI_SST25VF016B; 
 | 
			
		||||
		printf("Flash: SSTI  SST25VF016B 16 MBit\n");
 | 
			
		||||
		ddf->sector_size = 4096; 
 | 
			
		||||
		ddf->size = 0x200000; 
 | 
			
		||||
	} else if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x4A) {
 | 
			
		||||
		ddf->flash_type = SSTI_SST25VF032B; 
 | 
			
		||||
		printf("Flash: SSTI  SST25VF032B 32 MBit\n");
 | 
			
		||||
		ddf->sector_size = 4096; 
 | 
			
		||||
		ddf->size = 0x400000; 
 | 
			
		||||
	} else if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x4B) {
 | 
			
		||||
		ddf->flash_type = SSTI_SST25VF064C; 
 | 
			
		||||
		printf("Flash: SSTI  SST25VF064C 64 MBit\n");
 | 
			
		||||
		ddf->sector_size = 4096; 
 | 
			
		||||
		ddf->size = 0x800000; 
 | 
			
		||||
	} else if (id[0] == 0x01 && id[1] == 0x40 && id[2] == 0x15) {
 | 
			
		||||
		ddf->flash_type = SPANSION_S25FL116K;
 | 
			
		||||
		printf("Flash: SPANSION S25FL116K 16 MBit\n");
 | 
			
		||||
		ddf->sector_size = 4096; 
 | 
			
		||||
		ddf->size = 0x200000; 
 | 
			
		||||
	} else if (id[0] == 0x01 && id[1] == 0x40 && id[2] == 0x16) {
 | 
			
		||||
		ddf->flash_type = SPANSION_S25FL132K;
 | 
			
		||||
		printf("Flash: SPANSION S25FL132K 32 MBit\n");
 | 
			
		||||
		ddf->sector_size = 4096; 
 | 
			
		||||
		ddf->size = 0x400000; 
 | 
			
		||||
	} else if (id[0] == 0x01 && id[1] == 0x40 && id[2] == 0x17) {
 | 
			
		||||
		ddf->flash_type = SPANSION_S25FL164K;
 | 
			
		||||
		printf("Flash: SPANSION S25FL164K 64 MBit\n");
 | 
			
		||||
		ddf->sector_size = 4096; 
 | 
			
		||||
		ddf->size = 0x800000; 
 | 
			
		||||
	} else if (id[0] == 0x1F && id[1] == 0x28) {
 | 
			
		||||
		ddf->flash_type = ATMEL_AT45DB642D; 
 | 
			
		||||
		printf("Flash: Atmel AT45DB642D  64 MBit\n");
 | 
			
		||||
		ddf->sector_size = 1024; 
 | 
			
		||||
		ddf->size = 0x800000; 
 | 
			
		||||
	} else {
 | 
			
		||||
		printf("Unknown Flash Flash ID = %02x %02x %02x\n", id[0], id[1], id[2]);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	if (ddf->sector_size) {
 | 
			
		||||
		ddf->buffer = malloc(ddf->sector_size);
 | 
			
		||||
		//printf("allocated buffer %08x@%08x\n", ddf->sector_size, (uint32_t) ddf->buffer);
 | 
			
		||||
		if (!ddf->buffer)
 | 
			
		||||
			return -1;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int get_id(struct ddflash *ddf) {
 | 
			
		||||
	uint8_t id[4];
 | 
			
		||||
 | 
			
		||||
	if (ioctl(ddf->fd, IOCTL_DDB_ID, &ddf->id) < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
#if 1
 | 
			
		||||
	printf("%04x %04x %04x %04x %08x %08x\n",
 | 
			
		||||
	       ddf->id.vendor, ddf->id.device,
 | 
			
		||||
	       ddf->id.subvendor, ddf->id.subdevice,
 | 
			
		||||
	       ddf->id.hw, ddf->id.regmap);
 | 
			
		||||
#endif	
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
 | 
			
		||||
{
 | 
			
		||||
	int fd, fsize, ret = 0;
 | 
			
		||||
	off_t off;
 | 
			
		||||
	uint32_t p, i;
 | 
			
		||||
	uint8_t *buf;
 | 
			
		||||
	uint8_t hdr[256];
 | 
			
		||||
	unsigned int devid, version, length;
 | 
			
		||||
	unsigned int cid[8];
 | 
			
		||||
	int cids = 0;
 | 
			
		||||
	uint32_t maxlen = 1024 * 1024;
 | 
			
		||||
	
 | 
			
		||||
	fd = open(fn, O_RDONLY);
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		printf("%s: not found\n", fn);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	off = lseek(fd, 0, SEEK_END);
 | 
			
		||||
	if (off < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
	fsize = off;
 | 
			
		||||
	if (fsize > maxlen) {
 | 
			
		||||
		close(fd);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	lseek(fd, 0, SEEK_SET);	
 | 
			
		||||
	buf = malloc(fsize);
 | 
			
		||||
	if (!buf)
 | 
			
		||||
		return -1;
 | 
			
		||||
	read(fd, buf, fsize);
 | 
			
		||||
	close(fd);
 | 
			
		||||
	
 | 
			
		||||
	for (p = 0; p < fsize && buf[p]; p++) {
 | 
			
		||||
		char *key = &buf[p], *val = NULL;
 | 
			
		||||
 | 
			
		||||
		for (; p < fsize && buf[p] != 0x0a; p++) {
 | 
			
		||||
			if (buf[p] == ':') {
 | 
			
		||||
				buf[p] = 0;
 | 
			
		||||
				val = &buf[p + 1];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (val == NULL || p == fsize)
 | 
			
		||||
			break;
 | 
			
		||||
		buf[p] = 0;
 | 
			
		||||
		//printf("%-20s:%s\n", key, val);
 | 
			
		||||
		if (!strcasecmp(key, "Devid")) {
 | 
			
		||||
			sscanf(val, "%x", &devid);
 | 
			
		||||
		} else if (!strcasecmp(key, "Compat")) {
 | 
			
		||||
			cids = sscanf(val, "%x,%x,%x,%x,%x,%x,%x,%x",
 | 
			
		||||
				      &cid[0], &cid[1], &cid[2], &cid[3],
 | 
			
		||||
				      &cid[4], &cid[5], &cid[6], &cid[7]);
 | 
			
		||||
			if (cids < 1)
 | 
			
		||||
				break;
 | 
			
		||||
			for (i = 0; i < cids; i++) 
 | 
			
		||||
				if (cid[i] == ddf->id.device)
 | 
			
		||||
					break;
 | 
			
		||||
			if (i == cids) {
 | 
			
		||||
				printf("%s: no compatible id\n", fn);
 | 
			
		||||
				ret = -2; /* no compatible ID */
 | 
			
		||||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (!strcasecmp(key, "Version")) {
 | 
			
		||||
			if (strchr(val,'.')) {
 | 
			
		||||
				int major = 0, minor = 0;
 | 
			
		||||
				sscanf(val,"%d.%d",&major,&minor);
 | 
			
		||||
				version = (major << 16) + minor;
 | 
			
		||||
			} else
 | 
			
		||||
				sscanf(val, "%x", &version);
 | 
			
		||||
		} else if (!strcasecmp(key, "Length")) {
 | 
			
		||||
			sscanf(val, "%u", &length);
 | 
			
		||||
		} 
 | 
			
		||||
	}
 | 
			
		||||
	p++;
 | 
			
		||||
	*fw_off = p;
 | 
			
		||||
	printf("devid = %04x\n", devid);
 | 
			
		||||
	printf("version = %08x  %08x\n", version, ddf->id.hw);
 | 
			
		||||
	printf("length = %u\n", length);
 | 
			
		||||
	printf("fsize = %u, p = %u, f-p = %u\n", fsize, p, fsize - p);
 | 
			
		||||
	if (devid == ddf->id.device) {
 | 
			
		||||
		if (version <= (ddf->id.hw & 0xffffff)) {
 | 
			
		||||
			printf("%s: old version\n", fn);
 | 
			
		||||
			ret = -3; /* same id but no newer version */
 | 
			
		||||
		}
 | 
			
		||||
	} else
 | 
			
		||||
		ret = 1;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	free(buf);
 | 
			
		||||
	printf("check_fw = %d\n", ret);
 | 
			
		||||
	return ret;
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int update_image(struct ddflash *ddf, char *fn, 
 | 
			
		||||
			uint32_t adr, uint32_t len,
 | 
			
		||||
			int has_header, int no_change)
 | 
			
		||||
{
 | 
			
		||||
	int fs, res = 0;
 | 
			
		||||
	uint32_t fw_off = 0;
 | 
			
		||||
 | 
			
		||||
	printf("Check %s\n", fn);
 | 
			
		||||
	if (has_header) {
 | 
			
		||||
		int ck;
 | 
			
		||||
		
 | 
			
		||||
		ck = check_fw(ddf, fn, &fw_off);
 | 
			
		||||
		if (ck < 0)
 | 
			
		||||
			return ck;
 | 
			
		||||
		if (ck == 1 && no_change)
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
	fs = open(fn, O_RDONLY);
 | 
			
		||||
	if (fs < 0 ) {
 | 
			
		||||
		printf("File %s not found \n", fn);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	res = flashcmp(ddf, fs, adr, len, fw_off);
 | 
			
		||||
	if (res == -2) {
 | 
			
		||||
		printf("%s: same as flash\n", fn);
 | 
			
		||||
	}
 | 
			
		||||
	if (res < 0) 
 | 
			
		||||
		goto out;
 | 
			
		||||
	res = flashwrite(ddf, fs, adr, len, fw_off);
 | 
			
		||||
	if (res == 0) {
 | 
			
		||||
		res = flashcmp(ddf, fs, adr, len, fw_off);
 | 
			
		||||
		if (res == -2) {
 | 
			
		||||
			res = 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
out:
 | 
			
		||||
	close(fs);
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int fexists(char *fn)
 | 
			
		||||
{
 | 
			
		||||
	struct stat b;
 | 
			
		||||
 | 
			
		||||
	return (!stat(fn, &b));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int update_flash(struct ddflash *ddf)
 | 
			
		||||
{
 | 
			
		||||
@@ -730,6 +197,7 @@ int main(int argc, char **argv)
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	ddf.link = 0;
 | 
			
		||||
	flash = flash_detect(&ddf);
 | 
			
		||||
	if (flash < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,8 +10,10 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include "flash.h"
 | 
			
		||||
#include "flash.c"
 | 
			
		||||
 | 
			
		||||
typedef int (*COMMAND_FUNCTION)(int dev, int argc, char* argv[], uint32_t Flags);
 | 
			
		||||
 | 
			
		||||
@@ -51,7 +53,7 @@ int ReadFlash(int ddb, int argc, char *argv[], uint32_t Flags)
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Buffer = malloc(Len);
 | 
			
		||||
	if (flashread(ddb, Buffer, Start, Len) < 0) {
 | 
			
		||||
	if (flashread(ddb, linknr, Buffer, Start, Len) < 0) {
 | 
			
		||||
		printf("flashread error\n");
 | 
			
		||||
		free(Buffer);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -81,7 +83,7 @@ int ReadSave(int ddb, int argc, char *argv[], uint32_t Flags)
 | 
			
		||||
	Len   = strtoul(argv[1],NULL,16);
 | 
			
		||||
		
 | 
			
		||||
	Buffer = malloc(Len);
 | 
			
		||||
	if (flashread(ddb, Buffer, Start, Len) < 0) {
 | 
			
		||||
	if (flashread(ddb, linknr, Buffer, Start, Len) < 0) {
 | 
			
		||||
		printf("flashread error\n");
 | 
			
		||||
		free(Buffer);
 | 
			
		||||
		return 0;
 | 
			
		||||
@@ -108,12 +110,12 @@ int FlashChipEraseAtmel(int dev)
 | 
			
		||||
		Cmd[1] = ( (( i ) >> 16) & 0xFF );
 | 
			
		||||
		Cmd[2] = ( (( i ) >>  8) & 0xFF );
 | 
			
		||||
		Cmd[3] = 0x00;
 | 
			
		||||
		err = flashio(dev,Cmd,4,NULL,0);
 | 
			
		||||
		err = flashio(dev,linknr, Cmd,4,NULL,0);
 | 
			
		||||
		if( err < 0 ) 
 | 
			
		||||
			break;
 | 
			
		||||
		while (1) {
 | 
			
		||||
			Cmd[0] = 0xD7;  // Read Status register
 | 
			
		||||
			err = flashio(dev,Cmd,1,&Cmd[0],1);
 | 
			
		||||
			err = flashio(dev,linknr, Cmd,1,&Cmd[0],1);
 | 
			
		||||
			if( err < 0 ) break;
 | 
			
		||||
			if( (Cmd[0] & 0x80) == 0x80 ) break;
 | 
			
		||||
		}
 | 
			
		||||
@@ -131,25 +133,25 @@ int FlashChipEraseSSTI(int dev)
 | 
			
		||||
	
 | 
			
		||||
	do {
 | 
			
		||||
		Cmd[0] = 0x50;  // EWSR
 | 
			
		||||
		err = flashio(dev,Cmd,1,NULL,0);
 | 
			
		||||
		err = flashio(dev, linknr, Cmd,1,NULL,0);
 | 
			
		||||
		if( err < 0 ) break;
 | 
			
		||||
		
 | 
			
		||||
		Cmd[0] = 0x01;  // WRSR
 | 
			
		||||
		Cmd[1] = 0x00;  // BPx = 0, Unlock all blocks
 | 
			
		||||
		err = flashio(dev,Cmd,2,NULL,0);
 | 
			
		||||
		err = flashio(dev, linknr, Cmd,2,NULL,0);
 | 
			
		||||
		if( err < 0 ) break;
 | 
			
		||||
		
 | 
			
		||||
		Cmd[0] = 0x06;  // WREN
 | 
			
		||||
		err = flashio(dev,Cmd,1,NULL,0);
 | 
			
		||||
		err = flashio(dev, linknr, Cmd,1,NULL,0);
 | 
			
		||||
		if( err < 0 ) break;
 | 
			
		||||
		
 | 
			
		||||
		Cmd[0] = 0x60;  // CHIP Erase
 | 
			
		||||
		err = flashio(dev,Cmd,1,NULL,0);
 | 
			
		||||
		err = flashio(dev, linknr, Cmd,1,NULL,0);
 | 
			
		||||
		if( err < 0 ) break;
 | 
			
		||||
		
 | 
			
		||||
		while(1) {
 | 
			
		||||
			Cmd[0] = 0x05;  // RDRS
 | 
			
		||||
			err = flashio(dev,Cmd,1,&Cmd[0],1);
 | 
			
		||||
			err = flashio(dev, linknr, Cmd,1,&Cmd[0],1);
 | 
			
		||||
			if( err < 0 ) break;
 | 
			
		||||
			if( (Cmd[0] & 0x01) == 0 ) break;
 | 
			
		||||
		}
 | 
			
		||||
@@ -157,12 +159,12 @@ int FlashChipEraseSSTI(int dev)
 | 
			
		||||
			break;
 | 
			
		||||
		
 | 
			
		||||
		Cmd[0] = 0x50;  // EWSR
 | 
			
		||||
		err = flashio(dev,Cmd,1,NULL,0);
 | 
			
		||||
		err = flashio(dev, linknr, Cmd,1,NULL,0);
 | 
			
		||||
		if( err < 0 ) break;
 | 
			
		||||
		
 | 
			
		||||
		Cmd[0] = 0x01;  // WRSR
 | 
			
		||||
		Cmd[1] = 0x1C;  // BPx = 0, Lock all blocks
 | 
			
		||||
		err = flashio(dev,Cmd,2,NULL,0);
 | 
			
		||||
		err = flashio(dev, linknr, Cmd,2,NULL,0);
 | 
			
		||||
	}
 | 
			
		||||
	while(0);
 | 
			
		||||
	
 | 
			
		||||
@@ -332,7 +334,7 @@ int flashioc(int dev,int argc, char* argv[],uint32_t Flags)
 | 
			
		||||
        Buffer[i] = (uint8_t) tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( flashio(dev,Buffer,WriteLen,Buffer,ReadLen) < 0 )
 | 
			
		||||
    if( flashio(dev, linknr, Buffer,WriteLen,Buffer,ReadLen) < 0 )
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
@@ -384,8 +386,8 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags)
 | 
			
		||||
	int BufferSize = 0;
 | 
			
		||||
	int BlockErase = 0;
 | 
			
		||||
	uint32_t FlashOffset = 0x10000;
 | 
			
		||||
	int SectorSize = 0;
 | 
			
		||||
	int FlashSize = 0;
 | 
			
		||||
	uint32_t SectorSize = 0;
 | 
			
		||||
	uint32_t FlashSize = 0;
 | 
			
		||||
	int ValidateFPGAType = 1;
 | 
			
		||||
	int Flash;
 | 
			
		||||
	uint32_t Id1, Id2;
 | 
			
		||||
@@ -533,7 +535,7 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags)
 | 
			
		||||
					printf("out of memory\n");
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
				if (flashread(dev, CmpBuffer, FlashOffset, 0x10000)<0) {
 | 
			
		||||
				if (flashread(dev, linknr, CmpBuffer, FlashOffset, 0x10000)<0) {
 | 
			
		||||
					printf("Ioctl returns error\n");
 | 
			
		||||
					free(Buffer);
 | 
			
		||||
					free(CmpBuffer);
 | 
			
		||||
@@ -660,7 +662,7 @@ int FlashVerify(int dev,int argc, char* argv[],uint32_t Flags)
 | 
			
		||||
        // Place our own header
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    if (flashread(dev, Buffer2, FlashOffset, BufferSize)<0) {
 | 
			
		||||
    if (flashread(dev, linknr, Buffer2, FlashOffset, BufferSize)<0) {
 | 
			
		||||
	    printf("Ioctl returns error\n");
 | 
			
		||||
	    free(Buffer);
 | 
			
		||||
	    free(Buffer2);
 | 
			
		||||
@@ -1112,7 +1114,7 @@ char *GetSerNbr(int dev)
 | 
			
		||||
	int i;
 | 
			
		||||
	
 | 
			
		||||
	memset(Buffer,0,sizeof(Buffer));
 | 
			
		||||
	if (flashread(dev, Buffer, Start, sizeof(Buffer) - 1))
 | 
			
		||||
	if (flashread(dev, linknr, Buffer, Start, sizeof(Buffer) - 1))
 | 
			
		||||
	{
 | 
			
		||||
		printf("Ioctl returns error\n");
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -1289,7 +1291,7 @@ static int read_sfpd(int dev, uint8_t adr, uint8_t *val)
 | 
			
		||||
	uint8_t cmd[5] = { 0x5a, 0, 0, adr, 0 };     
 | 
			
		||||
	int r;
 | 
			
		||||
	
 | 
			
		||||
	r = flashio(dev, cmd, 5, val, 1);
 | 
			
		||||
	r = flashio(dev, linknr,  cmd, 5, val, 1);
 | 
			
		||||
	if (r < 0)
 | 
			
		||||
		return r;
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -1301,7 +1303,7 @@ static int read_sst_id(int dev, uint8_t *id)
 | 
			
		||||
	uint8_t buf[9];
 | 
			
		||||
	int r;
 | 
			
		||||
	
 | 
			
		||||
	r = flashio(dev, cmd, 2, buf, 9);
 | 
			
		||||
	r = flashio(dev, linknr,  cmd, 2, buf, 9);
 | 
			
		||||
	if (r < 0)
 | 
			
		||||
		return r;
 | 
			
		||||
	memcpy(id, buf + 1, 8);
 | 
			
		||||
@@ -1313,7 +1315,7 @@ static int read_winbd(int dev, uint8_t *val)
 | 
			
		||||
	uint8_t cmd[5] = { 0x4b, 0, 0, 0, 0 };     
 | 
			
		||||
	int r;
 | 
			
		||||
	
 | 
			
		||||
	r = flashio(dev, cmd, 5, val, 8);
 | 
			
		||||
	r = flashio(dev, linknr,  cmd, 5, val, 8);
 | 
			
		||||
	if (r < 0)
 | 
			
		||||
		return r;
 | 
			
		||||
	return 0;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										269
									
								
								apps/octonet/ddupdate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								apps/octonet/ddupdate.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,269 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "flash.h"
 | 
			
		||||
#include "flash.c"
 | 
			
		||||
 | 
			
		||||
static int verbose = 0;
 | 
			
		||||
 | 
			
		||||
static int yesno()
 | 
			
		||||
{
 | 
			
		||||
	char c;
 | 
			
		||||
 | 
			
		||||
	printf("\n\nNew firmware available\nReally flash now? y/n\n");
 | 
			
		||||
	fflush(0);
 | 
			
		||||
	c = getchar();
 | 
			
		||||
	if (c!='y') {
 | 
			
		||||
		printf("\nFlashing aborted.\n\n");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	printf("\nStarting to flash\n\n");
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int update_flash(struct ddflash *ddf)
 | 
			
		||||
{
 | 
			
		||||
	char *fname, *default_fname;
 | 
			
		||||
	int res, stat = 0;
 | 
			
		||||
	char *name = 0, *dname;
 | 
			
		||||
	
 | 
			
		||||
	switch (ddf->id.device) {
 | 
			
		||||
	case 0x300:
 | 
			
		||||
	case 0x301:
 | 
			
		||||
	case 0x302:
 | 
			
		||||
	case 0x307:
 | 
			
		||||
		if ((res = update_image(ddf, "/boot/bs.img", 0x4000, 0x1000, 0, 0)) == 1)
 | 
			
		||||
			stat |= 4;
 | 
			
		||||
		if ((res = update_image(ddf, "/boot/uboot.img", 0xb0000, 0xb0000, 0, 0)) == 1)
 | 
			
		||||
			stat |= 2;
 | 
			
		||||
		if (fexists("/config/gtl.enabled")) {
 | 
			
		||||
			if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x10000, 0xa0000, 1, 0)) == 1)
 | 
			
		||||
				stat |= 1;
 | 
			
		||||
			if (res == -1)
 | 
			
		||||
				if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x10000, 0xa0000, 1, 0)) == 1)
 | 
			
		||||
					stat |= 1;
 | 
			
		||||
		} else if (fexists("/config/gtl.disabled")) {
 | 
			
		||||
			if ((res = update_image(ddf, "/config/fpga.img", 0x10000, 0xa0000, 1, 0)) == 1)
 | 
			
		||||
				stat |= 1;
 | 
			
		||||
			if (res == -1)
 | 
			
		||||
				if ((res = update_image(ddf, "/boot/fpga.img", 0x10000, 0xa0000, 1, 0)) == 1)
 | 
			
		||||
					stat |= 1;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (ddf->id.device == 0x0307) {
 | 
			
		||||
				if (res == -1)
 | 
			
		||||
					if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x10000, 0xa0000, 1, 1)) == 1)
 | 
			
		||||
						stat |= 1;
 | 
			
		||||
				if (res == -1)
 | 
			
		||||
					if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x10000, 0xa0000, 1, 1)) == 1)
 | 
			
		||||
						stat |= 1;
 | 
			
		||||
			} else {
 | 
			
		||||
				if ((res = update_image(ddf, "/config/fpga.img", 0x10000, 0xa0000, 1, 1)) == 1)
 | 
			
		||||
					stat |= 1;
 | 
			
		||||
				if (res == -1)
 | 
			
		||||
					if ((res = update_image(ddf, "/boot/fpga.img", 0x10000, 0xa0000, 1, 1)) == 1)
 | 
			
		||||
						stat |= 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#if 1
 | 
			
		||||
		if ( (stat&1) && (ddf->id.hw & 0xffffff) <= 0x010001) {		
 | 
			
		||||
			if (ddf->id.device == 0x0307) {
 | 
			
		||||
				if ((res = update_image(ddf, "/config/fpga_gtl.img", 0x160000, 0x80000, 1, 0)) == 1)
 | 
			
		||||
					stat |= 1;
 | 
			
		||||
				if (res == -1)
 | 
			
		||||
					if ((res = update_image(ddf, "/boot/fpga_gtl.img", 0x160000, 0x80000, 1, 0)) == 1)
 | 
			
		||||
						stat |= 1;
 | 
			
		||||
			} else {
 | 
			
		||||
				if ((res = update_image(ddf, "/config/fpga.img", 0x160000, 0x80000, 1, 0)) == 1)
 | 
			
		||||
					stat |= 1;
 | 
			
		||||
				if (res == -1)
 | 
			
		||||
					if ((res = update_image(ddf, "/boot/fpga.img", 0x160000, 0x80000, 1, 0)) == 1)
 | 
			
		||||
						stat |= 1;
 | 
			
		||||
			
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x320:
 | 
			
		||||
		//fname="/boot/DVBNetV1A_DD01_0300.bit";
 | 
			
		||||
		fname="/boot/fpga.img";
 | 
			
		||||
		if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1)
 | 
			
		||||
			stat |= 1;
 | 
			
		||||
		return stat;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x322:
 | 
			
		||||
		//fname="/boot/DVBNetV1A_DD01_0300.bit";
 | 
			
		||||
		fname="/boot/fpga.img";
 | 
			
		||||
		if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1)
 | 
			
		||||
			stat |= 1;
 | 
			
		||||
		return stat;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		fname = ddf->fname;
 | 
			
		||||
		default_fname = devid2fname(ddf->id.device, &name);
 | 
			
		||||
		if (!fname)
 | 
			
		||||
			fname = default_fname;
 | 
			
		||||
		if (name)
 | 
			
		||||
			printf("Card:   %s\n", name);
 | 
			
		||||
		if (ddf->flash_name)
 | 
			
		||||
			printf("Flash:  %s\n", ddf->flash_name);
 | 
			
		||||
		printf("Version:%08x\n", ddf->id.hw);
 | 
			
		||||
		//printf("REGMAPa: %08x\n", ddf->id.regmap);
 | 
			
		||||
		if ((res = update_image(ddf, fname, 0x10000, 0x100000, 1, 0)) == 1)
 | 
			
		||||
			stat |= 1;
 | 
			
		||||
		return stat;
 | 
			
		||||
	}
 | 
			
		||||
	return stat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int update_link(struct ddflash *ddf)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	
 | 
			
		||||
	ret = flash_detect(ddf);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
	ret = update_flash(ddf);
 | 
			
		||||
 | 
			
		||||
	if (ddf->buffer)
 | 
			
		||||
		free(ddf->buffer);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int update_card(int ddbnum, char *fname)
 | 
			
		||||
{
 | 
			
		||||
	struct ddflash ddf;
 | 
			
		||||
	char ddbname[80];
 | 
			
		||||
	struct ddb_id ddbid;
 | 
			
		||||
	int ddb, ret, link, links;
 | 
			
		||||
	
 | 
			
		||||
	sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
 | 
			
		||||
	ddb = open(ddbname, O_RDWR);
 | 
			
		||||
	if (ddb < 0)
 | 
			
		||||
		return -3;
 | 
			
		||||
	ddf.fd = ddb;
 | 
			
		||||
	ddf.link = 0;
 | 
			
		||||
	ddf.fname = fname;
 | 
			
		||||
	links = 1;
 | 
			
		||||
 | 
			
		||||
	for (link = 0; link < links; link++) {
 | 
			
		||||
		ddf.link = link;
 | 
			
		||||
		if (verbose >= 2)
 | 
			
		||||
			printf("Get id card %u link %u\n", ddbnum, link);
 | 
			
		||||
		ret = get_id(&ddf);
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			goto out;
 | 
			
		||||
		if (!link) {
 | 
			
		||||
			switch (ddf.id.device) {
 | 
			
		||||
			case 0x20:
 | 
			
		||||
				links = 4;
 | 
			
		||||
				break;
 | 
			
		||||
			case 0x300:
 | 
			
		||||
			case 0x301:
 | 
			
		||||
			case 0x307:
 | 
			
		||||
				links = 2;
 | 
			
		||||
				break;
 | 
			
		||||
			
 | 
			
		||||
			default:
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		//printf("%08x %08x\n", ddf.id.device, ddf.id.subdevice);
 | 
			
		||||
		if (ddf.id.device) {
 | 
			
		||||
			printf("\n\nUpdate card %s link %u:\n", ddbname, link);
 | 
			
		||||
			ret = update_link(&ddf);
 | 
			
		||||
			//if (ret < 0)
 | 
			
		||||
			//	break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
out:
 | 
			
		||||
	close(ddb);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int usage()
 | 
			
		||||
{
 | 
			
		||||
	printf("ddupdate [OPTION]\n\n"
 | 
			
		||||
	       "-n N\n  only update card N (default with N=0)\n\n"
 | 
			
		||||
	       "-a \n   update all cards\n\n"
 | 
			
		||||
	       "-b file\n  fpga image file override (ignored if -a is used)\n\n"
 | 
			
		||||
	       "-v \n   more verbose (up to -v -v -v)\n\n"
 | 
			
		||||
		);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	int ddbnum = -1, all = 0, i, force = 0;
 | 
			
		||||
	char *fname = 0;
 | 
			
		||||
	
 | 
			
		||||
        while (1) {
 | 
			
		||||
                int option_index = 0;
 | 
			
		||||
		int c;
 | 
			
		||||
                static struct option long_options[] = {
 | 
			
		||||
			{"help", no_argument , NULL, 'h'},
 | 
			
		||||
			{0, 0, 0, 0}
 | 
			
		||||
		};
 | 
			
		||||
                c = getopt_long(argc, argv, 
 | 
			
		||||
				"n:havfb:",
 | 
			
		||||
				long_options, &option_index);
 | 
			
		||||
		if (c==-1)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		switch (c) {
 | 
			
		||||
		case 'b':
 | 
			
		||||
			fname = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'n':
 | 
			
		||||
			ddbnum = strtol(optarg, NULL, 0);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'a':
 | 
			
		||||
			all = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'v':
 | 
			
		||||
			verbose++;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'h':
 | 
			
		||||
			usage();
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (optind < argc) {
 | 
			
		||||
		printf("Warning: unused arguments\n");
 | 
			
		||||
	}
 | 
			
		||||
	if (!all && (ddbnum < 0)) {
 | 
			
		||||
		printf("Select card number or all cards\n\n");
 | 
			
		||||
		usage();
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	if (!all)
 | 
			
		||||
		return update_card(ddbnum, fname);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 100; i++) {
 | 
			
		||||
		int ret = update_card(i, 0);
 | 
			
		||||
		
 | 
			
		||||
		if (ret == -3)     /* could not open, no more cards! */
 | 
			
		||||
			break; 
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			return i; /* fatal error */ 
 | 
			
		||||
		if (verbose >= 1)
 | 
			
		||||
			printf("card %d up to date\n", i);
 | 
			
		||||
	}
 | 
			
		||||
	return 0; 
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -62,4 +62,45 @@ struct ddb_i2c_msg {
 | 
			
		||||
#define IOCTL_DDB_READ_I2C   _IOWR(DDB_MAGIC, 0x0a, struct ddb_i2c_msg)
 | 
			
		||||
#define IOCTL_DDB_WRITE_I2C  _IOR(DDB_MAGIC, 0x0b, struct ddb_i2c_msg)
 | 
			
		||||
 | 
			
		||||
#include "flash.c"
 | 
			
		||||
enum {
 | 
			
		||||
	UNKNOWN_FLASH = 0,
 | 
			
		||||
	ATMEL_AT45DB642D = 1,
 | 
			
		||||
	SSTI_SST25VF016B = 2,
 | 
			
		||||
	SSTI_SST25VF032B = 3,
 | 
			
		||||
	SSTI_SST25VF064C = 4,
 | 
			
		||||
	SPANSION_S25FL116K = 5,
 | 
			
		||||
	SPANSION_S25FL132K = 6,
 | 
			
		||||
	SPANSION_S25FL164K = 7,
 | 
			
		||||
	WINBOND_W25Q16JV = 8,
 | 
			
		||||
	WINBOND_W25Q32JV = 9,
 | 
			
		||||
	WINBOND_W25Q64JV = 10,
 | 
			
		||||
	WINBOND_W25Q128JV = 11,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct flash_info {
 | 
			
		||||
	uint8_t id[3];
 | 
			
		||||
	uint32_t type;
 | 
			
		||||
	uint32_t ssize;
 | 
			
		||||
	uint32_t fsize;
 | 
			
		||||
	char *name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ddflash {
 | 
			
		||||
	int fd;
 | 
			
		||||
	uint32_t link;
 | 
			
		||||
	char *fname;
 | 
			
		||||
	
 | 
			
		||||
	struct ddb_id id;
 | 
			
		||||
	uint32_t version;
 | 
			
		||||
 | 
			
		||||
	char    *flash_name;
 | 
			
		||||
	uint32_t flash_type;
 | 
			
		||||
	uint32_t sector_size;
 | 
			
		||||
	uint32_t size;
 | 
			
		||||
 | 
			
		||||
	uint32_t bufsize;
 | 
			
		||||
	uint32_t block_erase;
 | 
			
		||||
 | 
			
		||||
	uint8_t *buffer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										103
									
								
								apps/tscheck.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								apps/tscheck.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <linux/dvb/dmx.h>
 | 
			
		||||
#include <linux/dvb/frontend.h>
 | 
			
		||||
#include <linux/dvb/video.h>
 | 
			
		||||
 | 
			
		||||
char line_start[16] = "";
 | 
			
		||||
char line_end[16]   = "\r";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t cc_errors = 0;
 | 
			
		||||
uint32_t packets = 0;
 | 
			
		||||
uint32_t payload_packets = 0;
 | 
			
		||||
uint32_t packet_errors = 0;
 | 
			
		||||
 | 
			
		||||
uint8_t cc[8192] = { 0 };
 | 
			
		||||
 | 
			
		||||
void proc_ts(int i, uint8_t *buf)
 | 
			
		||||
{
 | 
			
		||||
	uint16_t pid= 0x1fff& ((buf[1] << 8) | buf[2]);
 | 
			
		||||
	uint8_t ccin = buf[3] & 0x1f;
 | 
			
		||||
	
 | 
			
		||||
	if( buf[0] == 0x47 && (buf[1] & 0x80) == 0) {
 | 
			
		||||
		if( pid != 8191 ) {
 | 
			
		||||
			if (ccin & 0x10) {
 | 
			
		||||
				if( cc[pid] != 0 ) {
 | 
			
		||||
					// TODO: 1 repetition allowed
 | 
			
		||||
					if ((((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) )  
 | 
			
		||||
						cc_errors += 1;
 | 
			
		||||
				}
 | 
			
		||||
				cc[pid] = ccin;
 | 
			
		||||
			}
 | 
			
		||||
			payload_packets += 1;
 | 
			
		||||
		}
 | 
			
		||||
	} else
 | 
			
		||||
		packet_errors += 1;
 | 
			
		||||
	
 | 
			
		||||
	if( (packets & 0x3FFF ) == 0) {
 | 
			
		||||
		printf("%s  Packets: %12u non null %12u, errors: %12u, CC errors: %12u%s",
 | 
			
		||||
		       line_start, packets, payload_packets, packet_errors, cc_errors, line_end);
 | 
			
		||||
		fflush(stdout);
 | 
			
		||||
	}
 | 
			
		||||
	packets += 1;  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define TSBUFSIZE (100*188)
 | 
			
		||||
 | 
			
		||||
void citest(char* n)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t *buf;
 | 
			
		||||
	uint8_t id;
 | 
			
		||||
	int i, nts;
 | 
			
		||||
	int len;
 | 
			
		||||
	int ts=open(n, O_RDONLY);
 | 
			
		||||
	buf=(uint8_t *)malloc(TSBUFSIZE);
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	while(1) {
 | 
			
		||||
		len=read(ts, buf, TSBUFSIZE);
 | 
			
		||||
		if (len<0) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (buf[0]!=0x47) {
 | 
			
		||||
			read(ts, buf, 1);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (len%188) { /* should not happen */
 | 
			
		||||
			printf("blah\n");
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		nts=len/188;
 | 
			
		||||
		for (i=0; i<nts; i++)
 | 
			
		||||
			proc_ts(i, buf+i*188);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
	if( argc < 2 )
 | 
			
		||||
	{
 | 
			
		||||
		printf("tscheck <file>|<device> [<display line>]\n");
 | 
			
		||||
		exit(0);
 | 
			
		||||
	}
 | 
			
		||||
	if( argc > 2 )
 | 
			
		||||
	{
 | 
			
		||||
		int line = atoi(argv[2]);
 | 
			
		||||
		if( line >= 0 && line < 64 )
 | 
			
		||||
		{
 | 
			
		||||
			snprintf(line_start,sizeof(line_start)-1,"\0337\033[%d;0H",line);
 | 
			
		||||
			strncpy(line_end,"\0338",sizeof(line_end)-1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	citest(argv[1]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3,9 +3,11 @@ EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -D
 | 
			
		||||
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
 | 
			
		||||
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
 | 
			
		||||
#mci-objs = ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o ddbridge-io.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o #mci.o
 | 
			
		||||
obj-$(CONFIG_DVB_OCTONET) += octonet.o
 | 
			
		||||
 | 
			
		||||
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends
 | 
			
		||||
EXTRA_CFLAGS += -Idrivers/media/common/tuners
 | 
			
		||||
NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/dvb-core
 | 
			
		||||
#EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends
 | 
			
		||||
#EXTRA_CFLAGS += -Idrivers/media/common/tuners
 | 
			
		||||
#NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/dvb-core
 | 
			
		||||
@@ -1,14 +1,15 @@
 | 
			
		||||
#
 | 
			
		||||
# Makefile for the ddbridge device driver
 | 
			
		||||
#
 | 
			
		||||
#NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux -I$(KBUILD_EXTMOD)/dvb-frontends -I$(KBUILD_EXTMOD)/tuners
 | 
			
		||||
 | 
			
		||||
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
 | 
			
		||||
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_DVB_OCTONET) += octonet.o
 | 
			
		||||
 | 
			
		||||
ccflags-y += -Idrivers/media/dvb-core/
 | 
			
		||||
ccflags-y += -Idrivers/media/dvb-frontends/
 | 
			
		||||
ccflags-y += -Idrivers/media/tuners/
 | 
			
		||||
 | 
			
		||||
#ccflags-y += -Idrivers/media/include/linux/
 | 
			
		||||
#ccflags-y += -Idrivers/media/dvb-frontends/
 | 
			
		||||
#ccflags-y += -Idrivers/media/tuners/
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
#include "ddbridge.h"
 | 
			
		||||
#include "ddbridge-i2c.h"
 | 
			
		||||
#include "ddbridge-io.h"
 | 
			
		||||
#include "dvb_net.h"
 | 
			
		||||
#include <media/dvb_net.h>
 | 
			
		||||
 | 
			
		||||
struct workqueue_struct *ddb_wq;
 | 
			
		||||
 | 
			
		||||
@@ -56,6 +56,10 @@ static int xo2_speed = 2;
 | 
			
		||||
module_param(xo2_speed, int, 0444);
 | 
			
		||||
MODULE_PARM_DESC(xo2_speed, "default transfer speed for xo2 based duoflex, 0=55,1=75,2=90,3=104 MBit/s, default=2, use attribute to change for individual cards");
 | 
			
		||||
 | 
			
		||||
static int raw_stream;
 | 
			
		||||
module_param(raw_stream, int, 0444);
 | 
			
		||||
MODULE_PARM_DESC(raw_stream, "send data as raw stream to DVB layer");
 | 
			
		||||
 | 
			
		||||
#ifdef __arm__
 | 
			
		||||
static int alt_dma = 1;
 | 
			
		||||
#else
 | 
			
		||||
@@ -99,6 +103,7 @@ struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr,
 | 
			
		||||
	irq->data = data;
 | 
			
		||||
	return irq;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(ddb_irq_set);
 | 
			
		||||
 | 
			
		||||
static void ddb_set_dma_table(struct ddb_io *io)
 | 
			
		||||
{
 | 
			
		||||
@@ -328,6 +333,7 @@ static int ddb_buffers_alloc(struct ddb *dev)
 | 
			
		||||
				if (dma_alloc(dev->pdev,
 | 
			
		||||
					      port->input[0]->dma, 0) < 0)
 | 
			
		||||
					return -1;
 | 
			
		||||
			/* fallthrough */
 | 
			
		||||
		case DDB_PORT_MOD:
 | 
			
		||||
			if (port->output->dma)
 | 
			
		||||
				if (dma_alloc(dev->pdev,
 | 
			
		||||
@@ -481,9 +487,8 @@ static void ddb_output_start_unlocked(struct ddb_output *output)
 | 
			
		||||
	}
 | 
			
		||||
	if (output->port->class != DDB_PORT_MOD)
 | 
			
		||||
		ddbwritel(dev, con | 1, TS_CONTROL(output));
 | 
			
		||||
	if (output->dma) {
 | 
			
		||||
	if (output->dma)
 | 
			
		||||
		output->dma->running = 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ddb_output_start(struct ddb_output *output)
 | 
			
		||||
@@ -531,6 +536,14 @@ static void ddb_input_stop_unlocked(struct ddb_input *input)
 | 
			
		||||
	if (input->dma) {
 | 
			
		||||
		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma));
 | 
			
		||||
		input->dma->running = 0;
 | 
			
		||||
		if (input->dma->stall_count)
 | 
			
		||||
			dev_warn(input->port->dev->dev,
 | 
			
		||||
				 "DMA stalled %u times!\n",
 | 
			
		||||
				 input->dma->stall_count);
 | 
			
		||||
		if (input->dma->packet_loss)
 | 
			
		||||
			dev_warn(input->port->dev->dev,
 | 
			
		||||
				 "%u packets lost due to low DMA performance!\n",
 | 
			
		||||
				 input->dma->packet_loss);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -553,6 +566,8 @@ static void ddb_input_start_unlocked(struct ddb_input *input)
 | 
			
		||||
		input->dma->cbuf = 0;
 | 
			
		||||
		input->dma->coff = 0;
 | 
			
		||||
		input->dma->stat = 0;
 | 
			
		||||
		input->dma->stall_count = 0;
 | 
			
		||||
		input->dma->packet_loss = 0;
 | 
			
		||||
		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma));
 | 
			
		||||
	}
 | 
			
		||||
	ddbwritel(dev, 0, TS_CONTROL(input));
 | 
			
		||||
@@ -568,13 +583,16 @@ static void ddb_input_start_unlocked(struct ddb_input *input)
 | 
			
		||||
	}
 | 
			
		||||
	if (dev->link[0].info->type == DDB_OCTONET)
 | 
			
		||||
		ddbwritel(dev, 0x01, TS_CONTROL(input));
 | 
			
		||||
	else {
 | 
			
		||||
		if (raw_stream)
 | 
			
		||||
			ddbwritel(dev, 0x01 | ((raw_stream & 3) << 8), TS_CONTROL(input));
 | 
			
		||||
		else
 | 
			
		||||
		ddbwritel(dev, 0x09, TS_CONTROL(input));
 | 
			
		||||
			ddbwritel(dev, 0x01 | input->con, TS_CONTROL(input));
 | 
			
		||||
	}
 | 
			
		||||
	if (input->port->type == DDB_TUNER_DUMMY)
 | 
			
		||||
		ddbwritel(dev, 0x000fff01, TS_CONTROL2(input));
 | 
			
		||||
	if (input->dma) {
 | 
			
		||||
	if (input->dma)
 | 
			
		||||
		input->dma->running = 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ddb_input_start(struct ddb_input *input)
 | 
			
		||||
@@ -651,7 +669,7 @@ static u32 ddb_output_free(struct ddb_output *output)
 | 
			
		||||
 | 
			
		||||
	if (output->dma->cbuf != idx) {
 | 
			
		||||
		if ((((output->dma->cbuf + 1) % output->dma->num) == idx) &&
 | 
			
		||||
		    (output->dma->size - output->dma->coff <= 2*188))
 | 
			
		||||
		    (output->dma->size - output->dma->coff <= 2 * 188))
 | 
			
		||||
			return 0;
 | 
			
		||||
		return 188;
 | 
			
		||||
	}
 | 
			
		||||
@@ -661,25 +679,6 @@ static u32 ddb_output_free(struct ddb_output *output)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static u32 ddb_dma_free(struct ddb_dma *dma)
 | 
			
		||||
{
 | 
			
		||||
	u32 idx, off, stat = dma->stat;
 | 
			
		||||
	s32 p1, p2, diff;
 | 
			
		||||
 | 
			
		||||
	idx = (stat >> 11) & 0x1f;
 | 
			
		||||
	off = (stat & 0x7ff) << 7;
 | 
			
		||||
 | 
			
		||||
	p1 = idx * dma->size + off;
 | 
			
		||||
	p2 = dma->cbuf * dma->size + dma->coff;
 | 
			
		||||
 | 
			
		||||
	diff = p1 - p2;
 | 
			
		||||
	if (diff <= 0)
 | 
			
		||||
		diff += dma->num * dma->size;
 | 
			
		||||
	return diff;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static ssize_t ddb_output_write(struct ddb_output *output,
 | 
			
		||||
				const __user u8 *buf, size_t count)
 | 
			
		||||
{
 | 
			
		||||
@@ -735,79 +734,6 @@ static ssize_t ddb_output_write(struct ddb_output *output,
 | 
			
		||||
	return count - left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static u32 ddb_input_free_bytes(struct ddb_input *input)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb *dev = input->port->dev;
 | 
			
		||||
	u32 idx, off, stat = input->dma->stat;
 | 
			
		||||
	u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma));
 | 
			
		||||
 | 
			
		||||
	idx = (stat >> 11) & 0x1f;
 | 
			
		||||
	off = (stat & 0x7ff) << 7;
 | 
			
		||||
 | 
			
		||||
	if (ctrl & 4)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (input->dma->cbuf != idx)
 | 
			
		||||
		return 1;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static s32 ddb_output_used_bufs(struct ddb_output *output)
 | 
			
		||||
{
 | 
			
		||||
	u32 idx, off, stat, ctrl;
 | 
			
		||||
	s32 diff;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irq(&output->dma->lock);
 | 
			
		||||
	stat = output->dma->stat;
 | 
			
		||||
	ctrl = output->dma->ctrl;
 | 
			
		||||
	spin_unlock_irq(&output->dma->lock);
 | 
			
		||||
 | 
			
		||||
	idx = (stat >> 11) & 0x1f;
 | 
			
		||||
	off = (stat & 0x7ff) << 7;
 | 
			
		||||
 | 
			
		||||
	if (ctrl & 4)
 | 
			
		||||
		return 0;
 | 
			
		||||
	diff = output->dma->cbuf - idx;
 | 
			
		||||
	if (diff == 0 && off < output->dma->coff)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (diff <= 0)
 | 
			
		||||
		diff += output->dma->num;
 | 
			
		||||
	return diff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static s32 ddb_input_free_bufs(struct ddb_input *input)
 | 
			
		||||
{
 | 
			
		||||
	u32 idx, off, stat, ctrl;
 | 
			
		||||
	s32 free;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irq(&input->dma->lock);
 | 
			
		||||
	ctrl = input->dma->ctrl;
 | 
			
		||||
	stat = input->dma->stat;
 | 
			
		||||
	spin_unlock_irq(&input->dma->lock);
 | 
			
		||||
	if (ctrl & 4)
 | 
			
		||||
		return 0;
 | 
			
		||||
	idx = (stat >> 11) & 0x1f;
 | 
			
		||||
	off = (stat & 0x7ff) << 7;
 | 
			
		||||
	free = input->dma->cbuf - idx;
 | 
			
		||||
	if (free == 0 && off < input->dma->coff)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (free <= 0)
 | 
			
		||||
		free += input->dma->num;
 | 
			
		||||
	return free - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u32 ddb_output_ok(struct ddb_output *output)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb_input *input = output->port->input[0];
 | 
			
		||||
	s32 diff;
 | 
			
		||||
 | 
			
		||||
	diff = ddb_input_free_bufs(input) - ddb_output_used_bufs(output);
 | 
			
		||||
	if (diff > 0)
 | 
			
		||||
		return 1;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static u32 ddb_input_avail(struct ddb_input *input)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb *dev = input->port->dev;
 | 
			
		||||
@@ -1107,9 +1033,9 @@ static struct dvb_frontend_ops dummy_ops = {
 | 
			
		||||
	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBS, SYS_DVBS2 },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "DUMMY DVB-C/C2 DVB-T/T2",
 | 
			
		||||
		.frequency_stepsize = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.frequency_stepsize_hz = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.symbol_rate_min = 870000,
 | 
			
		||||
		.symbol_rate_max = 11700000,
 | 
			
		||||
		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
 | 
			
		||||
@@ -1466,29 +1392,6 @@ static int tuner_attach_stv6111(struct ddb_input *input, int type)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int start_input(struct ddb_input *input)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 | 
			
		||||
 | 
			
		||||
	if (!dvb->users)
 | 
			
		||||
		ddb_input_start_all(input);
 | 
			
		||||
 | 
			
		||||
	return ++dvb->users;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int stop_input(struct ddb_input *input)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 | 
			
		||||
 | 
			
		||||
	if (--dvb->users)
 | 
			
		||||
		return dvb->users;
 | 
			
		||||
 | 
			
		||||
	ddb_input_stop_all(input);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 | 
			
		||||
@@ -1585,7 +1488,7 @@ static int dvb_register_adapters(struct ddb *dev)
 | 
			
		||||
 | 
			
		||||
	if (adapter_alloc >= 3 || dev->link[0].info->type == DDB_MOD ||
 | 
			
		||||
	    dev->link[0].info->type == DDB_OCTONET ||
 | 
			
		||||
	    dev->link[0].info->type == DDB_OCTOPRO ) {
 | 
			
		||||
	    dev->link[0].info->type == DDB_OCTOPRO) {
 | 
			
		||||
		port = &dev->port[0];
 | 
			
		||||
		adap = port->dvb[0].adap;
 | 
			
		||||
		ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
 | 
			
		||||
@@ -1792,6 +1695,7 @@ static int dvb_input_attach(struct ddb_input *input)
 | 
			
		||||
			osc24 = 0;
 | 
			
		||||
		else
 | 
			
		||||
			osc24 = 1;
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case DDB_TUNER_DVBCT2_SONY_P:
 | 
			
		||||
	case DDB_TUNER_DVBC2T2_SONY_P:
 | 
			
		||||
	case DDB_TUNER_ISDBT_SONY_P:
 | 
			
		||||
@@ -1808,6 +1712,7 @@ static int dvb_input_attach(struct ddb_input *input)
 | 
			
		||||
		break;
 | 
			
		||||
	case DDB_TUNER_DVBC2T2I_SONY:
 | 
			
		||||
		osc24 = 1;
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case DDB_TUNER_DVBCT2_SONY:
 | 
			
		||||
	case DDB_TUNER_DVBC2T2_SONY:
 | 
			
		||||
	case DDB_TUNER_ISDBT_SONY:
 | 
			
		||||
@@ -2098,16 +2003,6 @@ static void ddb_port_probe(struct ddb_port *port)
 | 
			
		||||
		port->class = DDB_PORT_MOD;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
#if 0
 | 
			
		||||
	if (link->info->type == DDB_OCTOPRO_HDIN) {
 | 
			
		||||
		if (port->nr == 0) {
 | 
			
		||||
			dev->link[l].info->type = DDB_OCTOPUS;
 | 
			
		||||
			port->name = "HDIN";
 | 
			
		||||
			port->class = DDB_PORT_LOOP;
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	if (link->info->type == DDB_OCTOPUS_MAX) {
 | 
			
		||||
		port->name = "DUAL DVB-S2 MAX";
 | 
			
		||||
		port->type_name = "MXL5XX";
 | 
			
		||||
@@ -2265,6 +2160,7 @@ static int ddb_port_attach(struct ddb_port *port)
 | 
			
		||||
		ret = ddb_ci_attach(port, ci_bitrate);
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			break;
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case DDB_PORT_LOOP:
 | 
			
		||||
		ret = dvb_register_device(port->dvb[0].adap,
 | 
			
		||||
					  &port->dvb[0].dev,
 | 
			
		||||
@@ -2387,9 +2283,15 @@ static void input_write_dvb(struct ddb_input *input,
 | 
			
		||||
		if (alt_dma)
 | 
			
		||||
			dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf],
 | 
			
		||||
						dma2->size, DMA_FROM_DEVICE);
 | 
			
		||||
		if (raw_stream || input->con)
 | 
			
		||||
			dvb_dmx_swfilter_raw(&dvb->demux,
 | 
			
		||||
					     dma2->vbuf[dma->cbuf],
 | 
			
		||||
					     dma2->size);
 | 
			
		||||
		else
 | 
			
		||||
			dvb_dmx_swfilter_packets(&dvb->demux,
 | 
			
		||||
						 dma2->vbuf[dma->cbuf],
 | 
			
		||||
						 dma2->size / 188);
 | 
			
		||||
 | 
			
		||||
		dma->cbuf = (dma->cbuf + 1) % dma2->num;
 | 
			
		||||
		if (ack)
 | 
			
		||||
			ddbwritel(dev, (dma->cbuf << 11),
 | 
			
		||||
@@ -2420,10 +2322,17 @@ static void input_tasklet(unsigned long data)
 | 
			
		||||
	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma));
 | 
			
		||||
	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma));
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	{
 | 
			
		||||
		u32 packet_loss = dma->packet_loss;
 | 
			
		||||
		u32 cur_counter = ddbreadl(dev, TS_STAT(input)) & 0xffff;
 | 
			
		||||
 | 
			
		||||
		if (cur_counter < (packet_loss & 0xffff))
 | 
			
		||||
			packet_loss += 0x10000;
 | 
			
		||||
		packet_loss = ((packet_loss & 0xffff0000) | cur_counter);
 | 
			
		||||
		dma->packet_loss = packet_loss;
 | 
			
		||||
	}
 | 
			
		||||
	if (4 & dma->ctrl)
 | 
			
		||||
		dev_err(dev->dev, "Overflow dma %d\n", dma->nr);
 | 
			
		||||
#endif
 | 
			
		||||
		dma->stall_count++;
 | 
			
		||||
	if (input->redi)
 | 
			
		||||
		input_write_dvb(input, input->redi);
 | 
			
		||||
	if (input->redo)
 | 
			
		||||
@@ -2432,7 +2341,7 @@ static void input_tasklet(unsigned long data)
 | 
			
		||||
	spin_unlock_irqrestore(&dma->lock, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
#ifdef OPTIMIZE_TASKLETS
 | 
			
		||||
static void input_handler(unsigned long data)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb_input *input = (struct ddb_input *)data;
 | 
			
		||||
@@ -2494,7 +2403,7 @@ unlock_exit:
 | 
			
		||||
	spin_unlock_irqrestore(&dma->lock, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
#ifdef OPTIMIZE_TASKLETS
 | 
			
		||||
static void output_handler(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb_output *output = (struct ddb_output *)data;
 | 
			
		||||
@@ -2584,10 +2493,6 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out, int irq_nr)
 | 
			
		||||
		dma->div = 1;
 | 
			
		||||
	}
 | 
			
		||||
	ddbwritel(io->port->dev, 0, DMA_BUFFER_ACK(dma));
 | 
			
		||||
#if 0
 | 
			
		||||
	dev_info(io->port->dev->dev, "init link %u, io %u, dma %u, dmaregs %08x bufregs %08x\n",
 | 
			
		||||
		 io->port->lnr, io->nr, nr, dma->regs, dma->bufregs);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr)
 | 
			
		||||
@@ -2612,10 +2517,6 @@ static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int anr)
 | 
			
		||||
		if (port->lnr)
 | 
			
		||||
			dma_nr += 32 + (port->lnr - 1) * 8;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
		dev_info(dev->dev, "init link %u, input %u, handler %u\n",
 | 
			
		||||
			 port->lnr, nr, dma_nr + base);
 | 
			
		||||
#endif
 | 
			
		||||
		ddb_irq_set(dev, 0, dma_nr + base, &input_handler, input);
 | 
			
		||||
		ddb_dma_init(input, dma_nr, 0, dma_nr + base);
 | 
			
		||||
	}
 | 
			
		||||
@@ -2633,10 +2534,6 @@ static void ddb_output_init(struct ddb_port *port, int nr)
 | 
			
		||||
	rm = io_regmap(output, 1);
 | 
			
		||||
	output->regs = DDB_LINK_TAG(port->lnr) |
 | 
			
		||||
		(rm->output->base + rm->output->size * nr);
 | 
			
		||||
#if 0
 | 
			
		||||
	dev_info(dev->dev, "init link %u, output %u, regs %08x\n",
 | 
			
		||||
		 port->lnr, nr, output->regs);
 | 
			
		||||
#endif
 | 
			
		||||
	if (dev->has_dma) {
 | 
			
		||||
		const struct ddb_regmap *rm0 = io_regmap(output, 0);
 | 
			
		||||
		u32 base = rm0->irq_base_odma;
 | 
			
		||||
@@ -3336,7 +3233,7 @@ static int ddb_release(struct inode *inode, struct file *file)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb *dev = file->private_data;
 | 
			
		||||
 | 
			
		||||
	dev->ddb_dev_users--;
 | 
			
		||||
	atomic_inc(&dev->ddb_dev_users);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3344,9 +3241,10 @@ static int ddb_open(struct inode *inode, struct file *file)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb *dev = ddbs[iminor(inode)];
 | 
			
		||||
 | 
			
		||||
	if (dev->ddb_dev_users)
 | 
			
		||||
	if (!atomic_dec_and_test(&dev->ddb_dev_users)) {
 | 
			
		||||
		atomic_inc(&dev->ddb_dev_users);
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
	dev->ddb_dev_users++;
 | 
			
		||||
	}
 | 
			
		||||
	file->private_data = dev;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -3646,7 +3544,7 @@ static ssize_t temp_show(struct device *device,
 | 
			
		||||
		l = attr->attr.name[5] - 0x30;
 | 
			
		||||
	link = &dev->link[l];
 | 
			
		||||
 | 
			
		||||
	if (link->info->type == DDB_MOD ) {
 | 
			
		||||
	if (link->info->type == DDB_MOD) {
 | 
			
		||||
		if (link->info->version >= 2) {
 | 
			
		||||
			temp = 0xffff & ddbreadl(dev, TEMPMON2_BOARD);
 | 
			
		||||
			temp = (temp * 1000) >> 8;
 | 
			
		||||
@@ -3718,25 +3616,6 @@ static ssize_t ctemp_show(struct device *device,
 | 
			
		||||
	return sprintf(buf, "%d\n", temp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static ssize_t qam_show(struct device *device,
 | 
			
		||||
			struct device_attribute *attr, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb *dev = dev_get_drvdata(device);
 | 
			
		||||
	struct i2c_adapter *adap;
 | 
			
		||||
	u8 tmp[4];
 | 
			
		||||
	s16 i, q;
 | 
			
		||||
 | 
			
		||||
	adap = &dev->i2c[1].adap;
 | 
			
		||||
	if (i2c_read_regs16(adap, 0x1f, 0xf480, tmp, 4) < 0)
 | 
			
		||||
		return sprintf(buf, "read_error\n");
 | 
			
		||||
	i = (s16)(((u16)tmp[1]) << 14) | (((u16)tmp[0]) << 6);
 | 
			
		||||
	q = (s16)(((u16)tmp[3]) << 14) | (((u16)tmp[2]) << 6);
 | 
			
		||||
 | 
			
		||||
	return sprintf(buf, "%d %d\n", i, q);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static ssize_t mod_show(struct device *device,
 | 
			
		||||
			struct device_attribute *attr, char *buf)
 | 
			
		||||
{
 | 
			
		||||
@@ -3917,32 +3796,6 @@ static ssize_t redirect_store(struct device *device,
 | 
			
		||||
	return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
/* A L P I  AAAAAALLPPPPPPII */
 | 
			
		||||
/* AAAAAAAA LLLLLLLL PPPPPPII */
 | 
			
		||||
static ssize_t redirect2_show(struct device *device,
 | 
			
		||||
			      struct device_attribute *attr, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t redirect2_store(struct device *device,
 | 
			
		||||
			       struct device_attribute *attr,
 | 
			
		||||
			       const char *buf, size_t count)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i, p;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	if (sscanf(buf, "%x %x\n", &i, &p) != 2)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	res = ddb_redirect(i, p);
 | 
			
		||||
	if (res < 0)
 | 
			
		||||
		return res;
 | 
			
		||||
	dev_info(device, "redirect: %02x, %02x\n", i, p);
 | 
			
		||||
	return count;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static ssize_t gap_show(struct device *device,
 | 
			
		||||
			struct device_attribute *attr, char *buf)
 | 
			
		||||
{
 | 
			
		||||
@@ -4100,9 +3953,6 @@ static struct device_attribute ddb_attrs[] = {
 | 
			
		||||
	__ATTR_MRO(devid3, devid_show),
 | 
			
		||||
	__ATTR_RO(hwid),
 | 
			
		||||
	__ATTR_RO(regmap),
 | 
			
		||||
#if 0
 | 
			
		||||
	__ATTR_RO(qam),
 | 
			
		||||
#endif
 | 
			
		||||
	__ATTR(redirect, 0664, redirect_show, redirect_store),
 | 
			
		||||
	__ATTR_MRO(snr,  bsnr_show),
 | 
			
		||||
	__ATTR_RO(bpsnr),
 | 
			
		||||
@@ -4170,9 +4020,6 @@ static struct device_attribute ddb_attrs_fanspeed[] = {
 | 
			
		||||
static struct class ddb_class = {
 | 
			
		||||
	.name		= "ddbridge",
 | 
			
		||||
	.owner          = THIS_MODULE,
 | 
			
		||||
#if 0
 | 
			
		||||
	.dev_attrs	= ddb_attrs,
 | 
			
		||||
#endif
 | 
			
		||||
	.devnode        = ddb_devnode,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -4205,7 +4052,6 @@ static void ddb_device_attrs_del(struct ddb *dev)
 | 
			
		||||
		if (dev->link[i].info &&
 | 
			
		||||
		    dev->link[i].info->temp_num)
 | 
			
		||||
			device_remove_file(dev->ddb_dev, &ddb_attrs_temp[i]);
 | 
			
		||||
	for (i = 0; i < dev->link[0].info->temp_num; i++)
 | 
			
		||||
	for (i = 0; i < dev->link[0].info->port_num; i++)
 | 
			
		||||
		device_remove_file(dev->ddb_dev, &ddb_attrs_mod[i]);
 | 
			
		||||
	for (i = 0; i < dev->link[0].info->fan_num; i++)
 | 
			
		||||
@@ -4274,6 +4120,7 @@ static int ddb_device_create(struct ddb *dev)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	mutex_lock(&ddb_mutex);
 | 
			
		||||
	dev->nr = ddb_num;
 | 
			
		||||
	atomic_set(&dev->ddb_dev_users, 1);
 | 
			
		||||
	ddbs[dev->nr] = dev;
 | 
			
		||||
	dev->ddb_dev = device_create(&ddb_class, dev->dev,
 | 
			
		||||
				     MKDEV(ddb_major, dev->nr),
 | 
			
		||||
@@ -4315,7 +4162,7 @@ static void gtl_link_handler(void *priv)
 | 
			
		||||
	struct ddb *dev = (struct ddb *)priv;
 | 
			
		||||
	u32 regs = dev->link[0].info->regmap->gtl->base;
 | 
			
		||||
 | 
			
		||||
	dev_info(dev->dev, "GT link change: %u\n",
 | 
			
		||||
	dev_info(dev->dev, "GT link changed to %u\n",
 | 
			
		||||
		 (1 & ddbreadl(dev, regs)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -4342,7 +4189,9 @@ static void link_tasklet(unsigned long data)
 | 
			
		||||
static void gtl_irq_handler(void *priv)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb_link *link = (struct ddb_link *)priv;
 | 
			
		||||
#if 1
 | 
			
		||||
#ifdef USE_LINK_TASKLET
 | 
			
		||||
	tasklet_schedule(&link->tasklet);
 | 
			
		||||
#else
 | 
			
		||||
	struct ddb *dev = link->dev;
 | 
			
		||||
	u32 s, l = link->nr, tag = DDB_LINK_TAG(link->nr);
 | 
			
		||||
 | 
			
		||||
@@ -4354,8 +4203,6 @@ static void gtl_irq_handler(void *priv)
 | 
			
		||||
		LINK_IRQ_HANDLE(l, 3);
 | 
			
		||||
		LINK_IRQ_HANDLE(l, 24);
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	tasklet_schedule(&link->tasklet);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -4399,7 +4246,7 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l)
 | 
			
		||||
				  subid & 0xffff, subid >> 16);
 | 
			
		||||
	if (link->info->type != DDB_OCTOPUS_MAX_CT &&
 | 
			
		||||
	    link->info->type != DDB_OCTOPUS_MAX  &&
 | 
			
		||||
	    link->info->type != DDB_OCTOPUS_MCI ) {
 | 
			
		||||
	    link->info->type != DDB_OCTOPUS_MCI) {
 | 
			
		||||
		dev_info(dev->dev,
 | 
			
		||||
			 "Detected GT link but found invalid ID %08x. You might have to update (flash) the add-on card first.",
 | 
			
		||||
			 id);
 | 
			
		||||
@@ -4661,6 +4508,7 @@ int ddb_exit_ddbridge(int stage, int error)
 | 
			
		||||
	default:
 | 
			
		||||
	case 2:
 | 
			
		||||
		destroy_workqueue(ddb_wq);
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case 1:
 | 
			
		||||
		ddb_class_destroy();
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -821,6 +821,8 @@ static const struct ddb_device_id ddb_device_ids[] = {
 | 
			
		||||
	DDB_DEVID(0x0323, 0xffff, ddb_none),
 | 
			
		||||
	DDB_DEVID(0x0328, 0xffff, ddb_none),
 | 
			
		||||
	DDB_DEVID(0x0329, 0xffff, ddb_octopro_hdin),
 | 
			
		||||
 | 
			
		||||
	DDB_DEVID(0xffff, 0xffff, ddb_none),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const struct ddb_info *get_ddb_info(u16 vendor, u16 device,
 | 
			
		||||
@@ -833,7 +835,8 @@ const struct ddb_info *get_ddb_info(u16 vendor, u16 device,
 | 
			
		||||
 | 
			
		||||
		if (vendor == id->vendor &&
 | 
			
		||||
		    device == id->device &&
 | 
			
		||||
		    subvendor == id->subvendor &&
 | 
			
		||||
		    (subvendor == id->subvendor ||
 | 
			
		||||
		     id->subvendor == 0xffff) &&
 | 
			
		||||
		    (subdevice == id->subdevice ||
 | 
			
		||||
		     id->subdevice == 0xffff))
 | 
			
		||||
			return id->info;
 | 
			
		||||
 
 | 
			
		||||
@@ -35,13 +35,12 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
 | 
			
		||||
	stat = wait_for_completion_timeout(&i2c->completion, HZ);
 | 
			
		||||
	val = ddbreadl(dev, i2c->regs + I2C_COMMAND);
 | 
			
		||||
	if (stat == 0) {
 | 
			
		||||
		dev_err(dev->dev, "I2C timeout, card %d, port %d, link %u\n",
 | 
			
		||||
			dev->nr, i2c->nr, i2c->link);
 | 
			
		||||
#if 1
 | 
			
		||||
		{
 | 
			
		||||
		u32 istat = ddbreadl(dev, INTERRUPT_STATUS);
 | 
			
		||||
 | 
			
		||||
		dev_err(dev->dev, "I2C timeout, card %d, port %d, link %u\n",
 | 
			
		||||
			dev->nr, i2c->nr, i2c->link);
 | 
			
		||||
		dev_err(dev->dev, "DDBridge IRS %08x\n", istat);
 | 
			
		||||
 | 
			
		||||
		if (i2c->link) {
 | 
			
		||||
			u32 listat =
 | 
			
		||||
				ddbreadl(dev,
 | 
			
		||||
@@ -60,8 +59,6 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
 | 
			
		||||
			dev_err(dev->dev, "I2C cmd=%08x mon=%08x\n",
 | 
			
		||||
				val, mon);
 | 
			
		||||
		}
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
	val &= 0x70000;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0 */
 | 
			
		||||
/*
 | 
			
		||||
 * ddbridge-i2c.h: Digital Devices bridge i2c driver
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
/*
 | 
			
		||||
 * ddbridge-io.c: Digital Devices bridge I/O functions
 | 
			
		||||
 *
 | 
			
		||||
@@ -65,6 +66,8 @@ u32 ddbreadl(struct ddb *dev, u32 adr)
 | 
			
		||||
		u32 val, l = (adr >> DDB_LINK_SHIFT) & 3;
 | 
			
		||||
		struct ddb_link *link = &dev->link[l];
 | 
			
		||||
 | 
			
		||||
		if (!link->regs)
 | 
			
		||||
			return 0;
 | 
			
		||||
		spin_lock_irqsave(&link->lock, flags);
 | 
			
		||||
		gtlw(link);
 | 
			
		||||
		ddblwritel0(link, adr & 0xfffc, link->regs + 0x14);
 | 
			
		||||
@@ -84,6 +87,8 @@ void ddbwritel(struct ddb *dev, u32 val, u32 adr)
 | 
			
		||||
		u32 l = (adr >> DDB_LINK_SHIFT);
 | 
			
		||||
		struct ddb_link *link = &dev->link[l];
 | 
			
		||||
 | 
			
		||||
		if (!link->regs)
 | 
			
		||||
			return;
 | 
			
		||||
		spin_lock_irqsave(&link->lock, flags);
 | 
			
		||||
		gtlw(link);
 | 
			
		||||
		ddblwritel0(link, 0xf0000 | (adr & 0xfffc), link->regs + 0x14);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0 */
 | 
			
		||||
/*
 | 
			
		||||
 * ddbridge-io.h: Digital Devices bridge I/O functions
 | 
			
		||||
 *
 | 
			
		||||
@@ -64,7 +65,7 @@ static inline u32 ddblreadl0(struct ddb_link *link, u32 adr)
 | 
			
		||||
	return readl(link->dev->regs + adr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
#ifdef DEBUG_GTLW
 | 
			
		||||
static inline void gtlw(struct ddb_link *link)
 | 
			
		||||
{
 | 
			
		||||
	u32 count = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
/*
 | 
			
		||||
 * ddbridge-m4.c: Digital Devices MAX M4 driver
 | 
			
		||||
 *
 | 
			
		||||
@@ -23,7 +24,6 @@
 | 
			
		||||
 | 
			
		||||
#include "ddbridge.h"
 | 
			
		||||
#include "ddbridge-io.h"
 | 
			
		||||
#include "ddbridge-i2c.h"
 | 
			
		||||
#include "ddbridge-mci.h"
 | 
			
		||||
 | 
			
		||||
struct m4_base {
 | 
			
		||||
@@ -335,6 +335,7 @@ static int set_parameters(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	struct m4 *state = fe->demodulator_priv;
 | 
			
		||||
	int res;
 | 
			
		||||
	//struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 | 
			
		||||
 | 
			
		||||
	stop(fe);
 | 
			
		||||
 | 
			
		||||
@@ -343,6 +344,7 @@ static int set_parameters(struct dvb_frontend *fe)
 | 
			
		||||
	state->iq_constellation_point_max = 0;
 | 
			
		||||
 | 
			
		||||
	state->iq_constellation_tap = 0;
 | 
			
		||||
	//printk("bw = %u\n", p->bandwidth_hz);
 | 
			
		||||
	switch (fe->dtv_property_cache.delivery_system) {
 | 
			
		||||
	case SYS_DVBS:
 | 
			
		||||
	case SYS_DVBS2:
 | 
			
		||||
@@ -450,7 +452,7 @@ static void release(struct dvb_frontend *fe)
 | 
			
		||||
	kfree(state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_algo(struct dvb_frontend *fe)
 | 
			
		||||
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	return DVBFE_ALGO_HW;
 | 
			
		||||
}
 | 
			
		||||
@@ -470,12 +472,12 @@ static struct dvb_frontend_ops m4_ops = {
 | 
			
		||||
		    SYS_DVBS, SYS_DVBS2, SYS_ISDBS, },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "M4",
 | 
			
		||||
		.frequency_min = 950000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.frequency_min_hz = 47125000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max_hz = 2150000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.symbol_rate_min = 100000,
 | 
			
		||||
		.symbol_rate_max = 100000000,
 | 
			
		||||
		.frequency_stepsize	= 0,
 | 
			
		||||
		.frequency_tolerance	= 0,
 | 
			
		||||
		.frequency_stepsize_hz	= 0,
 | 
			
		||||
		.frequency_tolerance_hz	= 0,
 | 
			
		||||
		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
 | 
			
		||||
		FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 |
 | 
			
		||||
		FE_CAN_QAM_AUTO |
 | 
			
		||||
 
 | 
			
		||||
@@ -458,11 +458,9 @@ static pci_ers_result_t ddb_pci_error_detected(struct pci_dev *pdev,
 | 
			
		||||
{
 | 
			
		||||
	switch (state) {
 | 
			
		||||
	case pci_channel_io_frozen:
 | 
			
		||||
		
 | 
			
		||||
		return PCI_ERS_RESULT_CAN_RECOVER;
 | 
			
		||||
	case pci_channel_io_perm_failure:
 | 
			
		||||
		return PCI_ERS_RESULT_DISCONNECT;
 | 
			
		||||
		break;
 | 
			
		||||
	case pci_channel_io_normal:
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
/*
 | 
			
		||||
 * ddbridge-max.c: Digital Devices MAX card line support functions
 | 
			
		||||
 *
 | 
			
		||||
@@ -67,7 +68,7 @@ static int max_emulate_switch(struct dvb_frontend *fe,
 | 
			
		||||
{
 | 
			
		||||
	int input;
 | 
			
		||||
 | 
			
		||||
	if (len !=4)
 | 
			
		||||
	if (len != 4)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	if ((cmd[0] != 0xe0) || (cmd[1] != 0x10) || (cmd[2] != 0x39))
 | 
			
		||||
@@ -357,6 +358,29 @@ static int max_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
 | 
			
		||||
 | 
			
		||||
static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb_input *input = fe->sec_priv;
 | 
			
		||||
	struct ddb_port *port = input->port;
 | 
			
		||||
	struct ddb *dev = port->dev;
 | 
			
		||||
	u32 tag = DDB_LINK_TAG(port->lnr);
 | 
			
		||||
	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
 | 
			
		||||
	u32 fmode = dev->link[port->lnr].lnb.fmode;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&dev->link[port->lnr].lnb.lock);
 | 
			
		||||
	switch (fmode) {
 | 
			
		||||
	default:
 | 
			
		||||
	case 0:
 | 
			
		||||
	case 3:
 | 
			
		||||
		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(dvb->input));
 | 
			
		||||
		break;
 | 
			
		||||
	case 1:
 | 
			
		||||
	case 2:
 | 
			
		||||
		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(0));
 | 
			
		||||
		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(1));
 | 
			
		||||
		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(2));
 | 
			
		||||
		ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(3));
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	mutex_unlock(&dev->link[port->lnr].lnb.lock);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -467,9 +491,6 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
 | 
			
		||||
 | 
			
		||||
/* MAX MCI related functions */
 | 
			
		||||
 | 
			
		||||
extern struct mci_cfg ddb_max_sx8_cfg;
 | 
			
		||||
extern struct mci_cfg ddb_max_m4_cfg;
 | 
			
		||||
 | 
			
		||||
int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
 | 
			
		||||
{
 | 
			
		||||
	struct ddb *dev = input->port->dev;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
/*
 | 
			
		||||
 * ddbridge-mci.c: Digital Devices microcode interface
 | 
			
		||||
 *
 | 
			
		||||
@@ -38,7 +39,7 @@ static int mci_reset(struct mci *state)
 | 
			
		||||
	msleep(300);
 | 
			
		||||
	ddblwritel(link, 0, MCI_CONTROL);
 | 
			
		||||
 | 
			
		||||
	while(1) {
 | 
			
		||||
	while (1) {
 | 
			
		||||
		status = ddblreadl(link, MCI_CONTROL);
 | 
			
		||||
		if ((status & MCI_CONTROL_READY) == MCI_CONTROL_READY)
 | 
			
		||||
			break;
 | 
			
		||||
@@ -46,7 +47,7 @@ static int mci_reset(struct mci *state)
 | 
			
		||||
			break;
 | 
			
		||||
		msleep(50);
 | 
			
		||||
	}
 | 
			
		||||
	if ((status & MCI_CONTROL_READY) == 0 )
 | 
			
		||||
	if ((status & MCI_CONTROL_READY) == 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
	if (link->ids.device == 0x0009  || link->ids.device == 0x000b)
 | 
			
		||||
		ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG);
 | 
			
		||||
@@ -85,13 +86,15 @@ static int ddb_mci_cmd_raw_unlocked(struct mci *state,
 | 
			
		||||
	if (stat == 0) {
 | 
			
		||||
		u32 istat = ddblreadl(link, INTERRUPT_STATUS);
 | 
			
		||||
 | 
			
		||||
		printk("MCI timeout\n");
 | 
			
		||||
		dev_err(state->base->link->dev->dev, "MCI timeout\n");
 | 
			
		||||
		val = ddblreadl(link, MCI_CONTROL);
 | 
			
		||||
		if (val == 0xffffffff) {
 | 
			
		||||
			printk("Lost PCIe link!\n");
 | 
			
		||||
			dev_err(state->base->link->dev->dev,
 | 
			
		||||
				"Lost PCIe link!\n");
 | 
			
		||||
			return -EIO;
 | 
			
		||||
		} else {
 | 
			
		||||
			printk("DDBridge IRS %08x link %u\n", istat, link->nr);
 | 
			
		||||
			dev_err(state->base->link->dev->dev,
 | 
			
		||||
				"DDBridge IRS %08x link %u\n", istat, link->nr);
 | 
			
		||||
			if (istat & 1)
 | 
			
		||||
				ddblwritel(link, istat, INTERRUPT_ACK);
 | 
			
		||||
			if (link->nr)
 | 
			
		||||
@@ -186,8 +189,7 @@ int ddb_mci_get_snr(struct dvb_frontend *fe)
 | 
			
		||||
 | 
			
		||||
	p->cnr.len = 1;
 | 
			
		||||
	p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
 | 
			
		||||
	p->cnr.stat[0].svalue = (s64) mci->
 | 
			
		||||
		signal_info.dvbs2_signal_info.signal_to_noise * 10;
 | 
			
		||||
	p->cnr.stat[0].svalue = (s64) mci->signal_info.dvbs2_signal_info.signal_to_noise * 10;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -259,23 +261,31 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
 | 
			
		||||
	{
 | 
			
		||||
		u32 pls_code =
 | 
			
		||||
			mci->signal_info.dvbs2_signal_info.pls_code;
 | 
			
		||||
		
 | 
			
		||||
		p->frequency =
 | 
			
		||||
			mci->signal_info.dvbs2_signal_info.frequency / 1000;
 | 
			
		||||
		p->delivery_system =
 | 
			
		||||
			(mci->signal_info.dvbs2_signal_info.standard == 2)  ?
 | 
			
		||||
			SYS_DVBS2 : SYS_DVBS;
 | 
			
		||||
		if (mci->signal_info.dvbs2_signal_info.standard == 2) {
 | 
			
		||||
			u32 modcod = (0x7c & pls_code) >> 2;
 | 
			
		||||
			u32 modcod;
 | 
			
		||||
 | 
			
		||||
			p->delivery_system = SYS_DVBS2;
 | 
			
		||||
			p->transmission_mode = pls_code;
 | 
			
		||||
			p->rolloff =
 | 
			
		||||
				ro_lut[mci->signal_info.
 | 
			
		||||
				       dvbs2_signal_info.roll_off & 7];
 | 
			
		||||
				ro_lut[mci->signal_info.dvbs2_signal_info.roll_off & 7];
 | 
			
		||||
			p->pilot = (pls_code & 1) ? PILOT_ON : PILOT_OFF;
 | 
			
		||||
			if (pls_code & 0x80) {
 | 
			
		||||
				/* no suitable values defined in Linux DVB API yet */
 | 
			
		||||
				/* modcod = (0x7f & pls_code) >> 1; */
 | 
			
		||||
				p->fec_inner = FEC_NONE;
 | 
			
		||||
				p->modulation = 0;
 | 
			
		||||
				if (pls_code >= 250)
 | 
			
		||||
					p->pilot = PILOT_ON;
 | 
			
		||||
			} else {
 | 
			
		||||
				modcod = (0x7c & pls_code) >> 2;
 | 
			
		||||
				p->fec_inner = modcod2fec[modcod];
 | 
			
		||||
				p->modulation = modcod2mod[modcod];
 | 
			
		||||
			p->transmission_mode = pls_code;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			p->delivery_system = SYS_DVBS;
 | 
			
		||||
			p->rolloff = ROLLOFF_35;
 | 
			
		||||
@@ -314,8 +324,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
 | 
			
		||||
 | 
			
		||||
	p->cnr.len = 1;
 | 
			
		||||
	p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
 | 
			
		||||
	p->cnr.stat[0].svalue = (s64) mci->
 | 
			
		||||
		signal_info.dvbs2_signal_info.signal_to_noise * 10;
 | 
			
		||||
	p->cnr.stat[0].svalue = (s64)
 | 
			
		||||
		mci->signal_info.dvbs2_signal_info.signal_to_noise * 10;
 | 
			
		||||
 | 
			
		||||
	p->strength.len = 1;
 | 
			
		||||
	p->strength.stat[0].scale = FE_SCALE_DECIBEL;
 | 
			
		||||
@@ -388,6 +398,7 @@ struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg
 | 
			
		||||
	state->nr = nr;
 | 
			
		||||
	state->demod = nr;
 | 
			
		||||
	state->tuner = tuner;
 | 
			
		||||
	state->input = input;
 | 
			
		||||
	if (cfg->init)
 | 
			
		||||
		cfg->init(state);
 | 
			
		||||
	return &state->fe;
 | 
			
		||||
 
 | 
			
		||||
@@ -148,11 +148,12 @@
 | 
			
		||||
#define M4_CMD_GET_IDS            (0x51)
 | 
			
		||||
#define M4_CMD_GET_DVBT_TPS       (0x52)
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
#define M4_CMD_GET_BBHEADER       (MCI_CMD_GET_BBHEADER)
 | 
			
		||||
 | 
			
		||||
#define M4_L1INFO_SEL_PRE         (0)
 | 
			
		||||
#define M4_L1INFO_SEL_DSINFO      (1)
 | 
			
		||||
#define M4_L1INFO_SEL_PLPINFO     (2)
 | 
			
		||||
@@ -180,6 +181,7 @@
 | 
			
		||||
#define M4_SIGNALINFO_FLAG_CHANGE (0x01)
 | 
			
		||||
#define M4_SIGNALINFO_FLAG_EWS    (0x02)
 | 
			
		||||
 | 
			
		||||
#define SX8_ROLLOFF_35  0
 | 
			
		||||
#define SX8_ROLLOFF_25  1
 | 
			
		||||
#define SX8_ROLLOFF_20  2
 | 
			
		||||
#define SX8_ROLLOFF_15  5
 | 
			
		||||
@@ -205,7 +207,7 @@ struct mci_command {
 | 
			
		||||
		u32 params[31];
 | 
			
		||||
		struct {
 | 
			
		||||
			u8  flags; /* Bit 0: DVB-S Enabled, 1: DVB-S2 Enabled,
 | 
			
		||||
				      6: FrequencyRange, 7: InputStreamID */
 | 
			
		||||
				      5: ChannelBonding, 6: FrequencyRange, 7: InputStreamID */
 | 
			
		||||
			u8  s2_modulation_mask; /* Bit 0 : QPSK, 1: 8PSK/8APSK,
 | 
			
		||||
						   2 : 16APSK, 3: 32APSK, 4: 64APSK,
 | 
			
		||||
						   5: 128APSK, 6: 256APSK */
 | 
			
		||||
@@ -217,6 +219,9 @@ struct mci_command {
 | 
			
		||||
			u8  rsvd2[3];
 | 
			
		||||
			u32 scrambling_sequence_index;
 | 
			
		||||
			u32 frequency_range;
 | 
			
		||||
			u8  channel_bonding_config; /* Bit 7: IsSlave,  Bit 5..4: MasterDemod,
 | 
			
		||||
						       bit 0:  Num channels - 2. 
 | 
			
		||||
						       (must be set on all channels to same value) */
 | 
			
		||||
		} dvbs2_search;
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
@@ -306,11 +311,10 @@ struct mci_command {
 | 
			
		||||
			u16  point;
 | 
			
		||||
		} get_iq_symbol;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
			uint8_t   flags; /*  Bit 0 : 0 = VTM/SDR, 1 = SCAN,
 | 
			
		||||
					     Bit 1: 1 = Disable AGC, Bit 2:
 | 
			
		||||
					     1 = Set Gain.   */
 | 
			
		||||
					     Bit 1: 1 = Disable AGC,
 | 
			
		||||
					     Bit 2: 1 = Set Gain.   */
 | 
			
		||||
			uint8_t   roll_off;
 | 
			
		||||
			uint8_t   rsvd1;
 | 
			
		||||
			uint8_t   rsvd2;
 | 
			
		||||
@@ -393,6 +397,21 @@ struct mci_result {
 | 
			
		||||
			u32 ber_denominator;		
 | 
			
		||||
		} dvbs2_signal_info;
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
			u8  modcod;
 | 
			
		||||
			u8  rsvd0[2];
 | 
			
		||||
			u8  flags;             /* Bit 0: TMCC changed, Bit 1: EWS */
 | 
			
		||||
			u32 frequency;         /* actual frequency in Hz */
 | 
			
		||||
			u32 symbol_rate;       /* actual symbolrate in Hz */
 | 
			
		||||
			s16 channel_power;     /* channel power in dBm x 100 */
 | 
			
		||||
			s16 band_power;        /*/ band power in dBm x 100 */
 | 
			
		||||
			s16 signal_to_noise;   /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */
 | 
			
		||||
			s16 rsvd2;
 | 
			
		||||
			u32 packet_errors;     /* Counter for packet errors. (set to 0 on Start command) */
 | 
			
		||||
			u32 ber_numerator;     /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
 | 
			
		||||
			u32 ber_denominator;		
 | 
			
		||||
		} isdbs_signal_info;
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
			u8  constellation;
 | 
			
		||||
			u8  rsvd0[2];
 | 
			
		||||
@@ -648,7 +667,6 @@ struct mci_result {
 | 
			
		||||
		struct {
 | 
			
		||||
			u8  Mode;          // FFT Mode   1,2,3
 | 
			
		||||
			u8  GuardInterval; // 1/32, 1/16, 1/8, /14
 | 
			
		||||
			
 | 
			
		||||
			u8  TMCCInfo[13];  // TMCC B20 - B121,  byte 0 bit 7: B20,  byte 12 bit 2: B121
 | 
			
		||||
		} ISDBT_TMCCInfo;
 | 
			
		||||
 | 
			
		||||
@@ -710,7 +728,7 @@ struct mci_result {
 | 
			
		||||
 | 
			
		||||
/* DVB-T2 L1-Post Signalling Data   ( ETSI EN 302 755 V1.4.1 Chapter 7.2.3 ) */
 | 
			
		||||
 | 
			
		||||
#define L1POST_SUB_SLICES_PER_FRAME(p)     (((u16)(p)[ 0] & 0x7F) | (p)[ 1])
 | 
			
		||||
#define L1POST_SUB_SLICES_PER_FRAME(p)     (((u16)(p)[0] & 0x7F) | (p)[1])
 | 
			
		||||
#define L1POST_NUM_PLP(p)                  ((p)[2] & 0xFF)
 | 
			
		||||
#define L1POST_NUM_AUX(p)                  ((p)[3] & 0x0F)
 | 
			
		||||
#define L1POST_AUX_CONFIG_RFU(p)           ((p)[4] & 0xFF)
 | 
			
		||||
@@ -750,8 +768,6 @@ struct mci_base {
 | 
			
		||||
	void                *key;
 | 
			
		||||
	struct ddb_link     *link;
 | 
			
		||||
	struct completion    completion;
 | 
			
		||||
	struct i2c_adapter  *i2c;
 | 
			
		||||
	struct mutex         i2c_lock;
 | 
			
		||||
	struct mutex         tuner_lock;
 | 
			
		||||
	struct mutex         mci_lock;
 | 
			
		||||
	int                  count;
 | 
			
		||||
@@ -759,6 +775,7 @@ struct mci_base {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mci {
 | 
			
		||||
	struct ddb_io       *input;
 | 
			
		||||
	struct mci_base     *base;
 | 
			
		||||
	struct dvb_frontend  fe;
 | 
			
		||||
	int                  nr;
 | 
			
		||||
@@ -787,4 +804,7 @@ int ddb_mci_get_info(struct mci *mci);
 | 
			
		||||
int ddb_mci_get_strength(struct dvb_frontend *fe);
 | 
			
		||||
void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p);
 | 
			
		||||
 | 
			
		||||
extern struct mci_cfg ddb_max_sx8_cfg;
 | 
			
		||||
extern struct mci_cfg ddb_max_m4_cfg;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -435,7 +435,7 @@ static int mod_setup_max2871(struct ddb *dev, u32 *reg)
 | 
			
		||||
 | 
			
		||||
			if (j == 4)
 | 
			
		||||
				val &= 0xFFFFFEDF;
 | 
			
		||||
			status = mod_write_max2871(dev, reg[j]);
 | 
			
		||||
			status = mod_write_max2871(dev, val);
 | 
			
		||||
			if (status)
 | 
			
		||||
				break;
 | 
			
		||||
			msleep(30);
 | 
			
		||||
@@ -1516,11 +1516,12 @@ 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;
 | 
			
		||||
	u32 cic, inc, bypass = 0;
 | 
			
		||||
 | 
			
		||||
	switch (rate) {
 | 
			
		||||
		/* 2^31 * freq*4*cic / 245.76Mhz */
 | 
			
		||||
	case SYS_DVBT_6:
 | 
			
		||||
		inc = 1917396114;
 | 
			
		||||
		inc = 0x72492492;
 | 
			
		||||
		cic = 8;
 | 
			
		||||
		break;
 | 
			
		||||
	case SYS_DVBT_7:
 | 
			
		||||
@@ -1532,15 +1533,45 @@ static int mod3_set_sample_rate(struct ddb_mod *mod, u32 rate)
 | 
			
		||||
		inc = 1917396114;
 | 
			
		||||
		cic = 6;
 | 
			
		||||
		break;
 | 
			
		||||
	case SYS_DVBC_6900:
 | 
			
		||||
		inc = 0x73000000; //1929379840;
 | 
			
		||||
		cic = 8;
 | 
			
		||||
		break;
 | 
			
		||||
	case 9:
 | 
			
		||||
		inc = 0x47e00000; //1929379840;
 | 
			
		||||
		cic = 10;
 | 
			
		||||
		bypass = 2;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case SYS_J83B_64_6: /* 5056941  */
 | 
			
		||||
		inc = 0x695a5a1d;
 | 
			
		||||
		cic = 10;
 | 
			
		||||
		break;
 | 
			
		||||
	case SYS_J83B_256_6: /* 5360537  */
 | 
			
		||||
		inc = 0x6fad87da;
 | 
			
		||||
		cic = 10;
 | 
			
		||||
		break;
 | 
			
		||||
		
 | 
			
		||||
	case SYS_ISDBT_6:
 | 
			
		||||
		inc = 1988410754;
 | 
			
		||||
		inc = 0x7684BD82; //1988410754;
 | 
			
		||||
		cic = 7;
 | 
			
		||||
		break;
 | 
			
		||||
	case SYS_DVBS2_22:
 | 
			
		||||
		inc = 0x72955555; // 1922389333;
 | 
			
		||||
		cic = 5;
 | 
			
		||||
		bypass = 2;
 | 
			
		||||
		break;
 | 
			
		||||
	case SYS_DVBS2_24:
 | 
			
		||||
		inc = 0x7d000000;
 | 
			
		||||
		cic = 5;
 | 
			
		||||
		bypass = 2;
 | 
			
		||||
		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));
 | 
			
		||||
	ddbwritel(mod->port->dev, (cic << 8) | (bypass << 4),
 | 
			
		||||
		  SDR_CHANNEL_CONFIG(mod->port->nr));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1870,7 +1901,7 @@ static int rfdac_init(struct ddb *dev)
 | 
			
		||||
	}
 | 
			
		||||
	if (tmp & 0x80)
 | 
			
		||||
		return -1;
 | 
			
		||||
	dev_info(dev->dev, "sync %d:%08x\n", i, tmp);
 | 
			
		||||
	//dev_info(dev->dev, "sync %d:%08x\n", i, tmp);
 | 
			
		||||
	ddbwritel(dev, RFDAC_CMD_RESET, RFDAC_CONTROL);
 | 
			
		||||
	for (i = 0; i < 10; i++) {
 | 
			
		||||
		msleep(20);
 | 
			
		||||
@@ -1880,7 +1911,7 @@ static int rfdac_init(struct ddb *dev)
 | 
			
		||||
	}
 | 
			
		||||
	if (tmp & 0x80)
 | 
			
		||||
		return -1;
 | 
			
		||||
	dev_info(dev->dev, "sync %d:%08x\n", i, tmp);
 | 
			
		||||
	//dev_info(dev->dev, "sync %d:%08x\n", i, tmp);
 | 
			
		||||
	ddbwritel(dev, RFDAC_CMD_SETUP, RFDAC_CONTROL);
 | 
			
		||||
	for (i = 0; i < 10; i++) {
 | 
			
		||||
		msleep(20);
 | 
			
		||||
@@ -1890,7 +1921,7 @@ static int rfdac_init(struct ddb *dev)
 | 
			
		||||
	}
 | 
			
		||||
	if (tmp & 0x80)
 | 
			
		||||
		return -1;
 | 
			
		||||
	dev_info(dev->dev, "sync %d:%08x\n", i, tmp);
 | 
			
		||||
	//dev_info(dev->dev, "sync %d:%08x\n", i, tmp);
 | 
			
		||||
	ddbwritel(dev, 0x01, JESD204B_BASE);
 | 
			
		||||
	for (i = 0; i < 400; i++) {
 | 
			
		||||
		msleep(20);
 | 
			
		||||
@@ -1898,7 +1929,7 @@ static int rfdac_init(struct ddb *dev)
 | 
			
		||||
		if ((tmp & 0xc0000000) == 0xc0000000)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	dev_info(dev->dev, "sync %d:%08x\n", i, tmp);
 | 
			
		||||
	//dev_info(dev->dev, "sync %d:%08x\n", i, tmp);
 | 
			
		||||
	if ((tmp & 0xc0000000) != 0xc0000000)
 | 
			
		||||
		return -1;
 | 
			
		||||
	return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ddbridge-ns.c: Digital Devices PCIe bridge driver net streaming
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010-2017Marcus Metzler <mocm@metzlerbros.de>
 | 
			
		||||
 * Copyright (C) 2010-2017 Digital Devices GmbH
 | 
			
		||||
 *                         Marcus Metzler <mocm@metzlerbros.de>
 | 
			
		||||
 *                         Ralph Metzler <rjkm@metzlerbros.de>
 | 
			
		||||
 *                         Digital Devices GmbH
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
@@ -441,11 +441,11 @@ static int ns_start(struct dvbnss *nss)
 | 
			
		||||
		reg |= 0x40;
 | 
			
		||||
	if (nss->params.flags & DVB_NS_IPV6)
 | 
			
		||||
		reg |= 0x80;
 | 
			
		||||
	ddbwritel(dev, reg | (dns->fe->nr << 8) | (dns->fe->port->lnr << 16),
 | 
			
		||||
		  STREAM_CONTROL(dns->nr));
 | 
			
		||||
	if (dns->fe != input)
 | 
			
		||||
		ddb_dvb_ns_input_start(dns->fe);
 | 
			
		||||
	ddb_dvb_ns_input_start(input);
 | 
			
		||||
	ddbwritel(dev, reg | (dns->fe->nr << 8) | (dns->fe->port->lnr << 16),
 | 
			
		||||
		  STREAM_CONTROL(dns->nr));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -232,6 +232,7 @@
 | 
			
		||||
 | 
			
		||||
#define TS_CONTROL(_io)         ((_io)->regs + 0x00)
 | 
			
		||||
#define TS_CONTROL2(_io)        ((_io)->regs + 0x04)
 | 
			
		||||
#define TS_STAT(_io)            ((_io)->regs + 0x08)
 | 
			
		||||
 | 
			
		||||
#define TS_INPUT_CONTROL_ENABLE     (0x00000001)
 | 
			
		||||
#define TS_INPUT_CONTROL_RESET      (0x00000002)
 | 
			
		||||
 
 | 
			
		||||
@@ -138,7 +138,6 @@ 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;
 | 
			
		||||
	}
 | 
			
		||||
@@ -162,7 +161,10 @@ static int mci_set_tuner(struct dvb_frontend *fe, u32 tuner, u32 on)
 | 
			
		||||
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;
 | 
			
		||||
@@ -171,7 +173,19 @@ static int stop_iq(struct dvb_frontend *fe)
 | 
			
		||||
	cmd.demod = state->mci.demod;
 | 
			
		||||
	ddb_mci_cmd(&state->mci, &cmd, NULL);
 | 
			
		||||
	ddb_mci_config(&state->mci, SX8_TSCONFIG_MODE_NORMAL);
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&mci_base->tuner_lock);
 | 
			
		||||
	sx8_base->tuner_use_count[input]--;
 | 
			
		||||
        if (!sx8_base->tuner_use_count[input])
 | 
			
		||||
		mci_set_tuner(fe, input, 0);
 | 
			
		||||
	if (state->mci.demod != SX8_DEMOD_NONE) {
 | 
			
		||||
		sx8_base->demod_in_use[state->mci.demod] = 0;
 | 
			
		||||
		state->mci.demod = SX8_DEMOD_NONE;
 | 
			
		||||
	}
 | 
			
		||||
	sx8_base->used_ldpc_bitrate[state->mci.nr] = 0;	
 | 
			
		||||
	sx8_base->iq_mode = 0;
 | 
			
		||||
	state->iq_started = 0;
 | 
			
		||||
	mutex_unlock(&mci_base->tuner_lock);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -226,7 +240,14 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
 | 
			
		||||
	u32 input = state->mci.tuner;
 | 
			
		||||
	u32 bits_per_symbol = 0;
 | 
			
		||||
	int i = -1, stat = 0;
 | 
			
		||||
	struct ddb_link *link = state->mci.base->link;
 | 
			
		||||
 | 
			
		||||
	if (link->ids.device == 0x000b) {
 | 
			
		||||
		/* Mask out higher modulations and MIS for Basic
 | 
			
		||||
		   or search command will fail */
 | 
			
		||||
		modmask &= 3;
 | 
			
		||||
		p->stream_id = NO_STREAM_ID_FILTER;
 | 
			
		||||
	}
 | 
			
		||||
	if (p->symbol_rate >= MCLK / 2)
 | 
			
		||||
		flags &= ~1;
 | 
			
		||||
	if ((flags & 3) == 0)
 | 
			
		||||
@@ -241,7 +262,6 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
 | 
			
		||||
			bits_per_symbol++;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	mutex_lock(&mci_base->tuner_lock);
 | 
			
		||||
	if (sx8_base->iq_mode) {
 | 
			
		||||
		stat = -EBUSY;
 | 
			
		||||
@@ -334,7 +354,8 @@ unlock:
 | 
			
		||||
	cmd.tuner = state->mci.tuner;
 | 
			
		||||
	cmd.demod = state->mci.demod;
 | 
			
		||||
	cmd.output = state->mci.nr;
 | 
			
		||||
	if (p->stream_id == 0x80000000)
 | 
			
		||||
	if ((p->stream_id != NO_STREAM_ID_FILTER)  &&
 | 
			
		||||
	    (p->stream_id & 0x80000000))
 | 
			
		||||
		cmd.output |= 0x80;
 | 
			
		||||
	stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
 | 
			
		||||
	if (stat)
 | 
			
		||||
@@ -355,6 +376,7 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
 | 
			
		||||
	u32 input = state->mci.tuner;
 | 
			
		||||
	int i, stat = 0;
 | 
			
		||||
 | 
			
		||||
	if (!state->iq_started) {
 | 
			
		||||
		mutex_lock(&mci_base->tuner_lock);
 | 
			
		||||
		if (sx8_base->iq_mode) {
 | 
			
		||||
			stat = -EBUSY;
 | 
			
		||||
@@ -372,17 +394,18 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
 | 
			
		||||
			mci_set_tuner(fe, input, 1);
 | 
			
		||||
		sx8_base->tuner_use_count[input]++;
 | 
			
		||||
		sx8_base->iq_mode = (ts_config > 1);
 | 
			
		||||
unlock:
 | 
			
		||||
	unlock:
 | 
			
		||||
		mutex_unlock(&mci_base->tuner_lock);
 | 
			
		||||
		if (stat)
 | 
			
		||||
			return stat;
 | 
			
		||||
	
 | 
			
		||||
	}
 | 
			
		||||
	memset(&cmd, 0, sizeof(cmd));
 | 
			
		||||
	cmd.command = SX8_CMD_START_IQ;
 | 
			
		||||
	cmd.sx8_start_iq.flags = flags;
 | 
			
		||||
	cmd.sx8_start_iq.flags = flags >> 8;
 | 
			
		||||
	cmd.sx8_start_iq.roll_off = roll_off;
 | 
			
		||||
	cmd.sx8_start_iq.frequency = p->frequency * 1000;
 | 
			
		||||
	cmd.sx8_start_iq.symbol_rate = p->symbol_rate;
 | 
			
		||||
	cmd.sx8_start_iq.gain = flags & 0xff;
 | 
			
		||||
	cmd.tuner = state->mci.tuner;
 | 
			
		||||
	cmd.demod = state->mci.demod;
 | 
			
		||||
	stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
 | 
			
		||||
@@ -392,18 +415,26 @@ unlock:
 | 
			
		||||
	return stat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int set_lna(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	printk("set_lna\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int set_parameters(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	int stat = 0;
 | 
			
		||||
	struct sx8 *state = fe->demodulator_priv;
 | 
			
		||||
	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 | 
			
		||||
	u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi;
 | 
			
		||||
 | 
			
		||||
	u32 ts_config = SX8_TSCONFIG_MODE_NORMAL, iq_mode = 0, isi, ts_mode = 0;
 | 
			
		||||
 | 
			
		||||
	isi = p->stream_id;
 | 
			
		||||
	if (isi != NO_STREAM_ID_FILTER) {
 | 
			
		||||
		iq_mode = (isi & 0x30000000) >> 28;
 | 
			
		||||
		ts_mode = (isi & 0x03000000) >> 24;
 | 
			
		||||
	}
 | 
			
		||||
	state->mci.input->con = ts_mode << 8;
 | 
			
		||||
	if (iq_mode)
 | 
			
		||||
		ts_config = (SX8_TSCONFIG_TSHEADER | SX8_TSCONFIG_MODE_IQ);
 | 
			
		||||
	stop(fe);
 | 
			
		||||
@@ -438,7 +469,7 @@ static int set_parameters(struct dvb_frontend *fe)
 | 
			
		||||
			state->mci.signal_info.status = MCI_DEMOD_WAIT_SIGNAL;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		stat = start_iq(fe, iq_mode & 1, 4, ts_config);
 | 
			
		||||
		stat = start_iq(fe, (isi >> 8) & 0xffff, 4, ts_config);
 | 
			
		||||
		if (!stat) {
 | 
			
		||||
			state->iq_started = 1;
 | 
			
		||||
			state->first_time_lock = 1;
 | 
			
		||||
@@ -469,7 +500,7 @@ static int tune(struct dvb_frontend *fe, bool re_tune,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_algo(struct dvb_frontend *fe)
 | 
			
		||||
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	return DVBFE_ALGO_HW;
 | 
			
		||||
}
 | 
			
		||||
@@ -509,10 +540,10 @@ static struct dvb_frontend_ops sx8_ops = {
 | 
			
		||||
	.xbar   = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "DVB-S/S2X",
 | 
			
		||||
		.frequency_min		= 950000,
 | 
			
		||||
		.frequency_max		= 2150000,
 | 
			
		||||
		.frequency_stepsize	= 0,
 | 
			
		||||
		.frequency_tolerance	= 0,
 | 
			
		||||
		.frequency_min_hz	= 950000000,
 | 
			
		||||
		.frequency_max_hz	= 2150000000,
 | 
			
		||||
		.frequency_stepsize_hz	= 0,
 | 
			
		||||
		.frequency_tolerance_hz	= 0,
 | 
			
		||||
		.symbol_rate_min	= 100000,
 | 
			
		||||
		.symbol_rate_max	= 100000000,
 | 
			
		||||
		.caps			= FE_CAN_INVERSION_AUTO |
 | 
			
		||||
@@ -527,6 +558,7 @@ static struct dvb_frontend_ops sx8_ops = {
 | 
			
		||||
	.release                        = release,
 | 
			
		||||
	.read_status                    = read_status,
 | 
			
		||||
	.set_input                      = set_input,
 | 
			
		||||
	.set_lna                        = set_lna,
 | 
			
		||||
	.sleep                          = sleep,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0 */
 | 
			
		||||
/*
 | 
			
		||||
 * ddbridge.h: Digital Devices PCIe bridge driver
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010-2019 Digital Devices GmbH
 | 
			
		||||
 * Copyright (C) 2010-2017 Digital Devices GmbH
 | 
			
		||||
 *                         Marcus Metzler <mocm@metzlerbros.de>
 | 
			
		||||
 *                         Ralph Metzler <rjkm@metzlerbros.de>
 | 
			
		||||
 *
 | 
			
		||||
@@ -15,10 +16,8 @@
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, point your browser to
 | 
			
		||||
 * http://www.gnu.org/copyleft/gpl.html
 | 
			
		||||
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _DDBRIDGE_H_
 | 
			
		||||
@@ -61,22 +60,20 @@
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <asm/dma.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <linux/uaccess.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/dvb/ca.h>
 | 
			
		||||
#include <linux/socket.h>
 | 
			
		||||
#include <linux/device.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_netstream.h"
 | 
			
		||||
#include "dmxdev.h"
 | 
			
		||||
#include "dvbdev.h"
 | 
			
		||||
#include "dvb_demux.h"
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include "dvb_ringbuffer.h"
 | 
			
		||||
#include "dvb_ca_en50221.h"
 | 
			
		||||
#include "dvb_net.h"
 | 
			
		||||
#include <media/dmxdev.h>
 | 
			
		||||
#include <media/dvbdev.h>
 | 
			
		||||
#include <media/dvb_demux.h>
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
#include <media/dvb_ringbuffer.h>
 | 
			
		||||
#include <media/dvb_ca_en50221.h>
 | 
			
		||||
#include <media/dvb_net.h>
 | 
			
		||||
 | 
			
		||||
#include "tda18271c2dd.h"
 | 
			
		||||
#include "stv6110x.h"
 | 
			
		||||
@@ -215,6 +212,9 @@ struct ddb_dma {
 | 
			
		||||
	u32                    ctrl;
 | 
			
		||||
	u32                    cbuf;
 | 
			
		||||
	u32                    coff;
 | 
			
		||||
 | 
			
		||||
	u32                    stall_count;
 | 
			
		||||
	u32                    packet_loss;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ddb_dvb {
 | 
			
		||||
@@ -236,7 +236,7 @@ struct ddb_dvb {
 | 
			
		||||
	enum fe_sec_tone_mode  tone;
 | 
			
		||||
	enum fe_sec_voltage    voltage;
 | 
			
		||||
 | 
			
		||||
	int (*i2c_gate_ctrl)(struct dvb_frontend *, int);
 | 
			
		||||
	int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int val);
 | 
			
		||||
	int (*set_voltage)(struct dvb_frontend *fe,
 | 
			
		||||
			   enum fe_sec_voltage voltage);
 | 
			
		||||
	int (*set_input)(struct dvb_frontend *fe, int input);
 | 
			
		||||
@@ -254,6 +254,7 @@ struct ddb_io {
 | 
			
		||||
	struct ddb_port       *port;
 | 
			
		||||
	u32                    nr;
 | 
			
		||||
	u32                    regs;
 | 
			
		||||
	u32                    con;
 | 
			
		||||
	struct ddb_dma        *dma;
 | 
			
		||||
	struct ddb_io         *redo;
 | 
			
		||||
	struct ddb_io         *redi;
 | 
			
		||||
@@ -405,7 +406,7 @@ struct ddb_lnb {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ddb_irq {
 | 
			
		||||
	void                   (*handler)(void *);
 | 
			
		||||
	void                   (*handler)(void *data);
 | 
			
		||||
	void                   *data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -424,6 +425,8 @@ struct ddb_link {
 | 
			
		||||
	int                    over_temperature_error;
 | 
			
		||||
	u8                     temp_tab[11];
 | 
			
		||||
	struct ddb_irq         irq[256];
 | 
			
		||||
 | 
			
		||||
	struct mci_base        *mci_base;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ddb {
 | 
			
		||||
@@ -450,7 +453,7 @@ struct ddb {
 | 
			
		||||
	struct ddb_dma         odma[DDB_MAX_OUTPUT];
 | 
			
		||||
 | 
			
		||||
	struct device         *ddb_dev;
 | 
			
		||||
	u32                    ddb_dev_users;
 | 
			
		||||
	atomic_t               ddb_dev_users;
 | 
			
		||||
	u32                    nr;
 | 
			
		||||
	u8                     iobuf[1028];
 | 
			
		||||
 | 
			
		||||
@@ -539,7 +542,7 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg);
 | 
			
		||||
int ddbridge_mod_init(struct ddb *dev);
 | 
			
		||||
void ddbridge_mod_output_stop(struct ddb_output *output);
 | 
			
		||||
int ddbridge_mod_output_start(struct ddb_output *output);
 | 
			
		||||
void ddbridge_mod_rate_handler(void *);
 | 
			
		||||
void ddbridge_mod_rate_handler(void *data);
 | 
			
		||||
 | 
			
		||||
void ddb_device_destroy(struct ddb *dev);
 | 
			
		||||
void ddb_nsd_detach(struct ddb *dev);
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@
 | 
			
		||||
#include <asm/uaccess.h>
 | 
			
		||||
#include <linux/dvb/ns.h>
 | 
			
		||||
 | 
			
		||||
#include "dvbdev.h"
 | 
			
		||||
#include <media/dvbdev.h>
 | 
			
		||||
 | 
			
		||||
#define DVBNS_MAXPIDS 32
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ is currently considered experimental.
 | 
			
		||||
 | 
			
		||||
Supported hardware:
 | 
			
		||||
 | 
			
		||||
Cine V7A                  (>=1.7 FW)
 | 
			
		||||
cineS2 V7A                (>=1.7 FW)
 | 
			
		||||
OctopusCI S2 Pro Advanced (>=1.7 FW)
 | 
			
		||||
Duoflex S2 v4 Advanced    (TBA)
 | 
			
		||||
MaxSX8                    (NOT the MAXS8!)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,34 @@
 | 
			
		||||
# SPDX-License-Identifier: GPL-2.0-only
 | 
			
		||||
#
 | 
			
		||||
# DVB device configuration
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
config DVB_MMAP
 | 
			
		||||
	bool "Enable DVB memory-mapped API (EXPERIMENTAL)"
 | 
			
		||||
	depends on DVB_CORE
 | 
			
		||||
	depends on VIDEO_V4L2=y || VIDEO_V4L2=DVB_CORE
 | 
			
		||||
	select VIDEOBUF2_VMALLOC
 | 
			
		||||
	help
 | 
			
		||||
	  This option enables DVB experimental memory-mapped API, which
 | 
			
		||||
	  reduces the number of context switches to read DVB buffers, as
 | 
			
		||||
	  the buffers can use mmap() syscalls.
 | 
			
		||||
 | 
			
		||||
	  Support for it is experimental. Use with care. If unsure,
 | 
			
		||||
	  say N.
 | 
			
		||||
 | 
			
		||||
config DVB_NET
 | 
			
		||||
	bool "DVB Network Support"
 | 
			
		||||
	default (NET && INET)
 | 
			
		||||
	depends on NET && INET && DVB_CORE
 | 
			
		||||
	help
 | 
			
		||||
	  This option enables DVB Network Support which is a part of the DVB
 | 
			
		||||
	  standard. It is used, for example, by automatic firmware updates used
 | 
			
		||||
	  on Set-Top-Boxes. It can also be used to access the Internet via the
 | 
			
		||||
	  DVB card, if the network provider supports it.
 | 
			
		||||
 | 
			
		||||
	  You may want to disable the network support on embedded devices. If
 | 
			
		||||
	  unsure say Y.
 | 
			
		||||
 | 
			
		||||
config DVB_MAX_ADAPTERS
 | 
			
		||||
	int "maximum number of DVB/ATSC adapters"
 | 
			
		||||
	depends on DVB_CORE
 | 
			
		||||
@@ -18,7 +45,7 @@ config DVB_MAX_ADAPTERS
 | 
			
		||||
config DVB_DYNAMIC_MINORS
 | 
			
		||||
	bool "Dynamic DVB minor allocation"
 | 
			
		||||
	depends on DVB_CORE
 | 
			
		||||
	default n
 | 
			
		||||
	default y
 | 
			
		||||
	help
 | 
			
		||||
	  If you say Y here, the DVB subsystem will use dynamic minor
 | 
			
		||||
	  allocation for any device that uses the DVB major number.
 | 
			
		||||
@@ -31,7 +58,6 @@ config DVB_DYNAMIC_MINORS
 | 
			
		||||
config DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
	bool "Enable DVB demux section packet loss log"
 | 
			
		||||
	depends on DVB_CORE
 | 
			
		||||
	default n
 | 
			
		||||
	help
 | 
			
		||||
	  Enable extra log messages meant to detect packet loss
 | 
			
		||||
	  inside the Kernel.
 | 
			
		||||
@@ -40,3 +66,15 @@ config DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
	  be very verbose.
 | 
			
		||||
 | 
			
		||||
	  If you are unsure about this, say N here.
 | 
			
		||||
 | 
			
		||||
config DVB_ULE_DEBUG
 | 
			
		||||
	bool "Enable DVB net ULE packet debug messages"
 | 
			
		||||
	depends on DVB_CORE
 | 
			
		||||
	help
 | 
			
		||||
	  Enable extra log messages meant to detect problems while
 | 
			
		||||
	  handling DVB network ULE packet loss inside the Kernel.
 | 
			
		||||
 | 
			
		||||
	  Should not be enabled on normal cases, as logs can
 | 
			
		||||
	  be very verbose.
 | 
			
		||||
 | 
			
		||||
	  If you are unsure about this, say N here.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,16 @@
 | 
			
		||||
# SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
#
 | 
			
		||||
# Makefile for the kernel DVB device drivers.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
 | 
			
		||||
dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
 | 
			
		||||
dvb-vb2-$(CONFIG_DVB_MMAP) := dvb_vb2.o
 | 
			
		||||
 | 
			
		||||
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o		 	\
 | 
			
		||||
		 dvb_ca_en50221.o dvb_frontend.o 		\
 | 
			
		||||
		 dvb_net.o dvb_ringbuffer.o dvb_math.o
 | 
			
		||||
		 $(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) dvb_math.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_DVB_CORE) += dvb-core.o
 | 
			
		||||
 | 
			
		||||
EXTRA_CFLAGS += -DCONFIG_DVB_DYNAMIC_MINORS -DCONFIG_DVB_NET
 | 
			
		||||
NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/dvb-core
 | 
			
		||||
#NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux
 | 
			
		||||
 
 | 
			
		||||
@@ -9,3 +9,5 @@ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
 | 
			
		||||
		 $(dvb-net-y) dvb_ringbuffer.o dvb_math.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_DVB_CORE) += dvb-core.o
 | 
			
		||||
 | 
			
		||||
ccflags-y += -Idrivers/media/dvb-core/
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
 | 
			
		||||
#define pr_fmt(fmt) "dmxdev: " fmt
 | 
			
		||||
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
@@ -27,8 +28,10 @@
 | 
			
		||||
#include <linux/ioctl.h>
 | 
			
		||||
#include <linux/wait.h>
 | 
			
		||||
#include <linux/uaccess.h>
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include "dmxdev.h"
 | 
			
		||||
#include <media/dmxdev.h>
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
#include <media/dvb_vb2.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int debug;
 | 
			
		||||
 | 
			
		||||
@@ -128,6 +131,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
 | 
			
		||||
	struct dvb_device *dvbdev = file->private_data;
 | 
			
		||||
	struct dmxdev *dmxdev = dvbdev->priv;
 | 
			
		||||
	struct dmx_frontend *front;
 | 
			
		||||
	bool need_ringbuffer = false;
 | 
			
		||||
 | 
			
		||||
	dprintk("%s\n", __func__);
 | 
			
		||||
 | 
			
		||||
@@ -139,14 +143,33 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((file->f_flags & O_ACCMODE) == O_RDWR) {
 | 
			
		||||
	dmxdev->may_do_mmap = 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The logic here is a little tricky due to the ifdef.
 | 
			
		||||
	 *
 | 
			
		||||
	 * The ringbuffer is used for both read and mmap.
 | 
			
		||||
	 *
 | 
			
		||||
	 * It is not needed, however, on two situations:
 | 
			
		||||
	 *	- Write devices (access with O_WRONLY);
 | 
			
		||||
	 *	- For duplex device nodes, opened with O_RDWR.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
 | 
			
		||||
		need_ringbuffer = true;
 | 
			
		||||
	else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
 | 
			
		||||
		if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
			dmxdev->may_do_mmap = 1;
 | 
			
		||||
			need_ringbuffer = true;
 | 
			
		||||
#else
 | 
			
		||||
			mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
			return -EOPNOTSUPP;
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
 | 
			
		||||
	if (need_ringbuffer) {
 | 
			
		||||
		void *mem;
 | 
			
		||||
 | 
			
		||||
		if (!dvbdev->readers) {
 | 
			
		||||
@@ -159,6 +182,11 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		}
 | 
			
		||||
		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
		if (dmxdev->may_do_mmap)
 | 
			
		||||
			dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
 | 
			
		||||
				     file->f_flags & O_NONBLOCK);
 | 
			
		||||
#endif
 | 
			
		||||
		dvbdev->readers--;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -196,7 +224,15 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
 | 
			
		||||
		dmxdev->demux->connect_frontend(dmxdev->demux,
 | 
			
		||||
						dmxdev->dvr_orig_fe);
 | 
			
		||||
	}
 | 
			
		||||
	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
 | 
			
		||||
	if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
 | 
			
		||||
	    dmxdev->may_do_mmap) {
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
		if (dmxdev->may_do_mmap) {
 | 
			
		||||
			if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
 | 
			
		||||
				dvb_vb2_stream_off(&dmxdev->dvr_vb2_ctx);
 | 
			
		||||
			dvb_vb2_release(&dmxdev->dvr_vb2_ctx);
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
		dvbdev->readers++;
 | 
			
		||||
		if (dmxdev->dvr_buffer.data) {
 | 
			
		||||
			void *mem = dmxdev->dvr_buffer.data;
 | 
			
		||||
@@ -381,12 +417,18 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
 | 
			
		||||
#endif
 | 
			
		||||
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
 | 
			
		||||
				       const u8 *buffer2, size_t buffer2_len,
 | 
			
		||||
				       struct dmx_section_filter *filter)
 | 
			
		||||
				       struct dmx_section_filter *filter,
 | 
			
		||||
				       u32 *buffer_flags)
 | 
			
		||||
{
 | 
			
		||||
	struct dmxdev_filter *dmxdevfilter = filter->priv;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	if (!dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx) &&
 | 
			
		||||
	    dmxdevfilter->buffer.error) {
 | 
			
		||||
#else
 | 
			
		||||
	if (dmxdevfilter->buffer.error) {
 | 
			
		||||
#endif
 | 
			
		||||
		wake_up(&dmxdevfilter->buffer.queue);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -397,12 +439,31 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
 | 
			
		||||
	}
 | 
			
		||||
	del_timer(&dmxdevfilter->timer);
 | 
			
		||||
	dprintk("section callback %*ph\n", 6, buffer1);
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx)) {
 | 
			
		||||
		ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
 | 
			
		||||
					  buffer1, buffer1_len,
 | 
			
		||||
					  buffer_flags);
 | 
			
		||||
		if (ret == buffer1_len)
 | 
			
		||||
			ret = dvb_vb2_fill_buffer(&dmxdevfilter->vb2_ctx,
 | 
			
		||||
						  buffer2, buffer2_len,
 | 
			
		||||
						  buffer_flags);
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
 | 
			
		||||
					      buffer1, buffer1_len);
 | 
			
		||||
		if (ret == buffer1_len) {
 | 
			
		||||
			ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer,
 | 
			
		||||
						      buffer2, buffer2_len);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
 | 
			
		||||
				      buffer1_len);
 | 
			
		||||
	if (ret == buffer1_len) {
 | 
			
		||||
		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
 | 
			
		||||
					      buffer2_len);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		dmxdevfilter->buffer.error = ret;
 | 
			
		||||
	if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
 | 
			
		||||
@@ -414,7 +475,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
 | 
			
		||||
 | 
			
		||||
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 | 
			
		||||
				  const u8 *buffer2, size_t buffer2_len,
 | 
			
		||||
				  struct dmx_ts_feed *feed)
 | 
			
		||||
				       struct dmx_ts_feed *feed,
 | 
			
		||||
				       u32 *buffer_flags)
 | 
			
		||||
{
 | 
			
		||||
	struct dmxdev_filter *dmxdevfilter = feed->priv;
 | 
			
		||||
	struct dvb_ringbuffer *buffer;
 | 
			
		||||
@@ -426,11 +488,28 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
 | 
			
		||||
	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
 | 
			
		||||
	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP ||
 | 
			
		||||
	    dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
 | 
			
		||||
		buffer = &dmxdevfilter->buffer;
 | 
			
		||||
	else
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
		ctx = &dmxdevfilter->vb2_ctx;
 | 
			
		||||
#endif
 | 
			
		||||
	} else {
 | 
			
		||||
		buffer = &dmxdevfilter->dev->dvr_buffer;
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
		ctx = &dmxdevfilter->dev->dvr_vb2_ctx;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	if (dvb_vb2_is_streaming(ctx)) {
 | 
			
		||||
		ret = dvb_vb2_fill_buffer(ctx, buffer1, buffer1_len,
 | 
			
		||||
					  buffer_flags);
 | 
			
		||||
		if (ret == buffer1_len)
 | 
			
		||||
			ret = dvb_vb2_fill_buffer(ctx, buffer2, buffer2_len,
 | 
			
		||||
						  buffer_flags);
 | 
			
		||||
	} else {
 | 
			
		||||
#endif
 | 
			
		||||
		if (buffer->error) {
 | 
			
		||||
			spin_unlock(&dmxdevfilter->dev->lock);
 | 
			
		||||
			wake_up(&buffer->queue);
 | 
			
		||||
@@ -438,7 +517,11 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
 | 
			
		||||
		}
 | 
			
		||||
		ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
 | 
			
		||||
		if (ret == buffer1_len)
 | 
			
		||||
		ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
 | 
			
		||||
			ret = dvb_dmxdev_buffer_write(buffer,
 | 
			
		||||
						      buffer2, buffer2_len);
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		buffer->error = ret;
 | 
			
		||||
	spin_unlock(&dmxdevfilter->dev->lock);
 | 
			
		||||
@@ -585,7 +668,7 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
 | 
			
		||||
				 struct dmxdev_filter *filter,
 | 
			
		||||
				 struct dmxdev_feed *feed)
 | 
			
		||||
{
 | 
			
		||||
	ktime_t timeout;
 | 
			
		||||
	ktime_t timeout = ktime_set(0, 0);
 | 
			
		||||
	struct dmx_pes_filter_params *para = &filter->params.pes;
 | 
			
		||||
	enum dmx_output otype;
 | 
			
		||||
	int ret;
 | 
			
		||||
@@ -593,7 +676,6 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
 | 
			
		||||
	enum dmx_ts_pes ts_pes;
 | 
			
		||||
	struct dmx_ts_feed *tsfeed;
 | 
			
		||||
 | 
			
		||||
	timeout = ktime_set(0, 0);
 | 
			
		||||
	feed->ts = NULL;
 | 
			
		||||
	otype = para->output;
 | 
			
		||||
 | 
			
		||||
@@ -777,7 +859,17 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
 | 
			
		||||
	mutex_init(&dmxdevfilter->mutex);
 | 
			
		||||
	file->private_data = dmxdevfilter;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	dmxdev->may_do_mmap = 1;
 | 
			
		||||
#else
 | 
			
		||||
	dmxdev->may_do_mmap = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	dvb_vb2_init(&dmxdevfilter->vb2_ctx, "demux_filter",
 | 
			
		||||
		     file->f_flags & O_NONBLOCK);
 | 
			
		||||
#endif
 | 
			
		||||
	dmxdevfilter->type = DMXDEV_TYPE_NONE;
 | 
			
		||||
	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
 | 
			
		||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
 | 
			
		||||
@@ -797,6 +889,11 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
 | 
			
		||||
{
 | 
			
		||||
	mutex_lock(&dmxdev->mutex);
 | 
			
		||||
	mutex_lock(&dmxdevfilter->mutex);
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
 | 
			
		||||
		dvb_vb2_stream_off(&dmxdevfilter->vb2_ctx);
 | 
			
		||||
	dvb_vb2_release(&dmxdevfilter->vb2_ctx);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	dvb_dmxdev_filter_stop(dmxdevfilter);
 | 
			
		||||
	dvb_dmxdev_filter_reset(dmxdevfilter);
 | 
			
		||||
@@ -1084,8 +1181,56 @@ static int dvb_demux_do_ioctl(struct file *file,
 | 
			
		||||
		mutex_unlock(&dmxdevfilter->mutex);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	case DMX_REQBUFS:
 | 
			
		||||
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 | 
			
		||||
			mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
			return -ERESTARTSYS;
 | 
			
		||||
		}
 | 
			
		||||
		ret = dvb_vb2_reqbufs(&dmxdevfilter->vb2_ctx, parg);
 | 
			
		||||
		mutex_unlock(&dmxdevfilter->mutex);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DMX_QUERYBUF:
 | 
			
		||||
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 | 
			
		||||
			mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
			return -ERESTARTSYS;
 | 
			
		||||
		}
 | 
			
		||||
		ret = dvb_vb2_querybuf(&dmxdevfilter->vb2_ctx, parg);
 | 
			
		||||
		mutex_unlock(&dmxdevfilter->mutex);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DMX_EXPBUF:
 | 
			
		||||
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 | 
			
		||||
			mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
			return -ERESTARTSYS;
 | 
			
		||||
		}
 | 
			
		||||
		ret = dvb_vb2_expbuf(&dmxdevfilter->vb2_ctx, parg);
 | 
			
		||||
		mutex_unlock(&dmxdevfilter->mutex);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DMX_QBUF:
 | 
			
		||||
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 | 
			
		||||
			mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
			return -ERESTARTSYS;
 | 
			
		||||
		}
 | 
			
		||||
		ret = dvb_vb2_qbuf(&dmxdevfilter->vb2_ctx, parg);
 | 
			
		||||
		if (ret == 0 && !dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
 | 
			
		||||
			ret = dvb_vb2_stream_on(&dmxdevfilter->vb2_ctx);
 | 
			
		||||
		mutex_unlock(&dmxdevfilter->mutex);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DMX_DQBUF:
 | 
			
		||||
		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 | 
			
		||||
			mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
			return -ERESTARTSYS;
 | 
			
		||||
		}
 | 
			
		||||
		ret = dvb_vb2_dqbuf(&dmxdevfilter->vb2_ctx, parg);
 | 
			
		||||
		mutex_unlock(&dmxdevfilter->mutex);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	default:
 | 
			
		||||
		ret = -EINVAL;
 | 
			
		||||
		ret = -ENOTTY;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
@@ -1098,30 +1243,70 @@ static long dvb_demux_ioctl(struct file *file, unsigned int cmd,
 | 
			
		||||
	return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
 | 
			
		||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0))
 | 
			
		||||
typedef unsigned int __poll_t;
 | 
			
		||||
#define EPOLLIN POLLIN
 | 
			
		||||
#define EPOLLERR POLLERR
 | 
			
		||||
#define EPOLLPRI POLLPRI
 | 
			
		||||
#define EPOLLRDNORM POLLRDNORM
 | 
			
		||||
#define EPOLLWRNORM POLLWRNORM
 | 
			
		||||
#define EPOLLOUT POLLOUT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static __poll_t dvb_demux_poll(struct file *file, poll_table *wait)
 | 
			
		||||
{
 | 
			
		||||
	struct dmxdev_filter *dmxdevfilter = file->private_data;
 | 
			
		||||
	unsigned int mask = 0;
 | 
			
		||||
 | 
			
		||||
	if ((!dmxdevfilter) || dmxdevfilter->dev->exit)
 | 
			
		||||
		return POLLERR;
 | 
			
		||||
	__poll_t mask = 0;
 | 
			
		||||
 | 
			
		||||
	poll_wait(file, &dmxdevfilter->buffer.queue, wait);
 | 
			
		||||
 | 
			
		||||
	if ((!dmxdevfilter) || dmxdevfilter->dev->exit)
 | 
			
		||||
		return EPOLLERR;
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	if (dvb_vb2_is_streaming(&dmxdevfilter->vb2_ctx))
 | 
			
		||||
		return dvb_vb2_poll(&dmxdevfilter->vb2_ctx, file, wait);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (dmxdevfilter->state != DMXDEV_STATE_GO &&
 | 
			
		||||
	    dmxdevfilter->state != DMXDEV_STATE_DONE &&
 | 
			
		||||
	    dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (dmxdevfilter->buffer.error)
 | 
			
		||||
		mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
 | 
			
		||||
		mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
 | 
			
		||||
 | 
			
		||||
	if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer))
 | 
			
		||||
		mask |= (POLLIN | POLLRDNORM | POLLPRI);
 | 
			
		||||
		mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI);
 | 
			
		||||
 | 
			
		||||
	return mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
static int dvb_demux_mmap(struct file *file, struct vm_area_struct *vma)
 | 
			
		||||
{
 | 
			
		||||
	struct dmxdev_filter *dmxdevfilter = file->private_data;
 | 
			
		||||
	struct dmxdev *dmxdev = dmxdevfilter->dev;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (!dmxdev->may_do_mmap)
 | 
			
		||||
		return -ENOTTY;
 | 
			
		||||
 | 
			
		||||
	if (mutex_lock_interruptible(&dmxdev->mutex))
 | 
			
		||||
		return -ERESTARTSYS;
 | 
			
		||||
 | 
			
		||||
	if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
 | 
			
		||||
		mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
		return -ERESTARTSYS;
 | 
			
		||||
	}
 | 
			
		||||
	ret = dvb_vb2_mmap(&dmxdevfilter->vb2_ctx, vma);
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&dmxdevfilter->mutex);
 | 
			
		||||
	mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int dvb_demux_release(struct inode *inode, struct file *file)
 | 
			
		||||
{
 | 
			
		||||
	struct dmxdev_filter *dmxdevfilter = file->private_data;
 | 
			
		||||
@@ -1146,10 +1331,14 @@ static const struct file_operations dvb_demux_fops = {
 | 
			
		||||
	.owner = THIS_MODULE,
 | 
			
		||||
	.read = dvb_demux_read,
 | 
			
		||||
	.unlocked_ioctl = dvb_demux_ioctl,
 | 
			
		||||
	.compat_ioctl = dvb_demux_ioctl,
 | 
			
		||||
	.open = dvb_demux_open,
 | 
			
		||||
	.release = dvb_demux_release,
 | 
			
		||||
	.poll = dvb_demux_poll,
 | 
			
		||||
	.llseek = default_llseek,
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	.mmap = dvb_demux_mmap,
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct dvb_device dvbdev_demux = {
 | 
			
		||||
@@ -1178,8 +1367,31 @@ static int dvb_dvr_do_ioctl(struct file *file,
 | 
			
		||||
		ret = dvb_dvr_set_buffer_size(dmxdev, arg);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	case DMX_REQBUFS:
 | 
			
		||||
		ret = dvb_vb2_reqbufs(&dmxdev->dvr_vb2_ctx, parg);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DMX_QUERYBUF:
 | 
			
		||||
		ret = dvb_vb2_querybuf(&dmxdev->dvr_vb2_ctx, parg);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DMX_EXPBUF:
 | 
			
		||||
		ret = dvb_vb2_expbuf(&dmxdev->dvr_vb2_ctx, parg);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DMX_QBUF:
 | 
			
		||||
		ret = dvb_vb2_qbuf(&dmxdev->dvr_vb2_ctx, parg);
 | 
			
		||||
		if (ret == 0 && !dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
 | 
			
		||||
			ret = dvb_vb2_stream_on(&dmxdev->dvr_vb2_ctx);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case DMX_DQBUF:
 | 
			
		||||
		ret = dvb_vb2_dqbuf(&dmxdev->dvr_vb2_ctx, parg);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	default:
 | 
			
		||||
		ret = -EINVAL;
 | 
			
		||||
		ret = -ENOTTY;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
@@ -1192,31 +1404,58 @@ static long dvb_dvr_ioctl(struct file *file,
 | 
			
		||||
	return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
 | 
			
		||||
static __poll_t dvb_dvr_poll(struct file *file, poll_table *wait)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_device *dvbdev = file->private_data;
 | 
			
		||||
	struct dmxdev *dmxdev = dvbdev->priv;
 | 
			
		||||
	unsigned int mask = 0;
 | 
			
		||||
	__poll_t mask = 0;
 | 
			
		||||
 | 
			
		||||
	dprintk("%s\n", __func__);
 | 
			
		||||
 | 
			
		||||
	if (dmxdev->exit)
 | 
			
		||||
		return POLLERR;
 | 
			
		||||
 | 
			
		||||
	poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
 | 
			
		||||
 | 
			
		||||
	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
 | 
			
		||||
	if (dmxdev->exit)
 | 
			
		||||
		return EPOLLERR;
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	if (dvb_vb2_is_streaming(&dmxdev->dvr_vb2_ctx))
 | 
			
		||||
		return dvb_vb2_poll(&dmxdev->dvr_vb2_ctx, file, wait);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
 | 
			
		||||
	    dmxdev->may_do_mmap) {
 | 
			
		||||
		if (dmxdev->dvr_buffer.error)
 | 
			
		||||
			mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
 | 
			
		||||
			mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI | EPOLLERR);
 | 
			
		||||
 | 
			
		||||
		if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer))
 | 
			
		||||
			mask |= (POLLIN | POLLRDNORM | POLLPRI);
 | 
			
		||||
			mask |= (EPOLLIN | EPOLLRDNORM | EPOLLPRI);
 | 
			
		||||
	} else
 | 
			
		||||
		mask |= (POLLOUT | POLLWRNORM | POLLPRI);
 | 
			
		||||
		mask |= (EPOLLOUT | EPOLLWRNORM | EPOLLPRI);
 | 
			
		||||
 | 
			
		||||
	return mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
static int dvb_dvr_mmap(struct file *file, struct vm_area_struct *vma)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_device *dvbdev = file->private_data;
 | 
			
		||||
	struct dmxdev *dmxdev = dvbdev->priv;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (!dmxdev->may_do_mmap)
 | 
			
		||||
		return -ENOTTY;
 | 
			
		||||
 | 
			
		||||
	if (dmxdev->exit)
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
 | 
			
		||||
	if (mutex_lock_interruptible(&dmxdev->mutex))
 | 
			
		||||
		return -ERESTARTSYS;
 | 
			
		||||
 | 
			
		||||
	ret = dvb_vb2_mmap(&dmxdev->dvr_vb2_ctx, vma);
 | 
			
		||||
	mutex_unlock(&dmxdev->mutex);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static const struct file_operations dvb_dvr_fops = {
 | 
			
		||||
	.owner = THIS_MODULE,
 | 
			
		||||
	.read = dvb_dvr_read,
 | 
			
		||||
@@ -1226,6 +1465,9 @@ static const struct file_operations dvb_dvr_fops = {
 | 
			
		||||
	.release = dvb_dvr_release,
 | 
			
		||||
	.poll = dvb_dvr_poll,
 | 
			
		||||
	.llseek = default_llseek,
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	.mmap = dvb_dvr_mmap,
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct dvb_device dvbdev_dvr = {
 | 
			
		||||
@@ -1237,6 +1479,7 @@ static const struct dvb_device dvbdev_dvr = {
 | 
			
		||||
#endif
 | 
			
		||||
	.fops = &dvb_dvr_fops
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
@@ -1244,7 +1487,12 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
 | 
			
		||||
	if (dmxdev->demux->open(dmxdev->demux) < 0)
 | 
			
		||||
		return -EUSERS;
 | 
			
		||||
 | 
			
		||||
	dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter));
 | 
			
		||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0))
 | 
			
		||||
	dmxdev->filter = vmalloc(sizeof(struct dmxdev_filter) * dmxdev->filternum);
 | 
			
		||||
#else
 | 
			
		||||
	dmxdev->filter = vmalloc(array_size(sizeof(struct dmxdev_filter),
 | 
			
		||||
					    dmxdev->filternum));
 | 
			
		||||
#endif
 | 
			
		||||
	if (!dmxdev->filter)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,115 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * dmxdev.h
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
 | 
			
		||||
 *                    for convergence integrated media GmbH
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2.1
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _DMXDEV_H_
 | 
			
		||||
#define _DMXDEV_H_
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/time.h>
 | 
			
		||||
#include <linux/timer.h>
 | 
			
		||||
#include <linux/wait.h>
 | 
			
		||||
#include <linux/fs.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/dvb/dmx.h>
 | 
			
		||||
 | 
			
		||||
#include "dvbdev.h"
 | 
			
		||||
#include "demux.h"
 | 
			
		||||
#include "dvb_ringbuffer.h"
 | 
			
		||||
 | 
			
		||||
enum dmxdev_type {
 | 
			
		||||
	DMXDEV_TYPE_NONE,
 | 
			
		||||
	DMXDEV_TYPE_SEC,
 | 
			
		||||
	DMXDEV_TYPE_PES,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum dmxdev_state {
 | 
			
		||||
	DMXDEV_STATE_FREE,
 | 
			
		||||
	DMXDEV_STATE_ALLOCATED,
 | 
			
		||||
	DMXDEV_STATE_SET,
 | 
			
		||||
	DMXDEV_STATE_GO,
 | 
			
		||||
	DMXDEV_STATE_DONE,
 | 
			
		||||
	DMXDEV_STATE_TIMEDOUT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct dmxdev_feed {
 | 
			
		||||
	u16 pid;
 | 
			
		||||
	struct dmx_ts_feed *ts;
 | 
			
		||||
	struct list_head next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct dmxdev_filter {
 | 
			
		||||
	union {
 | 
			
		||||
		struct dmx_section_filter *sec;
 | 
			
		||||
	} filter;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		/* list of TS and PES feeds (struct dmxdev_feed) */
 | 
			
		||||
		struct list_head ts;
 | 
			
		||||
		struct dmx_section_feed *sec;
 | 
			
		||||
	} feed;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct dmx_sct_filter_params sec;
 | 
			
		||||
		struct dmx_pes_filter_params pes;
 | 
			
		||||
	} params;
 | 
			
		||||
 | 
			
		||||
	enum dmxdev_type type;
 | 
			
		||||
	enum dmxdev_state state;
 | 
			
		||||
	struct dmxdev *dev;
 | 
			
		||||
	struct dvb_ringbuffer buffer;
 | 
			
		||||
 | 
			
		||||
	struct mutex mutex;
 | 
			
		||||
 | 
			
		||||
	/* only for sections */
 | 
			
		||||
	struct timer_list timer;
 | 
			
		||||
	int todo;
 | 
			
		||||
	u8 secheader[3];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct dmxdev {
 | 
			
		||||
	struct dvb_device *dvbdev;
 | 
			
		||||
	struct dvb_device *dvr_dvbdev;
 | 
			
		||||
 | 
			
		||||
	struct dmxdev_filter *filter;
 | 
			
		||||
	struct dmx_demux *demux;
 | 
			
		||||
 | 
			
		||||
	int filternum;
 | 
			
		||||
	int capabilities;
 | 
			
		||||
 | 
			
		||||
	unsigned int exit:1;
 | 
			
		||||
#define DMXDEV_CAP_DUPLEX 1
 | 
			
		||||
	struct dmx_frontend *dvr_orig_fe;
 | 
			
		||||
 | 
			
		||||
	struct dvb_ringbuffer dvr_buffer;
 | 
			
		||||
#define DVR_BUFFER_SIZE (10*188*1024)
 | 
			
		||||
 | 
			
		||||
	struct mutex mutex;
 | 
			
		||||
	spinlock_t lock;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *);
 | 
			
		||||
void dvb_dmxdev_release(struct dmxdev *dmxdev);
 | 
			
		||||
 | 
			
		||||
#endif /* _DMXDEV_H_ */
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
 // SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
/*
 | 
			
		||||
 * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces
 | 
			
		||||
 *
 | 
			
		||||
@@ -11,18 +12,6 @@
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 1999-2002 Ralph  Metzler
 | 
			
		||||
 *                       & Marcus Metzler for convergence integrated media GmbH
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 * To obtain the license, point your browser to
 | 
			
		||||
 * http://www.gnu.org/copyleft/gpl.html
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define pr_fmt(fmt) "dvb_ca_en50221: " fmt
 | 
			
		||||
@@ -31,10 +20,13 @@
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/list.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
 | 
			
		||||
#include <linux/nospec.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <linux/vmalloc.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
 | 
			
		||||
#include <linux/sched/signal.h>
 | 
			
		||||
#else
 | 
			
		||||
@@ -42,8 +34,8 @@
 | 
			
		||||
#endif
 | 
			
		||||
#include <linux/kthread.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_ca_en50221.h"
 | 
			
		||||
#include "dvb_ringbuffer.h"
 | 
			
		||||
#include <media/dvb_ca_en50221.h>
 | 
			
		||||
#include <media/dvb_ringbuffer.h>
 | 
			
		||||
 | 
			
		||||
static int dvb_ca_en50221_debug;
 | 
			
		||||
 | 
			
		||||
@@ -211,7 +203,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
 | 
			
		||||
 * @hlen: Number of bytes in haystack.
 | 
			
		||||
 * @needle: Buffer to find.
 | 
			
		||||
 * @nlen: Number of bytes in needle.
 | 
			
		||||
 * @return Pointer into haystack needle was found at, or NULL if not found.
 | 
			
		||||
 * return: Pointer into haystack needle was found at, or NULL if not found.
 | 
			
		||||
 */
 | 
			
		||||
static char *findstr(char *haystack, int hlen, char *needle, int nlen)
 | 
			
		||||
{
 | 
			
		||||
@@ -231,7 +223,7 @@ static char *findstr(char *haystack, int hlen, char *needle, int nlen)
 | 
			
		||||
/* ************************************************************************** */
 | 
			
		||||
/* EN50221 physical interface functions */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
/*
 | 
			
		||||
 * dvb_ca_en50221_check_camstatus - Check CAM status.
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot)
 | 
			
		||||
@@ -280,9 +272,9 @@ static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot)
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @slot: Slot on interface.
 | 
			
		||||
 * @waitfor: Flags to wait for.
 | 
			
		||||
 * @timeout_ms: Timeout in milliseconds.
 | 
			
		||||
 * @timeout_hz: Timeout in milliseconds.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 on success, nonzero on error.
 | 
			
		||||
 * return: 0 on success, nonzero on error.
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
 | 
			
		||||
					 u8 waitfor, int timeout_hz)
 | 
			
		||||
@@ -330,7 +322,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @slot: Slot id.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 on success, nonzero on failure.
 | 
			
		||||
 * return: 0 on success, nonzero on failure.
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
 | 
			
		||||
{
 | 
			
		||||
@@ -402,11 +394,11 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @slot: Slot id.
 | 
			
		||||
 * @address: Address to read from. Updated.
 | 
			
		||||
 * @tupleType: Tuple id byte. Updated.
 | 
			
		||||
 * @tupleLength: Tuple length. Updated.
 | 
			
		||||
 * @tuple_type: Tuple id byte. Updated.
 | 
			
		||||
 * @tuple_length: Tuple length. Updated.
 | 
			
		||||
 * @tuple: Dest buffer for tuple (must be 256 bytes). Updated.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 on success, nonzero on error.
 | 
			
		||||
 * return: 0 on success, nonzero on error.
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot,
 | 
			
		||||
				     int *address, int *tuple_type,
 | 
			
		||||
@@ -460,7 +452,7 @@ static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot,
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @slot: Slot id.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 on success, <0 on failure.
 | 
			
		||||
 * return: 0 on success, <0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot)
 | 
			
		||||
{
 | 
			
		||||
@@ -637,10 +629,11 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @slot: Slot to read from.
 | 
			
		||||
 * @ebuf: If non-NULL, the data will be written to this buffer. If NULL,
 | 
			
		||||
 * the data will be added into the buffering system as a normal fragment.
 | 
			
		||||
 *        the data will be added into the buffering system as a normal
 | 
			
		||||
 *        fragment.
 | 
			
		||||
 * @ecount: Size of ebuf. Ignored if ebuf is NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Number of bytes read, or < 0 on error
 | 
			
		||||
 * return: Number of bytes read, or < 0 on error
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
 | 
			
		||||
				    u8 *ebuf, int ecount)
 | 
			
		||||
@@ -789,11 +782,11 @@ exit:
 | 
			
		||||
 *
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @slot: Slot to write to.
 | 
			
		||||
 * @ebuf: The data in this buffer is treated as a complete link-level packet to
 | 
			
		||||
 * @buf: The data in this buffer is treated as a complete link-level packet to
 | 
			
		||||
 * be written.
 | 
			
		||||
 * @count: Size of ebuf.
 | 
			
		||||
 * @bytes_write: Size of ebuf.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Number of bytes written, or < 0 on error.
 | 
			
		||||
 * return: Number of bytes written, or < 0 on error.
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
 | 
			
		||||
				     u8 *buf, int bytes_write)
 | 
			
		||||
@@ -938,7 +931,7 @@ static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot)
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_ca_en50221_camchange_irq - A CAMCHANGE IRQ has occurred.
 | 
			
		||||
 *
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @pubca: CA instance.
 | 
			
		||||
 * @slot: Slot concerned.
 | 
			
		||||
 * @change_type: One of the DVB_CA_CAMCHANGE_* values.
 | 
			
		||||
 */
 | 
			
		||||
@@ -968,7 +961,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_ca_en50221_camready_irq - A CAMREADY IRQ has occurred.
 | 
			
		||||
 *
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @pubca: CA instance.
 | 
			
		||||
 * @slot: Slot concerned.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot)
 | 
			
		||||
@@ -988,7 +981,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camready_irq);
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_ca_en50221_frda_irq - An FR or DA IRQ has occurred.
 | 
			
		||||
 *
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @pubca: CA instance.
 | 
			
		||||
 * @slot: Slot concerned.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
 | 
			
		||||
@@ -1096,7 +1089,7 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
 | 
			
		||||
 *
 | 
			
		||||
 * @ca: CA instance.
 | 
			
		||||
 * @slot: Slot to process.
 | 
			
		||||
 * @return: 0 .. no change
 | 
			
		||||
 * return:: 0 .. no change
 | 
			
		||||
 *          1 .. CAM state changed
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -1274,7 +1267,7 @@ static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca,
 | 
			
		||||
		ca->pub->slot_ts_enable(ca->pub, slot);
 | 
			
		||||
		sl->slot_state = DVB_CA_SLOTSTATE_RUNNING;
 | 
			
		||||
		dvb_ca_en50221_thread_update_delay(ca);
 | 
			
		||||
		pr_err("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n",
 | 
			
		||||
		pr_info("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n",
 | 
			
		||||
		       ca->dvbdev->adapter->num);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
@@ -1317,7 +1310,7 @@ static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca,
 | 
			
		||||
	mutex_unlock(&sl->slot_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
/*
 | 
			
		||||
 * Kernel thread which monitors CA slots for CAM changes, and performs data
 | 
			
		||||
 * transfers.
 | 
			
		||||
 */
 | 
			
		||||
@@ -1357,12 +1350,11 @@ static int dvb_ca_en50221_thread(void *data)
 | 
			
		||||
 * Real ioctl implementation.
 | 
			
		||||
 * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them.
 | 
			
		||||
 *
 | 
			
		||||
 * @inode: Inode concerned.
 | 
			
		||||
 * @file: File concerned.
 | 
			
		||||
 * @cmd: IOCTL command.
 | 
			
		||||
 * @arg: Associated argument.
 | 
			
		||||
 * @parg: Associated argument.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 on success, <0 on error.
 | 
			
		||||
 * return: 0 on success, <0 on error.
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_io_do_ioctl(struct file *file,
 | 
			
		||||
				      unsigned int cmd, void *parg)
 | 
			
		||||
@@ -1411,7 +1403,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file,
 | 
			
		||||
		struct dvb_ca_slot *sl;
 | 
			
		||||
 | 
			
		||||
		slot = info->num;
 | 
			
		||||
		if ((slot > ca->slot_count) || (slot < 0)) {
 | 
			
		||||
		if ((slot >= ca->slot_count) || (slot < 0)) {
 | 
			
		||||
			err = -EINVAL;
 | 
			
		||||
			goto out_unlock;
 | 
			
		||||
		}
 | 
			
		||||
@@ -1441,12 +1433,11 @@ out_unlock:
 | 
			
		||||
/**
 | 
			
		||||
 * Wrapper for ioctl implementation.
 | 
			
		||||
 *
 | 
			
		||||
 * @inode: Inode concerned.
 | 
			
		||||
 * @file: File concerned.
 | 
			
		||||
 * @cmd: IOCTL command.
 | 
			
		||||
 * @arg: Associated argument.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 on success, <0 on error.
 | 
			
		||||
 * return: 0 on success, <0 on error.
 | 
			
		||||
 */
 | 
			
		||||
static long dvb_ca_en50221_io_ioctl(struct file *file,
 | 
			
		||||
				    unsigned int cmd, unsigned long arg)
 | 
			
		||||
@@ -1462,7 +1453,7 @@ static long dvb_ca_en50221_io_ioctl(struct file *file,
 | 
			
		||||
 * @count: Size of source buffer.
 | 
			
		||||
 * @ppos: Position in file (ignored).
 | 
			
		||||
 *
 | 
			
		||||
 * @return Number of bytes read, or <0 on error.
 | 
			
		||||
 * return: Number of bytes read, or <0 on error.
 | 
			
		||||
 */
 | 
			
		||||
static ssize_t dvb_ca_en50221_io_write(struct file *file,
 | 
			
		||||
				       const char __user *buf, size_t count,
 | 
			
		||||
@@ -1495,6 +1486,11 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
 | 
			
		||||
		return -EFAULT;
 | 
			
		||||
	buf += 2;
 | 
			
		||||
	count -= 2;
 | 
			
		||||
	if (slot >= ca->slot_count)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
 | 
			
		||||
	slot = array_index_nospec(slot, ca->slot_count);
 | 
			
		||||
#endif
 | 
			
		||||
	sl = &ca->slot_info[slot];
 | 
			
		||||
 | 
			
		||||
	/* check if the slot is actually running */
 | 
			
		||||
@@ -1557,7 +1553,7 @@ exit:
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
/*
 | 
			
		||||
 * Condition for waking up in dvb_ca_en50221_io_read_condition
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca,
 | 
			
		||||
@@ -1614,7 +1610,7 @@ nextslot:
 | 
			
		||||
 * @count: Size of destination buffer.
 | 
			
		||||
 * @ppos: Position in file (ignored).
 | 
			
		||||
 *
 | 
			
		||||
 * @return Number of bytes read, or <0 on error.
 | 
			
		||||
 * return: Number of bytes read, or <0 on error.
 | 
			
		||||
 */
 | 
			
		||||
static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf,
 | 
			
		||||
				      size_t count, loff_t *ppos)
 | 
			
		||||
@@ -1723,7 +1719,7 @@ exit:
 | 
			
		||||
 * @inode: Inode concerned.
 | 
			
		||||
 * @file: File concerned.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 on success, <0 on failure.
 | 
			
		||||
 * return: 0 on success, <0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
 | 
			
		||||
{
 | 
			
		||||
@@ -1773,7 +1769,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
 | 
			
		||||
 * @inode: Inode concerned.
 | 
			
		||||
 * @file: File concerned.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 on success, <0 on failure.
 | 
			
		||||
 * return: 0 on success, <0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
 | 
			
		||||
{
 | 
			
		||||
@@ -1802,30 +1798,33 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
 | 
			
		||||
 * @file: File concerned.
 | 
			
		||||
 * @wait: poll wait table.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Standard poll mask.
 | 
			
		||||
 * return: Standard poll mask.
 | 
			
		||||
 */
 | 
			
		||||
static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait)
 | 
			
		||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0))
 | 
			
		||||
typedef unsigned int __poll_t;
 | 
			
		||||
#define EPOLLIN POLLIN
 | 
			
		||||
#endif
 | 
			
		||||
static __poll_t dvb_ca_en50221_io_poll(struct file *file, poll_table *wait)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_device *dvbdev = file->private_data;
 | 
			
		||||
	struct dvb_ca_private *ca = dvbdev->priv;
 | 
			
		||||
	unsigned int mask = 0;
 | 
			
		||||
	__poll_t mask = 0;
 | 
			
		||||
	int slot;
 | 
			
		||||
	int result = 0;
 | 
			
		||||
 | 
			
		||||
	dprintk("%s\n", __func__);
 | 
			
		||||
 | 
			
		||||
	poll_wait(file, &ca->wait_queue, wait);
 | 
			
		||||
 | 
			
		||||
	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1)
 | 
			
		||||
		mask |= POLLIN;
 | 
			
		||||
		mask |= EPOLLIN;
 | 
			
		||||
 | 
			
		||||
	/* if there is something, return now */
 | 
			
		||||
	if (mask)
 | 
			
		||||
		return mask;
 | 
			
		||||
 | 
			
		||||
	/* wait for something to happen */
 | 
			
		||||
	poll_wait(file, &ca->wait_queue, wait);
 | 
			
		||||
 | 
			
		||||
	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1)
 | 
			
		||||
		mask |= POLLIN;
 | 
			
		||||
		mask |= EPOLLIN;
 | 
			
		||||
 | 
			
		||||
	return mask;
 | 
			
		||||
}
 | 
			
		||||
@@ -1859,11 +1858,11 @@ static const struct dvb_device dvbdev_ca = {
 | 
			
		||||
 * Initialise a new DVB CA EN50221 interface device.
 | 
			
		||||
 *
 | 
			
		||||
 * @dvb_adapter: DVB adapter to attach the new CA device to.
 | 
			
		||||
 * @ca: The dvb_ca instance.
 | 
			
		||||
 * @pubca: The dvb_ca instance.
 | 
			
		||||
 * @flags: Flags describing the CA device (DVB_CA_FLAG_*).
 | 
			
		||||
 * @slot_count: Number of slots supported.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 0 on success, nonzero on failure
 | 
			
		||||
 * return: 0 on success, nonzero on failure
 | 
			
		||||
 */
 | 
			
		||||
int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
 | 
			
		||||
			struct dvb_ca_en50221 *pubca, int flags, int slot_count)
 | 
			
		||||
@@ -1950,8 +1949,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_init);
 | 
			
		||||
/**
 | 
			
		||||
 * Release a DVB CA EN50221 interface device.
 | 
			
		||||
 *
 | 
			
		||||
 * @ca_dev: The dvb_device_t instance for the CA device.
 | 
			
		||||
 * @ca: The associated dvb_ca instance.
 | 
			
		||||
 * @pubca: The associated dvb_ca instance.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@
 | 
			
		||||
#include <linux/uaccess.h>
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_demux.h"
 | 
			
		||||
#include <media/dvb_demux.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
 | 
			
		||||
@@ -68,6 +68,17 @@ MODULE_PARM_DESC(dvb_demux_feed_err_pkts,
 | 
			
		||||
		dprintk(x);				\
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
#  define dprintk_sect_loss(x...) dprintk(x)
 | 
			
		||||
#else
 | 
			
		||||
#  define dprintk_sect_loss(x...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define set_buf_flags(__feed, __flag)			\
 | 
			
		||||
	do {						\
 | 
			
		||||
		(__feed)->buffer_flags |= (__flag);	\
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 * static inlined helper functions
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
@@ -117,30 +128,30 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
 | 
			
		||||
{
 | 
			
		||||
	int count = payload(buf);
 | 
			
		||||
	int p;
 | 
			
		||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
	int ccok;
 | 
			
		||||
	u8 cc;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (count == 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	p = 188 - count;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
	cc = buf[3] & 0x0f;
 | 
			
		||||
	ccok = ((feed->cc + 1) & 0x0f) == cc;
 | 
			
		||||
	feed->cc = cc;
 | 
			
		||||
	if (!ccok)
 | 
			
		||||
		dprintk("missed packet!\n");
 | 
			
		||||
#endif
 | 
			
		||||
	if (!ccok) {
 | 
			
		||||
		set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
 | 
			
		||||
		dprintk_sect_loss("missed packet: %d instead of %d!\n",
 | 
			
		||||
				  cc, (feed->cc + 1) & 0x0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (buf[1] & 0x40)	// PUSI ?
 | 
			
		||||
		feed->peslen = 0xfffa;
 | 
			
		||||
 | 
			
		||||
	feed->peslen += count;
 | 
			
		||||
 | 
			
		||||
	return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts);
 | 
			
		||||
	return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts,
 | 
			
		||||
			   &feed->buffer_flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
 | 
			
		||||
@@ -162,7 +173,7 @@ static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
 | 
			
		||||
			    NULL, 0, &f->filter);
 | 
			
		||||
			    NULL, 0, &f->filter, &feed->buffer_flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
 | 
			
		||||
@@ -181,9 +192,11 @@ static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
 | 
			
		||||
	if (sec->check_crc) {
 | 
			
		||||
		section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0);
 | 
			
		||||
		if (section_syntax_indicator &&
 | 
			
		||||
		    demux->check_crc32(feed, sec->secbuf, sec->seclen))
 | 
			
		||||
		    demux->check_crc32(feed, sec->secbuf, sec->seclen)) {
 | 
			
		||||
			set_buf_flags(feed, DMX_BUFFER_FLAG_HAD_CRC32_DISCARD);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0)
 | 
			
		||||
@@ -199,9 +212,8 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
 | 
			
		||||
{
 | 
			
		||||
	struct dmx_section_feed *sec = &feed->feed.sec;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
	if (sec->secbufp < sec->tsfeedp) {
 | 
			
		||||
		int i, n = sec->tsfeedp - sec->secbufp;
 | 
			
		||||
		int n = sec->tsfeedp - sec->secbufp;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Section padding is done with 0xff bytes entirely.
 | 
			
		||||
@@ -209,15 +221,13 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
 | 
			
		||||
		 * but just first and last.
 | 
			
		||||
		 */
 | 
			
		||||
		if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
 | 
			
		||||
			dprintk("dvb_demux.c section ts padding loss: %d/%d\n",
 | 
			
		||||
			set_buf_flags(feed,
 | 
			
		||||
				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
 | 
			
		||||
			dprintk_sect_loss("section ts padding loss: %d/%d\n",
 | 
			
		||||
					  n, sec->tsfeedp);
 | 
			
		||||
			dprintk("dvb_demux.c pad data:");
 | 
			
		||||
			for (i = 0; i < n; i++)
 | 
			
		||||
				pr_cont(" %02x", sec->secbuf[i]);
 | 
			
		||||
			pr_cont("\n");
 | 
			
		||||
			dprintk_sect_loss("pad data: %*ph\n", n, sec->secbuf);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	sec->tsfeedp = sec->secbufp = sec->seclen = 0;
 | 
			
		||||
	sec->secbuf = sec->secbuf_base;
 | 
			
		||||
@@ -236,10 +246,10 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
 | 
			
		||||
 *  when the second packet arrives.
 | 
			
		||||
 *
 | 
			
		||||
 * Fix:
 | 
			
		||||
 * when demux is started, let feed->pusi_seen = 0 to
 | 
			
		||||
 * when demux is started, let feed->pusi_seen = false to
 | 
			
		||||
 * prevent initial feeding of garbage from the end of
 | 
			
		||||
 * previous section. When you for the first time see PUSI=1
 | 
			
		||||
 * then set feed->pusi_seen = 1
 | 
			
		||||
 * then set feed->pusi_seen = true
 | 
			
		||||
 */
 | 
			
		||||
static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
 | 
			
		||||
					      const u8 *buf, u8 len)
 | 
			
		||||
@@ -252,11 +262,10 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
 | 
			
		||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
		dprintk("dvb_demux.c section buffer full loss: %d/%d\n",
 | 
			
		||||
		set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
 | 
			
		||||
		dprintk_sect_loss("section buffer full loss: %d/%d\n",
 | 
			
		||||
				  sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
 | 
			
		||||
				  DMX_MAX_SECFEED_SIZE);
 | 
			
		||||
#endif
 | 
			
		||||
		len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -284,12 +293,13 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
 | 
			
		||||
		sec->seclen = seclen;
 | 
			
		||||
		sec->crc_val = ~0;
 | 
			
		||||
		/* dump [secbuf .. secbuf+seclen) */
 | 
			
		||||
		if (feed->pusi_seen)
 | 
			
		||||
		if (feed->pusi_seen) {
 | 
			
		||||
			dvb_dmx_swfilter_section_feed(feed);
 | 
			
		||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
		else
 | 
			
		||||
			dprintk("dvb_demux.c pusi not seen, discarding section data\n");
 | 
			
		||||
#endif
 | 
			
		||||
		} else {
 | 
			
		||||
			set_buf_flags(feed,
 | 
			
		||||
				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
 | 
			
		||||
			dprintk_sect_loss("pusi not seen, discarding section data\n");
 | 
			
		||||
		}
 | 
			
		||||
		sec->secbufp += seclen;	/* secbufp and secbuf moving together is */
 | 
			
		||||
		sec->secbuf += seclen;	/* redundant but saves pointer arithmetic */
 | 
			
		||||
	}
 | 
			
		||||
@@ -322,19 +332,31 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!ccok || dc_i) {
 | 
			
		||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
		dprintk("dvb_demux.c discontinuity detected %d bytes lost\n",
 | 
			
		||||
			count);
 | 
			
		||||
		if (dc_i) {
 | 
			
		||||
			set_buf_flags(feed,
 | 
			
		||||
				      DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR);
 | 
			
		||||
			dprintk_sect_loss("%d frame with disconnect indicator\n",
 | 
			
		||||
				cc);
 | 
			
		||||
		} else {
 | 
			
		||||
			set_buf_flags(feed,
 | 
			
		||||
				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
 | 
			
		||||
			dprintk_sect_loss("discontinuity: %d instead of %d. %d bytes lost\n",
 | 
			
		||||
				cc, (feed->cc + 1) & 0x0f, count + 4);
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * those bytes under sume circumstances will again be reported
 | 
			
		||||
		 * those bytes under some circumstances will again be reported
 | 
			
		||||
		 * in the following dvb_dmx_swfilter_section_new
 | 
			
		||||
		 */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Discontinuity detected. Reset pusi_seen = 0 to
 | 
			
		||||
		 * Discontinuity detected. Reset pusi_seen to
 | 
			
		||||
		 * stop feeding of suspicious data until next PUSI=1 arrives
 | 
			
		||||
		 *
 | 
			
		||||
		 * FIXME: does it make sense if the MPEG-TS is the one
 | 
			
		||||
		 *	reporting discontinuity?
 | 
			
		||||
		 */
 | 
			
		||||
		feed->pusi_seen = 0;
 | 
			
		||||
 | 
			
		||||
		feed->pusi_seen = false;
 | 
			
		||||
		dvb_dmx_swfilter_section_new(feed);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -348,17 +370,16 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
 | 
			
		||||
 | 
			
		||||
			dvb_dmx_swfilter_section_copy_dump(feed, before,
 | 
			
		||||
							   before_len);
 | 
			
		||||
			/* before start of new section, set pusi_seen = 1 */
 | 
			
		||||
			feed->pusi_seen = 1;
 | 
			
		||||
			/* before start of new section, set pusi_seen */
 | 
			
		||||
			feed->pusi_seen = true;
 | 
			
		||||
			dvb_dmx_swfilter_section_new(feed);
 | 
			
		||||
			dvb_dmx_swfilter_section_copy_dump(feed, after,
 | 
			
		||||
							   after_len);
 | 
			
		||||
		} else if (count > 0) {
 | 
			
		||||
			set_buf_flags(feed,
 | 
			
		||||
				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
 | 
			
		||||
			dprintk_sect_loss("PUSI=1 but %d bytes lost\n", count);
 | 
			
		||||
		}
 | 
			
		||||
#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 | 
			
		||||
		else if (count > 0)
 | 
			
		||||
			dprintk("dvb_demux.c PUSI=1 but %d bytes lost\n",
 | 
			
		||||
				count);
 | 
			
		||||
#endif
 | 
			
		||||
	} else {
 | 
			
		||||
		/* PUSI=0 (is not set), no section boundary */
 | 
			
		||||
		dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
 | 
			
		||||
@@ -378,8 +399,10 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
 | 
			
		||||
			if (feed->ts_type & TS_PAYLOAD_ONLY)
 | 
			
		||||
				dvb_dmx_swfilter_payload(feed, buf);
 | 
			
		||||
			else
 | 
			
		||||
				feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
 | 
			
		||||
				feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
 | 
			
		||||
					    &feed->buffer_flags);
 | 
			
		||||
		}
 | 
			
		||||
		/* Used only on full-featured devices */
 | 
			
		||||
		if (feed->ts_type & TS_DECODER)
 | 
			
		||||
			if (feed->demux->write_to_decoder)
 | 
			
		||||
				feed->demux->write_to_decoder(feed, buf, 188);
 | 
			
		||||
@@ -426,6 +449,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 | 
			
		||||
						1024);
 | 
			
		||||
				speed_timedelta = ktime_ms_delta(cur_time,
 | 
			
		||||
							demux->speed_last_time);
 | 
			
		||||
				if (speed_timedelta)
 | 
			
		||||
					dprintk("TS speed %llu Kbits/sec \n",
 | 
			
		||||
						div64_u64(speed_bytes,
 | 
			
		||||
							  speed_timedelta));
 | 
			
		||||
@@ -437,6 +461,11 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (buf[1] & 0x80) {
 | 
			
		||||
		list_for_each_entry(feed, &demux->feed_list, list_head) {
 | 
			
		||||
			if ((feed->pid != pid) && (feed->pid != 0x2000))
 | 
			
		||||
				continue;
 | 
			
		||||
			set_buf_flags(feed, DMX_BUFFER_FLAG_TEI);
 | 
			
		||||
		}
 | 
			
		||||
		dprintk_tscheck("TEI detected. PID=0x%x data1=0x%x\n",
 | 
			
		||||
				pid, buf[1]);
 | 
			
		||||
		/* data in this packet can't be trusted - drop it unless
 | 
			
		||||
@@ -452,6 +481,13 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 | 
			
		||||
						(demux->cnt_storage[pid] + 1) & 0xf;
 | 
			
		||||
 | 
			
		||||
				if ((buf[3] & 0xf) != demux->cnt_storage[pid]) {
 | 
			
		||||
					list_for_each_entry(feed, &demux->feed_list, list_head) {
 | 
			
		||||
						if ((feed->pid != pid) && (feed->pid != 0x2000))
 | 
			
		||||
							continue;
 | 
			
		||||
						set_buf_flags(feed,
 | 
			
		||||
							      DMX_BUFFER_PKT_COUNTER_MISMATCH);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
 | 
			
		||||
						pid, demux->cnt_storage[pid],
 | 
			
		||||
						buf[3] & 0xf);
 | 
			
		||||
@@ -473,7 +509,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 | 
			
		||||
		if (feed->pid == pid)
 | 
			
		||||
			dvb_dmx_swfilter_packet_type(feed, buf);
 | 
			
		||||
		else if (feed->pid == 0x2000)
 | 
			
		||||
			feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
 | 
			
		||||
			feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
 | 
			
		||||
				    &feed->buffer_flags);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -592,7 +629,16 @@ void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&demux->lock, flags);
 | 
			
		||||
 | 
			
		||||
	demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts);
 | 
			
		||||
#if 1
 | 
			
		||||
	demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts,
 | 
			
		||||
			   &demux->feed->buffer_flags);
 | 
			
		||||
#else
 | 
			
		||||
	struct dvb_demux_feed *feed;
 | 
			
		||||
	list_for_each_entry(feed, &demux->feed_list, list_head) {
 | 
			
		||||
		feed->cb.ts(buf, count, NULL, 0, &feed->feed.ts,
 | 
			
		||||
			    &feed->buffer_flags);
 | 
			
		||||
	}
 | 
			
		||||
#endif	
 | 
			
		||||
 | 
			
		||||
	spin_unlock_irqrestore(&demux->lock, flags);
 | 
			
		||||
}
 | 
			
		||||
@@ -792,6 +838,7 @@ static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
 | 
			
		||||
	feed->demux = demux;
 | 
			
		||||
	feed->pid = 0xffff;
 | 
			
		||||
	feed->peslen = 0xfffa;
 | 
			
		||||
	feed->buffer_flags = 0;
 | 
			
		||||
 | 
			
		||||
	(*ts_feed) = &feed->feed.ts;
 | 
			
		||||
	(*ts_feed)->parent = dmx;
 | 
			
		||||
@@ -911,14 +958,14 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
 | 
			
		||||
		return;
 | 
			
		||||
	do {
 | 
			
		||||
		sf = &f->filter;
 | 
			
		||||
		doneq = 0;
 | 
			
		||||
		doneq = false;
 | 
			
		||||
		for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
 | 
			
		||||
			mode = sf->filter_mode[i];
 | 
			
		||||
			mask = sf->filter_mask[i];
 | 
			
		||||
			f->maskandmode[i] = mask & mode;
 | 
			
		||||
			doneq |= f->maskandnotmode[i] = mask & ~mode;
 | 
			
		||||
		}
 | 
			
		||||
		f->doneq = doneq ? 1 : 0;
 | 
			
		||||
		f->doneq = doneq ? true : false;
 | 
			
		||||
	} while ((f = f->next));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -945,6 +992,7 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
 | 
			
		||||
	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
 | 
			
		||||
	dvbdmxfeed->feed.sec.secbufp = 0;
 | 
			
		||||
	dvbdmxfeed->feed.sec.seclen = 0;
 | 
			
		||||
	dvbdmxfeed->pusi_seen = false;
 | 
			
		||||
 | 
			
		||||
	if (!dvbdmx->start_feed) {
 | 
			
		||||
		mutex_unlock(&dvbdmx->mutex);
 | 
			
		||||
@@ -1049,6 +1097,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
 | 
			
		||||
	dvbdmxfeed->cb.sec = callback;
 | 
			
		||||
	dvbdmxfeed->demux = dvbdmx;
 | 
			
		||||
	dvbdmxfeed->pid = 0xffff;
 | 
			
		||||
	dvbdmxfeed->buffer_flags = 0;
 | 
			
		||||
	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
 | 
			
		||||
	dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
 | 
			
		||||
	dvbdmxfeed->feed.sec.tsfeedp = 0;
 | 
			
		||||
@@ -1220,12 +1269,25 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
 | 
			
		||||
 | 
			
		||||
	dvbdemux->cnt_storage = NULL;
 | 
			
		||||
	dvbdemux->users = 0;
 | 
			
		||||
	dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
 | 
			
		||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0))
 | 
			
		||||
	dvbdemux->filter = vmalloc(sizeof(struct dvb_demux_filter) *
 | 
			
		||||
				   dvbdemux->filternum);
 | 
			
		||||
 | 
			
		||||
	if (!dvbdemux->filter)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed));
 | 
			
		||||
	dvbdemux->feed = vmalloc(sizeof(struct dvb_demux_feed) *
 | 
			
		||||
				 dvbdemux->feednum);
 | 
			
		||||
#else
 | 
			
		||||
	dvbdemux->filter = vmalloc(array_size(sizeof(struct dvb_demux_filter),
 | 
			
		||||
					      dvbdemux->filternum));
 | 
			
		||||
 | 
			
		||||
	if (!dvbdemux->filter)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	dvbdemux->feed = vmalloc(array_size(sizeof(struct dvb_demux_feed),
 | 
			
		||||
					    dvbdemux->feednum));
 | 
			
		||||
#endif
 | 
			
		||||
	if (!dvbdemux->feed) {
 | 
			
		||||
		vfree(dvbdemux->filter);
 | 
			
		||||
		dvbdemux->filter = NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,145 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * dvb_demux.h: DVB kernel demux API
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler
 | 
			
		||||
 *                         for convergence integrated media GmbH
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2.1
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _DVB_DEMUX_H_
 | 
			
		||||
#define _DVB_DEMUX_H_
 | 
			
		||||
 | 
			
		||||
#include <linux/time.h>
 | 
			
		||||
#include <linux/timer.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
 | 
			
		||||
#include "demux.h"
 | 
			
		||||
 | 
			
		||||
#define DMX_TYPE_TS  0
 | 
			
		||||
#define DMX_TYPE_SEC 1
 | 
			
		||||
#define DMX_TYPE_PES 2
 | 
			
		||||
 | 
			
		||||
#define DMX_STATE_FREE      0
 | 
			
		||||
#define DMX_STATE_ALLOCATED 1
 | 
			
		||||
#define DMX_STATE_SET       2
 | 
			
		||||
#define DMX_STATE_READY     3
 | 
			
		||||
#define DMX_STATE_GO        4
 | 
			
		||||
 | 
			
		||||
#define DVB_DEMUX_MASK_MAX 18
 | 
			
		||||
 | 
			
		||||
#define MAX_PID 0x1fff
 | 
			
		||||
 | 
			
		||||
#define SPEED_PKTS_INTERVAL 50000
 | 
			
		||||
 | 
			
		||||
struct dvb_demux_filter {
 | 
			
		||||
	struct dmx_section_filter filter;
 | 
			
		||||
	u8 maskandmode[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
	u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
	int doneq;
 | 
			
		||||
 | 
			
		||||
	struct dvb_demux_filter *next;
 | 
			
		||||
	struct dvb_demux_feed *feed;
 | 
			
		||||
	int index;
 | 
			
		||||
	int state;
 | 
			
		||||
	int type;
 | 
			
		||||
 | 
			
		||||
	u16 hw_handle;
 | 
			
		||||
	struct timer_list timer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
 | 
			
		||||
 | 
			
		||||
struct dvb_demux_feed {
 | 
			
		||||
	union {
 | 
			
		||||
		struct dmx_ts_feed ts;
 | 
			
		||||
		struct dmx_section_feed sec;
 | 
			
		||||
	} feed;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		dmx_ts_cb ts;
 | 
			
		||||
		dmx_section_cb sec;
 | 
			
		||||
	} cb;
 | 
			
		||||
 | 
			
		||||
	struct dvb_demux *demux;
 | 
			
		||||
	void *priv;
 | 
			
		||||
	int type;
 | 
			
		||||
	int state;
 | 
			
		||||
	u16 pid;
 | 
			
		||||
 | 
			
		||||
	ktime_t timeout;
 | 
			
		||||
	struct dvb_demux_filter *filter;
 | 
			
		||||
 | 
			
		||||
	int ts_type;
 | 
			
		||||
	enum dmx_ts_pes pes_type;
 | 
			
		||||
 | 
			
		||||
	int cc;
 | 
			
		||||
	int pusi_seen;		/* prevents feeding of garbage from previous section */
 | 
			
		||||
 | 
			
		||||
	u16 peslen;
 | 
			
		||||
 | 
			
		||||
	struct list_head list_head;
 | 
			
		||||
	unsigned int index;	/* a unique index for each feed (can be used as hardware pid filter index) */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct dvb_demux {
 | 
			
		||||
	struct dmx_demux dmx;
 | 
			
		||||
	void *priv;
 | 
			
		||||
	int filternum;
 | 
			
		||||
	int feednum;
 | 
			
		||||
	int (*start_feed)(struct dvb_demux_feed *feed);
 | 
			
		||||
	int (*stop_feed)(struct dvb_demux_feed *feed);
 | 
			
		||||
	int (*write_to_decoder)(struct dvb_demux_feed *feed,
 | 
			
		||||
				 const u8 *buf, size_t len);
 | 
			
		||||
	u32 (*check_crc32)(struct dvb_demux_feed *feed,
 | 
			
		||||
			    const u8 *buf, size_t len);
 | 
			
		||||
	void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
 | 
			
		||||
			 const u8 *src, size_t len);
 | 
			
		||||
 | 
			
		||||
	int users;
 | 
			
		||||
#define MAX_DVB_DEMUX_USERS 10
 | 
			
		||||
	struct dvb_demux_filter *filter;
 | 
			
		||||
	struct dvb_demux_feed *feed;
 | 
			
		||||
 | 
			
		||||
	struct list_head frontend_list;
 | 
			
		||||
 | 
			
		||||
	struct dvb_demux_feed *pesfilter[DMX_PES_OTHER];
 | 
			
		||||
	u16 pids[DMX_PES_OTHER];
 | 
			
		||||
	int playing;
 | 
			
		||||
	int recording;
 | 
			
		||||
 | 
			
		||||
#define DMX_MAX_PID 0x2000
 | 
			
		||||
	struct list_head feed_list;
 | 
			
		||||
	u8 tsbuf[204];
 | 
			
		||||
	int tsbufp;
 | 
			
		||||
 | 
			
		||||
	struct mutex mutex;
 | 
			
		||||
	spinlock_t lock;
 | 
			
		||||
 | 
			
		||||
	uint8_t *cnt_storage; /* for TS continuity check */
 | 
			
		||||
 | 
			
		||||
	ktime_t speed_last_time; /* for TS speed check */
 | 
			
		||||
	uint32_t speed_pkts_cnt; /* for TS speed check */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int dvb_dmx_init(struct dvb_demux *dvbdemux);
 | 
			
		||||
void dvb_dmx_release(struct dvb_demux *dvbdemux);
 | 
			
		||||
void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf,
 | 
			
		||||
			      size_t count);
 | 
			
		||||
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
 | 
			
		||||
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
 | 
			
		||||
			  size_t count);
 | 
			
		||||
void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf,
 | 
			
		||||
			  size_t count);
 | 
			
		||||
 | 
			
		||||
#endif /* _DVB_DEMUX_H_ */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -19,7 +19,7 @@
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <asm/bug.h>
 | 
			
		||||
#include "dvb_math.h"
 | 
			
		||||
#include <media/dvb_math.h>
 | 
			
		||||
 | 
			
		||||
static const unsigned short logtable[256] = {
 | 
			
		||||
	0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
/*
 | 
			
		||||
 * dvb_net.c
 | 
			
		||||
 *
 | 
			
		||||
@@ -13,18 +14,6 @@
 | 
			
		||||
 *                      and Wolfram Stering <wstering@cosy.sbg.ac.at>
 | 
			
		||||
 *
 | 
			
		||||
 * ULE Decaps according to RFC 4326.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 * To obtain the license, point your browser to
 | 
			
		||||
 * http://www.gnu.org/copyleft/gpl.html
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -38,7 +27,7 @@
 | 
			
		||||
 *                       Competence Center for Advanced Satellite Communications.
 | 
			
		||||
 *                     Bugfixes and robustness improvements.
 | 
			
		||||
 *                     Filtering on dest MAC addresses, if present (D-Bit = 0)
 | 
			
		||||
 *                     ULE_DEBUG compile-time option.
 | 
			
		||||
 *                     DVB_ULE_DEBUG compile-time option.
 | 
			
		||||
 * Apr 2006: cp v3:    Bugfixes and compliency with RFC 4326 (ULE) by
 | 
			
		||||
 *                       Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
 | 
			
		||||
 *                       Paris Lodron University of Salzburg.
 | 
			
		||||
@@ -69,8 +58,8 @@
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_demux.h"
 | 
			
		||||
#include "dvb_net.h"
 | 
			
		||||
#include <media/dvb_demux.h>
 | 
			
		||||
#include <media/dvb_net.h>
 | 
			
		||||
 | 
			
		||||
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
 | 
			
		||||
{
 | 
			
		||||
@@ -83,15 +72,20 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
 | 
			
		||||
 | 
			
		||||
#define DVB_NET_MULTICAST_MAX 10
 | 
			
		||||
 | 
			
		||||
#undef ULE_DEBUG
 | 
			
		||||
#undef DVB_ULE_DEBUG
 | 
			
		||||
 | 
			
		||||
#ifdef ULE_DEBUG
 | 
			
		||||
#ifdef DVB_ULE_DEBUG
 | 
			
		||||
/*
 | 
			
		||||
 * The code inside DVB_ULE_DEBUG keeps a history of the
 | 
			
		||||
 * last 100 TS cells processed.
 | 
			
		||||
 */
 | 
			
		||||
static unsigned char ule_hist[100*TS_SZ] = { 0 };
 | 
			
		||||
static unsigned char *ule_where = ule_hist, ule_dump;
 | 
			
		||||
 | 
			
		||||
static void hexdump(const unsigned char *buf, unsigned short len)
 | 
			
		||||
{
 | 
			
		||||
	print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct dvb_net_priv {
 | 
			
		||||
@@ -130,7 +124,7 @@ struct dvb_net_priv {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
/*
 | 
			
		||||
 *	Determine the packet's protocol ID. The rule here is that we
 | 
			
		||||
 *	assume 802.3 if the type field is short enough to be a length.
 | 
			
		||||
 *	This is normal practice and works for any 'now in use' protocol.
 | 
			
		||||
@@ -160,7 +154,7 @@ static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
 | 
			
		||||
 | 
			
		||||
	rawp = skb->data;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	/*
 | 
			
		||||
	 *	This is a magic hack to spot IPX packets. Older Novell breaks
 | 
			
		||||
	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC
 | 
			
		||||
	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
 | 
			
		||||
@@ -169,7 +163,7 @@ static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
 | 
			
		||||
	if (*(unsigned short *)rawp == 0xFFFF)
 | 
			
		||||
		return htons(ETH_P_802_3);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	/*
 | 
			
		||||
	 *	Real 802.2 LLC
 | 
			
		||||
	 */
 | 
			
		||||
	return htons(ETH_P_802_2);
 | 
			
		||||
@@ -220,7 +214,8 @@ static int ule_exthdr_padding(struct dvb_net_priv *p)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Handle ULE extension headers.
 | 
			
		||||
/*
 | 
			
		||||
 *  Handle ULE extension headers.
 | 
			
		||||
 *  Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
 | 
			
		||||
 *  Returns: >= 0: nr. of bytes consumed by next extension header
 | 
			
		||||
 *	     -1:   Mandatory extension header that is not recognized or TEST SNDU; discard.
 | 
			
		||||
@@ -284,11 +279,9 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
 | 
			
		||||
		if (l < 0)
 | 
			
		||||
			return l;	/* Stop extension header processing and discard SNDU. */
 | 
			
		||||
		total_ext_len += l;
 | 
			
		||||
#ifdef ULE_DEBUG
 | 
			
		||||
		pr_debug("ule_next_hdr=%p, ule_sndu_type=%i, l=%i, total_ext_len=%i\n",
 | 
			
		||||
			 p->ule_next_hdr, (int)p->ule_sndu_type,
 | 
			
		||||
			 l, total_ext_len);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	} while (p->ule_sndu_type < ETH_P_802_3_MIN);
 | 
			
		||||
 | 
			
		||||
@@ -296,7 +289,7 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Prepare for a new ULE SNDU: reset the decoder state. */
 | 
			
		||||
/* Prepare for a new ULE SNDU: reset the decoder state. */
 | 
			
		||||
static inline void reset_ule( struct dvb_net_priv *p )
 | 
			
		||||
{
 | 
			
		||||
	p->ule_skb = NULL;
 | 
			
		||||
@@ -309,7 +302,7 @@ static inline void reset_ule( struct dvb_net_priv *p )
 | 
			
		||||
	p->ule_bridged = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
/*
 | 
			
		||||
 * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of
 | 
			
		||||
 * TS cells of a single PID.
 | 
			
		||||
 */
 | 
			
		||||
@@ -324,29 +317,21 @@ struct dvb_net_ule_handle {
 | 
			
		||||
	const u8 *ts, *ts_end, *from_where;
 | 
			
		||||
	u8 ts_remain, how_much, new_ts;
 | 
			
		||||
	bool error;
 | 
			
		||||
#ifdef ULE_DEBUG
 | 
			
		||||
	/*
 | 
			
		||||
	 * The code inside ULE_DEBUG keeps a history of the
 | 
			
		||||
	 * last 100 TS cells processed.
 | 
			
		||||
	 */
 | 
			
		||||
	static unsigned char ule_hist[100*TS_SZ];
 | 
			
		||||
	static unsigned char *ule_where = ule_hist, ule_dump;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int dvb_net_ule_new_ts_cell(struct dvb_net_ule_handle *h)
 | 
			
		||||
{
 | 
			
		||||
	/* We are about to process a new TS cell. */
 | 
			
		||||
 | 
			
		||||
#ifdef ULE_DEBUG
 | 
			
		||||
	if (h->ule_where >= &h->ule_hist[100*TS_SZ])
 | 
			
		||||
		h->ule_where = h->ule_hist;
 | 
			
		||||
	memcpy(h->ule_where, h->ts, TS_SZ);
 | 
			
		||||
	if (h->ule_dump) {
 | 
			
		||||
		hexdump(h->ule_where, TS_SZ);
 | 
			
		||||
		h->ule_dump = 0;
 | 
			
		||||
#ifdef DVB_ULE_DEBUG
 | 
			
		||||
	if (ule_where >= &ule_hist[100*TS_SZ])
 | 
			
		||||
		ule_where = ule_hist;
 | 
			
		||||
	memcpy(ule_where, h->ts, TS_SZ);
 | 
			
		||||
	if (ule_dump) {
 | 
			
		||||
		hexdump(ule_where, TS_SZ);
 | 
			
		||||
		ule_dump = 0;
 | 
			
		||||
	}
 | 
			
		||||
	h->ule_where += TS_SZ;
 | 
			
		||||
	ule_where += TS_SZ;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -664,6 +649,7 @@ static int dvb_net_ule_should_drop(struct dvb_net_ule_handle *h)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
 | 
			
		||||
				  struct kvec iov[3],
 | 
			
		||||
				  u32 ule_crc, u32 expected_crc)
 | 
			
		||||
{
 | 
			
		||||
	u8 dest_addr[ETH_ALEN];
 | 
			
		||||
@@ -676,22 +662,22 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
 | 
			
		||||
			h->ts_remain > 2 ?
 | 
			
		||||
				*(unsigned short *)h->from_where : 0);
 | 
			
		||||
 | 
			
		||||
	#ifdef ULE_DEBUG
 | 
			
		||||
        #ifdef DVB_ULE_DEBUG
 | 
			
		||||
		hexdump(iov[0].iov_base, iov[0].iov_len);
 | 
			
		||||
		hexdump(iov[1].iov_base, iov[1].iov_len);
 | 
			
		||||
		hexdump(iov[2].iov_base, iov[2].iov_len);
 | 
			
		||||
 | 
			
		||||
		if (h->ule_where == h->ule_hist) {
 | 
			
		||||
			hexdump(&h->ule_hist[98*TS_SZ], TS_SZ);
 | 
			
		||||
			hexdump(&h->ule_hist[99*TS_SZ], TS_SZ);
 | 
			
		||||
		} else if (h->ule_where == &h->ule_hist[TS_SZ]) {
 | 
			
		||||
			hexdump(&h->ule_hist[99*TS_SZ], TS_SZ);
 | 
			
		||||
			hexdump(h->ule_hist, TS_SZ);
 | 
			
		||||
		if (ule_where == ule_hist) {
 | 
			
		||||
			hexdump(&ule_hist[98*TS_SZ], TS_SZ);
 | 
			
		||||
			hexdump(&ule_hist[99*TS_SZ], TS_SZ);
 | 
			
		||||
		} else if (ule_where == &ule_hist[TS_SZ]) {
 | 
			
		||||
			hexdump(&ule_hist[99*TS_SZ], TS_SZ);
 | 
			
		||||
			hexdump(ule_hist, TS_SZ);
 | 
			
		||||
		} else {
 | 
			
		||||
			hexdump(h->ule_where - TS_SZ - TS_SZ, TS_SZ);
 | 
			
		||||
			hexdump(h->ule_where - TS_SZ, TS_SZ);
 | 
			
		||||
			hexdump(ule_where - TS_SZ - TS_SZ, TS_SZ);
 | 
			
		||||
			hexdump(ule_where - TS_SZ, TS_SZ);
 | 
			
		||||
		}
 | 
			
		||||
		h->ule_dump = 1;
 | 
			
		||||
		ule_dump = 1;
 | 
			
		||||
	#endif
 | 
			
		||||
 | 
			
		||||
		h->dev->stats.rx_errors++;
 | 
			
		||||
@@ -709,11 +695,9 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
 | 
			
		||||
 | 
			
		||||
	if (!h->priv->ule_dbit) {
 | 
			
		||||
		if (dvb_net_ule_should_drop(h)) {
 | 
			
		||||
#ifdef ULE_DEBUG
 | 
			
		||||
			netdev_dbg(h->dev,
 | 
			
		||||
				   "Dropping SNDU: MAC destination address does not match: dest addr: %pM, h->dev addr: %pM\n",
 | 
			
		||||
				   h->priv->ule_skb->data, h->dev->dev_addr);
 | 
			
		||||
#endif
 | 
			
		||||
			dev_kfree_skb(h->priv->ule_skb);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
@@ -784,6 +768,7 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
 | 
			
		||||
	struct dvb_net_ule_handle h = {
 | 
			
		||||
		.dev = dev,
 | 
			
		||||
		.priv = netdev_priv(dev),
 | 
			
		||||
		.ethh = NULL,
 | 
			
		||||
		.buf = buf,
 | 
			
		||||
		.buf_len = buf_len,
 | 
			
		||||
		.skipped = 0L,
 | 
			
		||||
@@ -793,11 +778,7 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
 | 
			
		||||
		.ts_remain = 0,
 | 
			
		||||
		.how_much = 0,
 | 
			
		||||
		.new_ts = 1,
 | 
			
		||||
		.ethh = NULL,
 | 
			
		||||
		.error = false,
 | 
			
		||||
#ifdef ULE_DEBUG
 | 
			
		||||
		.ule_where = ule_hist,
 | 
			
		||||
#endif
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -869,7 +850,7 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
 | 
			
		||||
				       *(tail - 2) << 8 |
 | 
			
		||||
				       *(tail - 1);
 | 
			
		||||
 | 
			
		||||
			dvb_net_ule_check_crc(&h, ule_crc, expected_crc);
 | 
			
		||||
			dvb_net_ule_check_crc(&h, iov, ule_crc, expected_crc);
 | 
			
		||||
 | 
			
		||||
			/* Prepare for next SNDU. */
 | 
			
		||||
			reset_ule(h.priv);
 | 
			
		||||
@@ -902,7 +883,8 @@ static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
 | 
			
		||||
 | 
			
		||||
static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
 | 
			
		||||
			       const u8 *buffer2, size_t buffer2_len,
 | 
			
		||||
			       struct dmx_ts_feed *feed)
 | 
			
		||||
			       struct dmx_ts_feed *feed,
 | 
			
		||||
			       u32 *buffer_flags)
 | 
			
		||||
{
 | 
			
		||||
	struct net_device *dev = feed->priv;
 | 
			
		||||
 | 
			
		||||
@@ -1011,11 +993,11 @@ static void dvb_net_sec(struct net_device *dev,
 | 
			
		||||
 | 
			
		||||
static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
 | 
			
		||||
				const u8 *buffer2, size_t buffer2_len,
 | 
			
		||||
		 struct dmx_section_filter *filter)
 | 
			
		||||
				struct dmx_section_filter *filter, u32 *buffer_flags)
 | 
			
		||||
{
 | 
			
		||||
	struct net_device *dev = filter->priv;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	/*
 | 
			
		||||
	 * we rely on the DVB API definition where exactly one complete
 | 
			
		||||
	 * section is delivered in buffer1
 | 
			
		||||
	 */
 | 
			
		||||
@@ -1023,7 +1005,7 @@ static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
 | 
			
		||||
static netdev_tx_t dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	dev_kfree_skb(skb);
 | 
			
		||||
	return NETDEV_TX_OK;
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
#include <linux/uaccess.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "dvb_ringbuffer.h"
 | 
			
		||||
#include <media/dvb_ringbuffer.h>
 | 
			
		||||
 | 
			
		||||
#define PKT_READY 0
 | 
			
		||||
#define PKT_DISPOSED 1
 | 
			
		||||
@@ -63,7 +63,7 @@ int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
 | 
			
		||||
	 * this pairs with smp_store_release() in dvb_ringbuffer_write(),
 | 
			
		||||
	 * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
 | 
			
		||||
	 *
 | 
			
		||||
	 * for memory barriers also see Documentation/circular-buffers.txt
 | 
			
		||||
	 * for memory barriers also see Documentation/core-api/circular-buffers.txt
 | 
			
		||||
	 */
 | 
			
		||||
	return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										442
									
								
								dvb-core/dvb_vb2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										442
									
								
								dvb-core/dvb_vb2.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,442 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
/*
 | 
			
		||||
 * dvb-vb2.c - dvb-vb2
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2015 Samsung Electronics
 | 
			
		||||
 *
 | 
			
		||||
 * Author: jh1009.sung@samsung.com
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/err.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/mm.h>
 | 
			
		||||
 | 
			
		||||
#include <media/dvbdev.h>
 | 
			
		||||
#include <media/dvb_vb2.h>
 | 
			
		||||
 | 
			
		||||
#define DVB_V2_MAX_SIZE		(4096 * 188)
 | 
			
		||||
 | 
			
		||||
static int vb2_debug;
 | 
			
		||||
module_param(vb2_debug, int, 0644);
 | 
			
		||||
 | 
			
		||||
#define dprintk(level, fmt, arg...)					      \
 | 
			
		||||
	do {								      \
 | 
			
		||||
		if (vb2_debug >= level)					      \
 | 
			
		||||
			pr_info("vb2: %s: " fmt, __func__, ## arg); \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
static int _queue_setup(struct vb2_queue *vq,
 | 
			
		||||
			unsigned int *nbuffers, unsigned int *nplanes,
 | 
			
		||||
			unsigned int sizes[], struct device *alloc_devs[])
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
 | 
			
		||||
 | 
			
		||||
	ctx->buf_cnt = *nbuffers;
 | 
			
		||||
	*nplanes = 1;
 | 
			
		||||
	sizes[0] = ctx->buf_siz;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * videobuf2-vmalloc allocator is context-less so no need to set
 | 
			
		||||
	 * alloc_ctxs array.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	dprintk(3, "[%s] count=%d, size=%d\n", ctx->name,
 | 
			
		||||
		*nbuffers, sizes[0]);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _buffer_prepare(struct vb2_buffer *vb)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 | 
			
		||||
	unsigned long size = ctx->buf_siz;
 | 
			
		||||
 | 
			
		||||
	if (vb2_plane_size(vb, 0) < size) {
 | 
			
		||||
		dprintk(1, "[%s] data will not fit into plane (%lu < %lu)\n",
 | 
			
		||||
			ctx->name, vb2_plane_size(vb, 0), size);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vb2_set_plane_payload(vb, 0, size);
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _buffer_queue(struct vb2_buffer *vb)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 | 
			
		||||
	struct dvb_buffer *buf = container_of(vb, struct dvb_buffer, vb);
 | 
			
		||||
	unsigned long flags = 0;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&ctx->slock, flags);
 | 
			
		||||
	list_add_tail(&buf->list, &ctx->dvb_q);
 | 
			
		||||
	spin_unlock_irqrestore(&ctx->slock, flags);
 | 
			
		||||
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _start_streaming(struct vb2_queue *vq, unsigned int count)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
 | 
			
		||||
 | 
			
		||||
	dprintk(3, "[%s] count=%d\n", ctx->name, count);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _stop_streaming(struct vb2_queue *vq)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
 | 
			
		||||
	struct dvb_buffer *buf;
 | 
			
		||||
	unsigned long flags = 0;
 | 
			
		||||
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&ctx->slock, flags);
 | 
			
		||||
	while (!list_empty(&ctx->dvb_q)) {
 | 
			
		||||
		buf = list_entry(ctx->dvb_q.next,
 | 
			
		||||
				 struct dvb_buffer, list);
 | 
			
		||||
		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 | 
			
		||||
		list_del(&buf->list);
 | 
			
		||||
	}
 | 
			
		||||
	spin_unlock_irqrestore(&ctx->slock, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _dmxdev_lock(struct vb2_queue *vq)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&ctx->mutex);
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _dmxdev_unlock(struct vb2_queue *vq)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vq);
 | 
			
		||||
 | 
			
		||||
	if (mutex_is_locked(&ctx->mutex))
 | 
			
		||||
		mutex_unlock(&ctx->mutex);
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct vb2_ops dvb_vb2_qops = {
 | 
			
		||||
	.queue_setup		= _queue_setup,
 | 
			
		||||
	.buf_prepare		= _buffer_prepare,
 | 
			
		||||
	.buf_queue		= _buffer_queue,
 | 
			
		||||
	.start_streaming	= _start_streaming,
 | 
			
		||||
	.stop_streaming		= _stop_streaming,
 | 
			
		||||
	.wait_prepare		= _dmxdev_unlock,
 | 
			
		||||
	.wait_finish		= _dmxdev_lock,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void _fill_dmx_buffer(struct vb2_buffer *vb, void *pb)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 | 
			
		||||
	struct dmx_buffer *b = pb;
 | 
			
		||||
 | 
			
		||||
	b->index = vb->index;
 | 
			
		||||
	b->length = vb->planes[0].length;
 | 
			
		||||
	b->bytesused = vb->planes[0].bytesused;
 | 
			
		||||
	b->offset = vb->planes[0].m.offset;
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _fill_vb2_buffer(struct vb2_buffer *vb, struct vb2_plane *planes)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_vb2_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 | 
			
		||||
 | 
			
		||||
	planes[0].bytesused = 0;
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct vb2_buf_ops dvb_vb2_buf_ops = {
 | 
			
		||||
	.fill_user_buffer	= _fill_dmx_buffer,
 | 
			
		||||
	.fill_vb2_buffer	= _fill_vb2_buffer,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Videobuf operations
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int nonblocking)
 | 
			
		||||
{
 | 
			
		||||
	struct vb2_queue *q = &ctx->vb_q;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	memset(ctx, 0, sizeof(struct dvb_vb2_ctx));
 | 
			
		||||
	q->type = DVB_BUF_TYPE_CAPTURE;
 | 
			
		||||
	/**capture type*/
 | 
			
		||||
	q->is_output = 0;
 | 
			
		||||
	/**only mmap is supported currently*/
 | 
			
		||||
	q->io_modes = VB2_MMAP;
 | 
			
		||||
	q->drv_priv = ctx;
 | 
			
		||||
	q->buf_struct_size = sizeof(struct dvb_buffer);
 | 
			
		||||
	q->min_buffers_needed = 1;
 | 
			
		||||
	q->ops = &dvb_vb2_qops;
 | 
			
		||||
	q->mem_ops = &vb2_vmalloc_memops;
 | 
			
		||||
	q->buf_ops = &dvb_vb2_buf_ops;
 | 
			
		||||
	q->num_buffers = 0;
 | 
			
		||||
	ret = vb2_core_queue_init(q);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		ctx->state = DVB_VB2_STATE_NONE;
 | 
			
		||||
		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mutex_init(&ctx->mutex);
 | 
			
		||||
	spin_lock_init(&ctx->slock);
 | 
			
		||||
	INIT_LIST_HEAD(&ctx->dvb_q);
 | 
			
		||||
 | 
			
		||||
	strscpy(ctx->name, name, DVB_VB2_NAME_MAX);
 | 
			
		||||
	ctx->nonblocking = nonblocking;
 | 
			
		||||
	ctx->state = DVB_VB2_STATE_INIT;
 | 
			
		||||
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_release(struct dvb_vb2_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q;
 | 
			
		||||
 | 
			
		||||
	if (ctx->state & DVB_VB2_STATE_INIT)
 | 
			
		||||
		vb2_core_queue_release(q);
 | 
			
		||||
 | 
			
		||||
	ctx->state = DVB_VB2_STATE_NONE;
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_stream_on(struct dvb_vb2_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct vb2_queue *q = &ctx->vb_q;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = vb2_core_streamon(q, q->type);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		ctx->state = DVB_VB2_STATE_NONE;
 | 
			
		||||
		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	ctx->state |= DVB_VB2_STATE_STREAMON;
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_stream_off(struct dvb_vb2_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct vb2_queue *q = (struct vb2_queue *)&ctx->vb_q;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ctx->state &= ~DVB_VB2_STATE_STREAMON;
 | 
			
		||||
	ret = vb2_core_streamoff(q, q->type);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		ctx->state = DVB_VB2_STATE_NONE;
 | 
			
		||||
		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	return (ctx->state & DVB_VB2_STATE_STREAMON);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
 | 
			
		||||
			const unsigned char *src, int len,
 | 
			
		||||
			enum dmx_buffer_flags *buffer_flags)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long flags = 0;
 | 
			
		||||
	void *vbuf = NULL;
 | 
			
		||||
	int todo = len;
 | 
			
		||||
	unsigned char *psrc = (unsigned char *)src;
 | 
			
		||||
	int ll = 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * normal case: This func is called twice from demux driver
 | 
			
		||||
	 * one with valid src pointer, second time with NULL pointer
 | 
			
		||||
	 */
 | 
			
		||||
	if (!src || !len)
 | 
			
		||||
		return 0;
 | 
			
		||||
	spin_lock_irqsave(&ctx->slock, flags);
 | 
			
		||||
	if (buffer_flags && *buffer_flags) {
 | 
			
		||||
		ctx->flags |= *buffer_flags;
 | 
			
		||||
		*buffer_flags = 0;
 | 
			
		||||
	}
 | 
			
		||||
	while (todo) {
 | 
			
		||||
		if (!ctx->buf) {
 | 
			
		||||
			if (list_empty(&ctx->dvb_q)) {
 | 
			
		||||
				dprintk(3, "[%s] Buffer overflow!!!\n",
 | 
			
		||||
					ctx->name);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ctx->buf = list_entry(ctx->dvb_q.next,
 | 
			
		||||
					      struct dvb_buffer, list);
 | 
			
		||||
			ctx->remain = vb2_plane_size(&ctx->buf->vb, 0);
 | 
			
		||||
			ctx->offset = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!dvb_vb2_is_streaming(ctx)) {
 | 
			
		||||
			vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_ERROR);
 | 
			
		||||
			list_del(&ctx->buf->list);
 | 
			
		||||
			ctx->buf = NULL;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Fill buffer */
 | 
			
		||||
		ll = min(todo, ctx->remain);
 | 
			
		||||
		vbuf = vb2_plane_vaddr(&ctx->buf->vb, 0);
 | 
			
		||||
		memcpy(vbuf + ctx->offset, psrc, ll);
 | 
			
		||||
		todo -= ll;
 | 
			
		||||
		psrc += ll;
 | 
			
		||||
 | 
			
		||||
		ctx->remain -= ll;
 | 
			
		||||
		ctx->offset += ll;
 | 
			
		||||
 | 
			
		||||
		if (ctx->remain == 0) {
 | 
			
		||||
			vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE);
 | 
			
		||||
			list_del(&ctx->buf->list);
 | 
			
		||||
			ctx->buf = NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ctx->nonblocking && ctx->buf) {
 | 
			
		||||
		vb2_set_plane_payload(&ctx->buf->vb, 0, ll);
 | 
			
		||||
		vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE);
 | 
			
		||||
		list_del(&ctx->buf->list);
 | 
			
		||||
		ctx->buf = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	spin_unlock_irqrestore(&ctx->slock, flags);
 | 
			
		||||
 | 
			
		||||
	if (todo)
 | 
			
		||||
		dprintk(1, "[%s] %d bytes are dropped.\n", ctx->name, todo);
 | 
			
		||||
	else
 | 
			
		||||
		dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
 | 
			
		||||
	dprintk(3, "[%s] %d bytes are copied\n", ctx->name, len - todo);
 | 
			
		||||
	return (len - todo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	/* Adjust size to a sane value */
 | 
			
		||||
	if (req->size > DVB_V2_MAX_SIZE)
 | 
			
		||||
		req->size = DVB_V2_MAX_SIZE;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: round req->size to a 188 or 204 multiple */
 | 
			
		||||
 | 
			
		||||
	ctx->buf_siz = req->size;
 | 
			
		||||
	ctx->buf_cnt = req->count;
 | 
			
		||||
	ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, 0, &req->count);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		ctx->state = DVB_VB2_STATE_NONE;
 | 
			
		||||
		dprintk(1, "[%s] count=%d size=%d errno=%d\n", ctx->name,
 | 
			
		||||
			ctx->buf_cnt, ctx->buf_siz, ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	ctx->state |= DVB_VB2_STATE_REQBUFS;
 | 
			
		||||
	dprintk(3, "[%s] count=%d size=%d\n", ctx->name,
 | 
			
		||||
		ctx->buf_cnt, ctx->buf_siz);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 | 
			
		||||
{
 | 
			
		||||
	vb2_core_querybuf(&ctx->vb_q, b->index, b);
 | 
			
		||||
	dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp)
 | 
			
		||||
{
 | 
			
		||||
	struct vb2_queue *q = &ctx->vb_q;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = vb2_core_expbuf(&ctx->vb_q, &exp->fd, q->type, exp->index,
 | 
			
		||||
			      0, exp->flags);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
 | 
			
		||||
			exp->index, ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	dprintk(3, "[%s] index=%d fd=%d\n", ctx->name, exp->index, exp->fd);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
 | 
			
		||||
			b->index, ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	dprintk(5, "[%s] index=%d\n", ctx->name, b->index);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = vb2_core_dqbuf(&ctx->vb_q, &b->index, b, ctx->nonblocking);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&ctx->slock, flags);
 | 
			
		||||
	b->count = ctx->count++;
 | 
			
		||||
	b->flags = ctx->flags;
 | 
			
		||||
	ctx->flags = 0;
 | 
			
		||||
	spin_unlock_irqrestore(&ctx->slock, flags);
 | 
			
		||||
 | 
			
		||||
	dprintk(5, "[%s] index=%d, count=%d, flags=%d\n",
 | 
			
		||||
		ctx->name, b->index, ctx->count, b->flags);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_vb2_mmap(struct dvb_vb2_ctx *ctx, struct vm_area_struct *vma)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = vb2_mmap(&ctx->vb_q, vma);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		dprintk(1, "[%s] errno=%d\n", ctx->name, ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
	dprintk(3, "[%s] ret=%d\n", ctx->name, ret);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx, struct file *file,
 | 
			
		||||
		      poll_table *wait)
 | 
			
		||||
{
 | 
			
		||||
	dprintk(3, "[%s]\n", ctx->name);
 | 
			
		||||
	return vb2_core_poll(&ctx->vb_q, file, wait);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/i2c.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/device.h>
 | 
			
		||||
@@ -31,7 +32,7 @@
 | 
			
		||||
#include <linux/cdev.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include "dvbdev.h"
 | 
			
		||||
#include <media/dvbdev.h>
 | 
			
		||||
 | 
			
		||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,0,0))
 | 
			
		||||
/* Due to enum tuner_pad_index */
 | 
			
		||||
@@ -54,8 +55,19 @@ static LIST_HEAD(dvb_adapter_list);
 | 
			
		||||
static DEFINE_MUTEX(dvbdev_register_lock);
 | 
			
		||||
 | 
			
		||||
static const char * const dnames[] = {
 | 
			
		||||
	"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
 | 
			
		||||
	"net", "osd", "ci", "mod", "ns", "nsd"
 | 
			
		||||
	[DVB_DEVICE_VIDEO] =		"video",
 | 
			
		||||
	[DVB_DEVICE_AUDIO] =		"audio",
 | 
			
		||||
	[DVB_DEVICE_SEC] =		"sec",
 | 
			
		||||
	[DVB_DEVICE_FRONTEND] =		"frontend",
 | 
			
		||||
	[DVB_DEVICE_DEMUX] =		"demux",
 | 
			
		||||
	[DVB_DEVICE_DVR] =		"dvr",
 | 
			
		||||
	[DVB_DEVICE_CA] =		"ca",
 | 
			
		||||
	[DVB_DEVICE_NET] =		"net",
 | 
			
		||||
	[DVB_DEVICE_OSD] =		"osd",
 | 
			
		||||
	[DVB_DEVICE_CI] =		"ci",
 | 
			
		||||
	[DVB_DEVICE_MOD] =		"mod",
 | 
			
		||||
	[DVB_DEVICE_NS] =		"ns",
 | 
			
		||||
	[DVB_DEVICE_NSD] =		"nsd",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_DYNAMIC_MINORS
 | 
			
		||||
@@ -63,7 +75,22 @@ static const char * const dnames[] = {
 | 
			
		||||
#define DVB_MAX_IDS		MAX_DVB_MINORS
 | 
			
		||||
#else
 | 
			
		||||
#define DVB_MAX_IDS		4
 | 
			
		||||
#define nums2minor(num, type, id)	((num << 6) | (id << 4) | type)
 | 
			
		||||
 | 
			
		||||
static const u8 minor_type[] = {
 | 
			
		||||
       [DVB_DEVICE_VIDEO]      = 0,
 | 
			
		||||
       [DVB_DEVICE_AUDIO]      = 1,
 | 
			
		||||
       [DVB_DEVICE_SEC]        = 2,
 | 
			
		||||
       [DVB_DEVICE_FRONTEND]   = 3,
 | 
			
		||||
       [DVB_DEVICE_DEMUX]      = 4,
 | 
			
		||||
       [DVB_DEVICE_DVR]        = 5,
 | 
			
		||||
       [DVB_DEVICE_CA]         = 6,
 | 
			
		||||
       [DVB_DEVICE_NET]        = 7,
 | 
			
		||||
       [DVB_DEVICE_OSD]        = 8,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define nums2minor(num, type, id) \
 | 
			
		||||
       (((num) << 6) | ((id) << 4) | minor_type[type])
 | 
			
		||||
 | 
			
		||||
#define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -319,9 +346,11 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
 | 
			
		||||
	if (npads) {
 | 
			
		||||
		dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
 | 
			
		||||
				       GFP_KERNEL);
 | 
			
		||||
		if (!dvbdev->pads)
 | 
			
		||||
		if (!dvbdev->pads){
 | 
			
		||||
			kfree(dvbdev->entity);
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case DVB_DEVICE_FRONTEND:
 | 
			
		||||
@@ -420,8 +449,10 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
 | 
			
		||||
	if (!dvbdev->entity)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	link = media_create_intf_link(dvbdev->entity, &dvbdev->intf_devnode->intf,
 | 
			
		||||
				      MEDIA_LNK_FL_ENABLED);
 | 
			
		||||
	link = media_create_intf_link(dvbdev->entity,
 | 
			
		||||
				      &dvbdev->intf_devnode->intf,
 | 
			
		||||
				      MEDIA_LNK_FL_ENABLED |
 | 
			
		||||
				      MEDIA_LNK_FL_IMMUTABLE);
 | 
			
		||||
	if (!link)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
#endif
 | 
			
		||||
@@ -429,8 +460,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 | 
			
		||||
			const struct dvb_device *template, void *priv, int type,
 | 
			
		||||
			int demux_sink_pads)
 | 
			
		||||
			const struct dvb_device *template, void *priv,
 | 
			
		||||
			enum dvb_device_type type, int demux_sink_pads)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_device *dvbdev;
 | 
			
		||||
	struct file_operations *dvbdevfops;
 | 
			
		||||
@@ -454,7 +485,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
 | 
			
		||||
	dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
 | 
			
		||||
 | 
			
		||||
	if (!dvbdevfops){
 | 
			
		||||
		kfree (dvbdev);
 | 
			
		||||
@@ -470,7 +501,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 | 
			
		||||
	dvbdev->fops = dvbdevfops;
 | 
			
		||||
	init_waitqueue_head (&dvbdev->wait_queue);
 | 
			
		||||
 | 
			
		||||
	memcpy(dvbdevfops, template->fops, sizeof(struct file_operations));
 | 
			
		||||
	dvbdevfops->owner = adap->module;
 | 
			
		||||
 | 
			
		||||
	list_add_tail (&dvbdev->list_head, &adap->device_list);
 | 
			
		||||
@@ -504,7 +534,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 | 
			
		||||
		dvb_media_device_free(dvbdev);
 | 
			
		||||
		kfree(dvbdevfops);
 | 
			
		||||
		kfree(dvbdev);
 | 
			
		||||
		up_write(&minor_rwsem);
 | 
			
		||||
		mutex_unlock(&dvbdev_register_lock);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
@@ -579,7 +608,8 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
 | 
			
		||||
			if (strncmp(entity->name, name, strlen(name)))
 | 
			
		||||
				continue;
 | 
			
		||||
			link = media_create_intf_link(entity, intf,
 | 
			
		||||
						      MEDIA_LNK_FL_ENABLED);
 | 
			
		||||
						      MEDIA_LNK_FL_ENABLED |
 | 
			
		||||
						      MEDIA_LNK_FL_IMMUTABLE);
 | 
			
		||||
			if (!link)
 | 
			
		||||
				return -ENOMEM;
 | 
			
		||||
		}
 | 
			
		||||
@@ -598,8 +628,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;
 | 
			
		||||
	int ret, pad_source, pad_sink;
 | 
			
		||||
	static const char *connector_name = "Television";
 | 
			
		||||
 | 
			
		||||
	if (!mdev)
 | 
			
		||||
@@ -660,17 +689,6 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 | 
			
		||||
			return ret;
 | 
			
		||||
		
 | 
			
		||||
		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,
 | 
			
		||||
@@ -679,32 +697,40 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 | 
			
		||||
						     MEDIA_LNK_FL_ENABLED,
 | 
			
		||||
						     false);
 | 
			
		||||
		} else {
 | 
			
		||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0))
 | 
			
		||||
			pad_sink = media_get_pad_index(tuner, true,
 | 
			
		||||
						       PAD_SIGNAL_ANALOG);
 | 
			
		||||
			if (pad_sink < 0)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			ret = media_create_pad_links(mdev,
 | 
			
		||||
						     MEDIA_ENT_F_CONN_RF,
 | 
			
		||||
						     conn, 0,
 | 
			
		||||
						     MEDIA_ENT_F_TUNER,
 | 
			
		||||
						     tuner, source_pad,
 | 
			
		||||
						     tuner, pad_sink,
 | 
			
		||||
						     MEDIA_LNK_FL_ENABLED,
 | 
			
		||||
						     false);
 | 
			
		||||
#else
 | 
			
		||||
			pad_sink = TUNER_PAD_RF_INPUT;
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
		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;
 | 
			
		||||
		/* NOTE: first found tuner source pad presumed correct */
 | 
			
		||||
		pad_source = media_get_pad_index(tuner, false,
 | 
			
		||||
						 PAD_SIGNAL_ANALOG);
 | 
			
		||||
		if (pad_source < 0)
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
#else
 | 
			
		||||
		source_pad = TUNER_PAD_OUTPUT;
 | 
			
		||||
		pad_source = TUNER_PAD_OUTPUT;
 | 
			
		||||
#endif
 | 
			
		||||
		
 | 
			
		||||
		ret = media_create_pad_links(mdev,
 | 
			
		||||
					     MEDIA_ENT_F_TUNER,
 | 
			
		||||
					     tuner, source_pad,
 | 
			
		||||
					     tuner, pad_source,
 | 
			
		||||
					     MEDIA_ENT_F_DTV_DEMOD,
 | 
			
		||||
					     demod, 0, MEDIA_LNK_FL_ENABLED,
 | 
			
		||||
					     false);
 | 
			
		||||
@@ -757,14 +783,16 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 | 
			
		||||
	media_device_for_each_intf(intf, mdev) {
 | 
			
		||||
		if (intf->type == MEDIA_INTF_T_DVB_CA && ca) {
 | 
			
		||||
			link = media_create_intf_link(ca, intf,
 | 
			
		||||
						      MEDIA_LNK_FL_ENABLED);
 | 
			
		||||
						      MEDIA_LNK_FL_ENABLED |
 | 
			
		||||
						      MEDIA_LNK_FL_IMMUTABLE);
 | 
			
		||||
			if (!link)
 | 
			
		||||
				return -ENOMEM;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (intf->type == MEDIA_INTF_T_DVB_FE && tuner) {
 | 
			
		||||
			link = media_create_intf_link(tuner, intf,
 | 
			
		||||
						      MEDIA_LNK_FL_ENABLED);
 | 
			
		||||
						      MEDIA_LNK_FL_ENABLED |
 | 
			
		||||
						      MEDIA_LNK_FL_IMMUTABLE);
 | 
			
		||||
			if (!link)
 | 
			
		||||
				return -ENOMEM;
 | 
			
		||||
		}
 | 
			
		||||
@@ -776,7 +804,8 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 | 
			
		||||
		 */
 | 
			
		||||
		if (intf->type == MEDIA_INTF_T_DVB_DVR && demux) {
 | 
			
		||||
			link = media_create_intf_link(demux, intf,
 | 
			
		||||
						      MEDIA_LNK_FL_ENABLED);
 | 
			
		||||
						      MEDIA_LNK_FL_ENABLED |
 | 
			
		||||
						      MEDIA_LNK_FL_IMMUTABLE);
 | 
			
		||||
			if (!link)
 | 
			
		||||
				return -ENOMEM;
 | 
			
		||||
		}
 | 
			
		||||
@@ -862,6 +891,10 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
 | 
			
		||||
	adap->mfe_dvbdev = NULL;
 | 
			
		||||
	mutex_init (&adap->mfe_lock);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
 | 
			
		||||
	mutex_init(&adap->mdev_lock);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	list_add_tail (&adap->list_head, &dvb_adapter_list);
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&dvbdev_register_lock);
 | 
			
		||||
@@ -882,7 +915,7 @@ EXPORT_SYMBOL(dvb_unregister_adapter);
 | 
			
		||||
 | 
			
		||||
/* if the miracle happens and "generic_usercopy()" is included into
 | 
			
		||||
   the kernel, then this can vanish. please don't make the mistake and
 | 
			
		||||
   define this as video_usercopy(). this will introduce a dependecy
 | 
			
		||||
   define this as video_usercopy(). this will introduce a dependency
 | 
			
		||||
   to the v4l "videodev.o" module, which is unnecessary for some
 | 
			
		||||
   cards (ie. the budget dvb-cards don't need the v4l module...) */
 | 
			
		||||
int dvb_usercopy(struct file *file,
 | 
			
		||||
@@ -946,6 +979,57 @@ out:
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(dvb_usercopy);
 | 
			
		||||
 | 
			
		||||
#if IS_ENABLED(CONFIG_I2C)
 | 
			
		||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0))
 | 
			
		||||
struct i2c_client *dvb_module_probe(const char *module_name,
 | 
			
		||||
				    const char *name,
 | 
			
		||||
				    struct i2c_adapter *adap,
 | 
			
		||||
				    unsigned char addr,
 | 
			
		||||
				    void *platform_data)
 | 
			
		||||
{
 | 
			
		||||
 	struct i2c_client *client;
 | 
			
		||||
	struct i2c_board_info *board_info;
 | 
			
		||||
 | 
			
		||||
	board_info = kzalloc(sizeof(*board_info), GFP_KERNEL);
 | 
			
		||||
	if (!board_info)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (name)
 | 
			
		||||
		strscpy(board_info->type, name, I2C_NAME_SIZE);
 | 
			
		||||
	else
 | 
			
		||||
		strscpy(board_info->type, module_name, I2C_NAME_SIZE);
 | 
			
		||||
 | 
			
		||||
	board_info->addr = addr;
 | 
			
		||||
	board_info->platform_data = platform_data;
 | 
			
		||||
	request_module(module_name);
 | 
			
		||||
	client = i2c_new_client_device(adap, board_info);
 | 
			
		||||
	if (!i2c_client_has_driver(client)) {
 | 
			
		||||
		kfree(board_info);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!try_module_get(client->dev.driver->owner)) {
 | 
			
		||||
		i2c_unregister_device(client);
 | 
			
		||||
		client = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	kfree(board_info);
 | 
			
		||||
	return client;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(dvb_module_probe);
 | 
			
		||||
 | 
			
		||||
void dvb_module_release(struct i2c_client *client)
 | 
			
		||||
{
 | 
			
		||||
	if (!client)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	module_put(client->dev.driver->owner);
 | 
			
		||||
	i2c_unregister_device(client);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(dvb_module_release);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_device *dvbdev = dev_get_drvdata(dev);
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@ EXTRA_CFLAGS += -DCONFIG_DVB_LNBH25
 | 
			
		||||
EXTRA_CFLAGS += -DCONFIG_DVB_MXL5XX
 | 
			
		||||
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2099
 | 
			
		||||
EXTRA_CFLAGS += -DDBVALS
 | 
			
		||||
NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/dvb-core
 | 
			
		||||
 | 
			
		||||
drxk-objs := drxk_hard.o 
 | 
			
		||||
obj-$(CONFIG_DVB_DRXK) += drxk.o
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
#ifndef _CXD2099_H_
 | 
			
		||||
#define _CXD2099_H_
 | 
			
		||||
 | 
			
		||||
#include <dvb_ca_en50221.h>
 | 
			
		||||
#include <media/dvb_ca_en50221.h>
 | 
			
		||||
 | 
			
		||||
struct cxd2099_cfg {
 | 
			
		||||
	u32 bitrate;
 | 
			
		||||
 
 | 
			
		||||
@@ -35,8 +35,8 @@
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include "dvb_math.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
#include <media/dvb_math.h>
 | 
			
		||||
#include "cxd2843.h"
 | 
			
		||||
 | 
			
		||||
#define Log10x100(x) ((s32)(((((u64) intlog2(x) * 0x1e1a5e2e) >> 47 ) + 1) >> 1))
 | 
			
		||||
@@ -105,8 +105,12 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
 | 
			
		||||
static int writeregs(struct cxd_state *state, u8 adr, u8 reg,
 | 
			
		||||
		     u8 *regd, u16 len)
 | 
			
		||||
{
 | 
			
		||||
	u8 data[len + 1];
 | 
			
		||||
	u8 data[16];
 | 
			
		||||
 | 
			
		||||
	if (len >= 15) {
 | 
			
		||||
		pr_err("cxd2843: writeregs length %u too large\n", len);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	data[0] = reg;
 | 
			
		||||
	memcpy(data + 1, regd, len);
 | 
			
		||||
	return i2c_write(state->i2c, adr, data, len + 1);
 | 
			
		||||
@@ -2240,7 +2244,7 @@ static enum dvbfe_search search(struct dvb_frontend *fe)
 | 
			
		||||
		return DVBFE_ALGO_SEARCH_AGAIN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_algo(struct dvb_frontend *fe)
 | 
			
		||||
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	return DVBFE_ALGO_HW;
 | 
			
		||||
}
 | 
			
		||||
@@ -2489,9 +2493,9 @@ static struct dvb_frontend_ops common_ops_2854 = {
 | 
			
		||||
	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2, SYS_ISDBT },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "CXD2854 DVB-C/C2 DVB-T/T2 ISDB-T",
 | 
			
		||||
		.frequency_stepsize = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.frequency_stepsize_hz = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.symbol_rate_min = 870000,
 | 
			
		||||
		.symbol_rate_max = 11700000,
 | 
			
		||||
		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
 | 
			
		||||
@@ -2502,7 +2506,8 @@ static struct dvb_frontend_ops common_ops_2854 = {
 | 
			
		||||
			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 | 
			
		||||
			FE_CAN_TRANSMISSION_MODE_AUTO |
 | 
			
		||||
			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
 | 
			
		||||
			FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
 | 
			
		||||
			FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION |
 | 
			
		||||
		        FE_CAN_MULTISTREAM
 | 
			
		||||
	},
 | 
			
		||||
	.release = release,
 | 
			
		||||
	.sleep = sleep,
 | 
			
		||||
@@ -2522,9 +2527,9 @@ static struct dvb_frontend_ops common_ops_2843 = {
 | 
			
		||||
	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2, SYS_DVBC2 },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "CXD2843 DVB-C/C2 DVB-T/T2",
 | 
			
		||||
		.frequency_stepsize = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.frequency_stepsize_hz = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.symbol_rate_min = 870000,
 | 
			
		||||
		.symbol_rate_max = 11700000,
 | 
			
		||||
		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
 | 
			
		||||
@@ -2535,7 +2540,8 @@ static struct dvb_frontend_ops common_ops_2843 = {
 | 
			
		||||
			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 | 
			
		||||
			FE_CAN_TRANSMISSION_MODE_AUTO |
 | 
			
		||||
			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
 | 
			
		||||
			FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
 | 
			
		||||
			FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION |
 | 
			
		||||
		        FE_CAN_MULTISTREAM
 | 
			
		||||
	},
 | 
			
		||||
	.release = release,
 | 
			
		||||
	.sleep = sleep,
 | 
			
		||||
@@ -2560,9 +2566,9 @@ static struct dvb_frontend_ops common_ops_2837 = {
 | 
			
		||||
	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT, SYS_DVBT2 },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "CXD2837 DVB-C DVB-T/T2",
 | 
			
		||||
		.frequency_stepsize = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.frequency_stepsize_hz = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.symbol_rate_min = 870000,
 | 
			
		||||
		.symbol_rate_max = 11700000,
 | 
			
		||||
		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
 | 
			
		||||
@@ -2573,7 +2579,8 @@ static struct dvb_frontend_ops common_ops_2837 = {
 | 
			
		||||
			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 | 
			
		||||
			FE_CAN_TRANSMISSION_MODE_AUTO |
 | 
			
		||||
			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
 | 
			
		||||
			FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
 | 
			
		||||
			FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION |
 | 
			
		||||
		        FE_CAN_MULTISTREAM
 | 
			
		||||
	},
 | 
			
		||||
	.release = release,
 | 
			
		||||
	.sleep = sleep,
 | 
			
		||||
@@ -2598,9 +2605,9 @@ static struct dvb_frontend_ops common_ops_2838 = {
 | 
			
		||||
	.delsys = { SYS_ISDBT },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "CXD2838 ISDB-T",
 | 
			
		||||
		.frequency_stepsize = 166667,
 | 
			
		||||
		.frequency_min = 47000000,
 | 
			
		||||
		.frequency_max = 865000000,
 | 
			
		||||
		.frequency_stepsize_hz = 166667,
 | 
			
		||||
		.frequency_min_hz = 47000000,
 | 
			
		||||
		.frequency_max_hz = 865000000,
 | 
			
		||||
		.symbol_rate_min = 870000,
 | 
			
		||||
		.symbol_rate_max = 11700000,
 | 
			
		||||
		.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
#include "drxk.h"
 | 
			
		||||
#include "drxk_hard.h"
 | 
			
		||||
 | 
			
		||||
@@ -2804,10 +2804,12 @@ static int DVBTScCommand(struct drxk_state *state,
 | 
			
		||||
	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
 | 
			
		||||
		status = Write16_0(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
 | 
			
		||||
		/* All commands using 1 parameters */
 | 
			
		||||
		/* fall through */
 | 
			
		||||
	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
 | 
			
		||||
	case OFDM_SC_RA_RAM_CMD_USER_IO:
 | 
			
		||||
		status = Write16_0(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
 | 
			
		||||
		/* All commands using 0 parameters */
 | 
			
		||||
		/* fall through */
 | 
			
		||||
	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
 | 
			
		||||
	case OFDM_SC_RA_RAM_CMD_NULL:
 | 
			
		||||
		/* Write command */
 | 
			
		||||
@@ -3215,7 +3217,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
 | 
			
		||||
		case TRANSMISSION_MODE_AUTO:
 | 
			
		||||
		default:
 | 
			
		||||
			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
 | 
			
		||||
			/* fall through , try first guess DRX_FFTMODE_8K */
 | 
			
		||||
			/* try first guess DRX_FFTMODE_8K */
 | 
			
		||||
			/* fall through */
 | 
			
		||||
		case TRANSMISSION_MODE_8K:
 | 
			
		||||
			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -3233,7 +3236,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
 | 
			
		||||
		default:
 | 
			
		||||
		case GUARD_INTERVAL_AUTO:
 | 
			
		||||
			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
 | 
			
		||||
			/* fall through , try first guess DRX_GUARD_1DIV4 */
 | 
			
		||||
			/* try first guess DRX_GUARD_1DIV4 */
 | 
			
		||||
			/* fall through */
 | 
			
		||||
		case GUARD_INTERVAL_1_4:
 | 
			
		||||
			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -3258,9 +3262,10 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
 | 
			
		||||
		case 	HIERARCHY_NONE:
 | 
			
		||||
		default:
 | 
			
		||||
			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M;
 | 
			
		||||
			/* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
 | 
			
		||||
			/* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
 | 
			
		||||
			//	transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO;
 | 
			
		||||
			//break;
 | 
			
		||||
			/* fall through */
 | 
			
		||||
		case 	HIERARCHY_1:
 | 
			
		||||
			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -3282,7 +3287,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
 | 
			
		||||
		case QAM_AUTO:
 | 
			
		||||
		default:
 | 
			
		||||
			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
 | 
			
		||||
			/* fall through , try first guess DRX_CONSTELLATION_QAM64 */
 | 
			
		||||
			/* try first guess DRX_CONSTELLATION_QAM64 */
 | 
			
		||||
			/* fall through */
 | 
			
		||||
		case QAM_64:
 | 
			
		||||
			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -3325,7 +3331,8 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
 | 
			
		||||
		case FEC_AUTO:
 | 
			
		||||
		default:
 | 
			
		||||
			operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
 | 
			
		||||
			/* fall through , try first guess DRX_CODERATE_2DIV3 */
 | 
			
		||||
			/* try first guess DRX_CODERATE_2DIV3 */
 | 
			
		||||
			/* fall through */
 | 
			
		||||
		case FEC_2_3  :
 | 
			
		||||
			transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
 | 
			
		||||
			break;
 | 
			
		||||
@@ -4994,12 +5001,12 @@ static int drxk_t_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_prop
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct dvb_frontend_ops drxk_c_ops = {
 | 
			
		||||
	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "DRXK DVB-C",
 | 
			
		||||
		.type = FE_QAM,
 | 
			
		||||
		.frequency_stepsize = 62500,
 | 
			
		||||
		.frequency_min = 47000000,
 | 
			
		||||
		.frequency_max = 862000000,
 | 
			
		||||
		.frequency_stepsize_hz = 62500,
 | 
			
		||||
		.frequency_min_hz = 47000000,
 | 
			
		||||
		.frequency_max_hz = 862000000,
 | 
			
		||||
		.symbol_rate_min = 870000,
 | 
			
		||||
		.symbol_rate_max = 11700000,
 | 
			
		||||
		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
 | 
			
		||||
@@ -5022,13 +5029,13 @@ static struct dvb_frontend_ops drxk_c_ops = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct dvb_frontend_ops drxk_t_ops = {
 | 
			
		||||
	.delsys = { SYS_DVBT },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name			= "DRXK DVB-T",
 | 
			
		||||
		.type			= FE_OFDM,
 | 
			
		||||
		.frequency_min		= 47125000,
 | 
			
		||||
		.frequency_max		= 865000000,
 | 
			
		||||
		.frequency_stepsize	= 166667,
 | 
			
		||||
		.frequency_tolerance	= 0,
 | 
			
		||||
		.frequency_min_hz	= 47125000,
 | 
			
		||||
		.frequency_max_hz	= 865000000,
 | 
			
		||||
		.frequency_stepsize_hz	= 166667,
 | 
			
		||||
		.frequency_tolerance_hz	= 0,
 | 
			
		||||
		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
 | 
			
		||||
		FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
 | 
			
		||||
		FE_CAN_FEC_AUTO |
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
#include "lnbh25.h"
 | 
			
		||||
 | 
			
		||||
struct lnbh25 {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
#include "lnbp21.h"
 | 
			
		||||
#include "lnbh24.h"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
#include <asm/unaligned.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
#include "mxl5xx.h"
 | 
			
		||||
#include "mxl5xx_regs.h"
 | 
			
		||||
#include "mxl5xx_defs.h"
 | 
			
		||||
@@ -357,19 +357,6 @@ 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)
 | 
			
		||||
{
 | 
			
		||||
	if (toAddr)
 | 
			
		||||
		*toAddr = regAddr;
 | 
			
		||||
	if (toLsbPos)
 | 
			
		||||
		*toLsbPos = lsbPos;
 | 
			
		||||
	if (toWidth)
 | 
			
		||||
		*toWidth = width;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int firmware_is_alive(struct mxl *state)
 | 
			
		||||
{
 | 
			
		||||
	u32 hb0, hb1;
 | 
			
		||||
@@ -379,10 +366,10 @@ static int firmware_is_alive(struct mxl *state)
 | 
			
		||||
	msleep(20);
 | 
			
		||||
	if (read_register(state, HYDRA_HEAR_BEAT, &hb1))
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (hb1 == hb0)
 | 
			
		||||
	if (hb1 == hb0) {
 | 
			
		||||
		pr_warn("mxl5xx: Hydra FW not running!\n");
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	pr_info("mxl5xx: Hydra FW alive. Hail!\n");
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -405,7 +392,7 @@ static void release(struct dvb_frontend *fe)
 | 
			
		||||
	kfree(state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_algo(struct dvb_frontend *fe)
 | 
			
		||||
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	return DVBFE_ALGO_HW;
 | 
			
		||||
}
 | 
			
		||||
@@ -799,6 +786,7 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case SYS_DVBS:
 | 
			
		||||
		switch ((MXL_HYDRA_MODULATION_E)
 | 
			
		||||
			regData[DMD_MODULATION_SCHEME_ADDR]) {
 | 
			
		||||
@@ -846,10 +834,10 @@ static struct dvb_frontend_ops mxl_ops = {
 | 
			
		||||
	.xbar   = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name			= "MXL5XX",
 | 
			
		||||
		.frequency_min		= 300000,
 | 
			
		||||
		.frequency_max		= 2350000,
 | 
			
		||||
		.frequency_stepsize	= 0,
 | 
			
		||||
		.frequency_tolerance	= 0,
 | 
			
		||||
		.frequency_min_hz	= 300000000,
 | 
			
		||||
		.frequency_max_hz	= 2350000000,
 | 
			
		||||
		.frequency_stepsize_hz	= 0,
 | 
			
		||||
		.frequency_tolerance_hz	= 0,
 | 
			
		||||
		.symbol_rate_min	= 1000000,
 | 
			
		||||
		.symbol_rate_max	= 45000000,
 | 
			
		||||
		.caps			= FE_CAN_INVERSION_AUTO |
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
#include "stv0367dd.h"
 | 
			
		||||
#include "stv0367dd_regs.h"
 | 
			
		||||
 | 
			
		||||
@@ -2074,9 +2074,9 @@ static struct dvb_frontend_ops common_ops = {
 | 
			
		||||
	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "STV0367 DVB-C DVB-T",
 | 
			
		||||
		.frequency_stepsize = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.frequency_stepsize_hz = 166667,	/* DVB-T only */
 | 
			
		||||
		.frequency_min_hz = 47000000,	/* DVB-T: 47125000 */
 | 
			
		||||
		.frequency_max_hz = 865000000,	/* DVB-C: 862000000 */
 | 
			
		||||
		.symbol_rate_min = 870000,
 | 
			
		||||
		.symbol_rate_max = 11700000,
 | 
			
		||||
		.caps = /* DVB-C */
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/dvb/frontend.h>
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
 | 
			
		||||
#include "stv6110x.h" /* for demodulator internal modes */
 | 
			
		||||
 | 
			
		||||
@@ -5142,10 +5142,10 @@ static struct dvb_frontend_ops stv090x_ops = {
 | 
			
		||||
#ifdef USE_API3
 | 
			
		||||
		.type			= FE_QPSK,
 | 
			
		||||
#endif
 | 
			
		||||
		.frequency_min		= 950000,
 | 
			
		||||
		.frequency_max 		= 2150000,
 | 
			
		||||
		.frequency_stepsize	= 0,
 | 
			
		||||
		.frequency_tolerance	= 0,
 | 
			
		||||
		.frequency_min_hz	= 950000000,
 | 
			
		||||
		.frequency_max_hz	= 2150000000,
 | 
			
		||||
		.frequency_stepsize_hz	= 0,
 | 
			
		||||
		.frequency_tolerance_hz	= 0,
 | 
			
		||||
		.symbol_rate_min 	= 1000000,
 | 
			
		||||
		.symbol_rate_max 	= 45000000,
 | 
			
		||||
		.caps			= FE_CAN_INVERSION_AUTO |
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@
 | 
			
		||||
#ifndef __STV090x_PRIV_H
 | 
			
		||||
#define __STV090x_PRIV_H
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
 | 
			
		||||
#define FE_ERROR				0
 | 
			
		||||
#define FE_NOTICE				1
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
#include "stv0910.h"
 | 
			
		||||
#include "stv0910_regs.h"
 | 
			
		||||
 | 
			
		||||
@@ -1581,7 +1581,7 @@ static int tune(struct dvb_frontend *fe, bool re_tune,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_algo(struct dvb_frontend *fe)
 | 
			
		||||
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	return DVBFE_ALGO_HW;
 | 
			
		||||
}
 | 
			
		||||
@@ -1801,10 +1801,10 @@ static struct dvb_frontend_ops stv0910_ops = {
 | 
			
		||||
	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name			= "STV0910",
 | 
			
		||||
		.frequency_min		= 950000,
 | 
			
		||||
		.frequency_max		= 2150000,
 | 
			
		||||
		.frequency_stepsize	= 0,
 | 
			
		||||
		.frequency_tolerance	= 0,
 | 
			
		||||
		.frequency_min_hz		= 950000000,
 | 
			
		||||
		.frequency_max_hz		= 2150000000,
 | 
			
		||||
		.frequency_stepsize_hz	= 0,
 | 
			
		||||
		.frequency_tolerance_hz	= 0,
 | 
			
		||||
		.symbol_rate_min	= 100000,
 | 
			
		||||
		.symbol_rate_max	= 70000000,
 | 
			
		||||
		.caps			= FE_CAN_INVERSION_AUTO |
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
 | 
			
		||||
#include "stv6110x_reg.h"
 | 
			
		||||
#include "stv6110x.h"
 | 
			
		||||
@@ -346,9 +346,9 @@ static void stv6110x_release(struct dvb_frontend *fe)
 | 
			
		||||
static const struct dvb_tuner_ops stv6110x_ops = {
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name		   = "STV6110(A) Silicon Tuner",
 | 
			
		||||
		.frequency_min	=  950000,
 | 
			
		||||
		.frequency_max	= 2150000,
 | 
			
		||||
		.frequency_step	= 0,
 | 
			
		||||
		.frequency_min_hz  =  950000000,
 | 
			
		||||
		.frequency_max_hz  = 2150000000,
 | 
			
		||||
		.frequency_step_hz = 0,
 | 
			
		||||
	},
 | 
			
		||||
	.release		= stv6110x_release
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
 | 
			
		||||
static inline u32 MulDiv32(u32 a, u32 b, u32 c)
 | 
			
		||||
{
 | 
			
		||||
@@ -706,9 +706,9 @@ static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 | 
			
		||||
static struct dvb_tuner_ops tuner_ops = {
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "STV6111",
 | 
			
		||||
		.frequency_min  =  950000,
 | 
			
		||||
		.frequency_max  = 2150000,
 | 
			
		||||
		.frequency_step =       0
 | 
			
		||||
		.frequency_min_hz  =  950000000,
 | 
			
		||||
		.frequency_max_hz  = 2150000000,
 | 
			
		||||
		.frequency_step_hz =       0
 | 
			
		||||
	},
 | 
			
		||||
	.init              = init,
 | 
			
		||||
	.sleep             = sleep,
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
 | 
			
		||||
#ifndef CHK_ERROR
 | 
			
		||||
#define CHK_ERROR(s) if ((status = s) < 0) break
 | 
			
		||||
@@ -889,9 +889,9 @@ static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 | 
			
		||||
static struct dvb_tuner_ops tuner_ops = {
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "NXP TDA18212",
 | 
			
		||||
		.frequency_min  =  47125000,
 | 
			
		||||
		.frequency_max  = 865000000,
 | 
			
		||||
		.frequency_step =     62500
 | 
			
		||||
		.frequency_min_hz  =  47125000,
 | 
			
		||||
		.frequency_max_hz  = 865000000,
 | 
			
		||||
		.frequency_step_hz =     62500
 | 
			
		||||
	},
 | 
			
		||||
	.init              = init,
 | 
			
		||||
	.sleep             = sleep,
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include <asm/div64.h>
 | 
			
		||||
 | 
			
		||||
#include "dvb_frontend.h"
 | 
			
		||||
#include <media/dvb_frontend.h>
 | 
			
		||||
 | 
			
		||||
struct SStandardParam {
 | 
			
		||||
	s32   m_IFFrequency;
 | 
			
		||||
@@ -1183,6 +1183,7 @@ static int set_params(struct dvb_frontend *fe,
 | 
			
		||||
 | 
			
		||||
	switch (delsys) {
 | 
			
		||||
	case  SYS_DVBT:
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case  SYS_DVBT2:
 | 
			
		||||
		switch (bw) {
 | 
			
		||||
		case 6000000:
 | 
			
		||||
@@ -1197,7 +1198,9 @@ static int set_params(struct dvb_frontend *fe,
 | 
			
		||||
		default:
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case SYS_DVBC_ANNEX_A:
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case SYS_DVBC_ANNEX_C:
 | 
			
		||||
		if (bw <= 6000000)
 | 
			
		||||
			Standard = HF_DVBC_6MHZ;
 | 
			
		||||
@@ -1292,9 +1295,9 @@ static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 | 
			
		||||
static struct dvb_tuner_ops tuner_ops = {
 | 
			
		||||
	.info = {
 | 
			
		||||
		.name = "NXP TDA18271C2D",
 | 
			
		||||
		.frequency_min  =  47125000,
 | 
			
		||||
		.frequency_max  = 865000000,
 | 
			
		||||
		.frequency_step =     62500
 | 
			
		||||
		.frequency_min_hz  =  47125000,
 | 
			
		||||
		.frequency_max_hz  = 865000000,
 | 
			
		||||
		.frequency_step_hz =     62500
 | 
			
		||||
	},
 | 
			
		||||
	.init              = init,
 | 
			
		||||
	.sleep             = sleep,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
 | 
			
		||||
/*
 | 
			
		||||
 * audio.h
 | 
			
		||||
 * audio.h - DEPRECATED MPEG-TS audio decoder API
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: should not be used on future drivers
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
 | 
			
		||||
 *                  & Marcus Metzler <marcus@convergence.de>
 | 
			
		||||
@@ -51,7 +54,7 @@ typedef enum {
 | 
			
		||||
typedef struct audio_mixer {
 | 
			
		||||
	unsigned int volume_left;
 | 
			
		||||
	unsigned int volume_right;
 | 
			
		||||
  // what else do we need? bass, pass-through, ...
 | 
			
		||||
/* what else do we need? bass, pass-through, ... */
 | 
			
		||||
} audio_mixer_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -66,27 +69,6 @@ typedef struct audio_status {
 | 
			
		||||
} audio_status_t;                              /* separate decoder hardware */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
struct audio_karaoke {  /* if Vocal1 or Vocal2 are non-zero, they get mixed  */
 | 
			
		||||
	int vocal1;    /* into left and right t at 70% each */
 | 
			
		||||
	int vocal2;    /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets*/
 | 
			
		||||
	int melody;    /* mixed into the left channel and */
 | 
			
		||||
		       /* Vocal2 into the right channel at 100% each. */
 | 
			
		||||
		       /* if Melody is non-zero, the melody channel gets mixed*/
 | 
			
		||||
} audio_karaoke_t;     /* into left and right  */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef __u16 audio_attributes_t;
 | 
			
		||||
/*   bits: descr. */
 | 
			
		||||
/*   15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, */
 | 
			
		||||
/*   12    multichannel extension */
 | 
			
		||||
/*   11-10 audio type (0=not spec, 1=language included) */
 | 
			
		||||
/*    9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) */
 | 
			
		||||
/*    7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit,  */
 | 
			
		||||
/*    5- 4 Sample frequency fs (0=48kHz, 1=96kHz) */
 | 
			
		||||
/*    2- 0 number of audio channels (n+1 channels) */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */
 | 
			
		||||
#define AUDIO_CAP_DTS    1
 | 
			
		||||
#define AUDIO_CAP_LPCM   2
 | 
			
		||||
@@ -114,22 +96,6 @@ typedef __u16 audio_attributes_t;
 | 
			
		||||
#define AUDIO_SET_ID               _IO('o', 13)
 | 
			
		||||
#define AUDIO_SET_MIXER            _IOW('o', 14, audio_mixer_t)
 | 
			
		||||
#define AUDIO_SET_STREAMTYPE       _IO('o', 15)
 | 
			
		||||
#define AUDIO_SET_EXT_ID           _IO('o', 16)
 | 
			
		||||
#define AUDIO_SET_ATTRIBUTES       _IOW('o', 17, audio_attributes_t)
 | 
			
		||||
#define AUDIO_SET_KARAOKE          _IOW('o', 18, audio_karaoke_t)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * AUDIO_GET_PTS
 | 
			
		||||
 *
 | 
			
		||||
 * Read the 33 bit presentation time stamp as defined
 | 
			
		||||
 * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
 | 
			
		||||
 *
 | 
			
		||||
 * The PTS should belong to the currently played
 | 
			
		||||
 * frame if possible, but may also be a value close to it
 | 
			
		||||
 * like the PTS of the last decoded frame or the last PTS
 | 
			
		||||
 * extracted by the PES parser.
 | 
			
		||||
 */
 | 
			
		||||
#define AUDIO_GET_PTS              _IOR('o', 19, __u64)
 | 
			
		||||
#define AUDIO_BILINGUAL_CHANNEL_SELECT _IO('o', 20)
 | 
			
		||||
 | 
			
		||||
#endif /* _DVBAUDIO_H_ */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
 | 
			
		||||
/*
 | 
			
		||||
 * ca.h
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
 | 
			
		||||
/*
 | 
			
		||||
 * dmx.h
 | 
			
		||||
 *
 | 
			
		||||
@@ -210,6 +211,96 @@ struct dmx_stc {
 | 
			
		||||
	__u64 stc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum dmx_buffer_flags - DMX memory-mapped buffer flags
 | 
			
		||||
 *
 | 
			
		||||
 * @DMX_BUFFER_FLAG_HAD_CRC32_DISCARD:
 | 
			
		||||
 *	Indicates that the Kernel discarded one or more frames due to wrong
 | 
			
		||||
 *	CRC32 checksum.
 | 
			
		||||
 * @DMX_BUFFER_FLAG_TEI:
 | 
			
		||||
 *	Indicates that the Kernel has detected a Transport Error indicator
 | 
			
		||||
 *	(TEI) on a filtered pid.
 | 
			
		||||
 * @DMX_BUFFER_PKT_COUNTER_MISMATCH:
 | 
			
		||||
 *	Indicates that the Kernel has detected a packet counter mismatch
 | 
			
		||||
 *	on a filtered pid.
 | 
			
		||||
 * @DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED:
 | 
			
		||||
 *	Indicates that the Kernel has detected one or more frame discontinuity.
 | 
			
		||||
 * @DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR:
 | 
			
		||||
 *	Received at least one packet with a frame discontinuity indicator.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
enum dmx_buffer_flags {
 | 
			
		||||
	DMX_BUFFER_FLAG_HAD_CRC32_DISCARD		= 1 << 0,
 | 
			
		||||
	DMX_BUFFER_FLAG_TEI				= 1 << 1,
 | 
			
		||||
	DMX_BUFFER_PKT_COUNTER_MISMATCH			= 1 << 2,
 | 
			
		||||
	DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED		= 1 << 3,
 | 
			
		||||
	DMX_BUFFER_FLAG_DISCONTINUITY_INDICATOR		= 1 << 4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dmx_buffer - dmx buffer info
 | 
			
		||||
 *
 | 
			
		||||
 * @index:	id number of the buffer
 | 
			
		||||
 * @bytesused:	number of bytes occupied by data in the buffer (payload);
 | 
			
		||||
 * @offset:	for buffers with memory == DMX_MEMORY_MMAP;
 | 
			
		||||
 *		offset from the start of the device memory for this plane,
 | 
			
		||||
 *		(or a "cookie" that should be passed to mmap() as offset)
 | 
			
		||||
 * @length:	size in bytes of the buffer
 | 
			
		||||
 * @flags:	bit array of buffer flags as defined by &enum dmx_buffer_flags.
 | 
			
		||||
 *		Filled only at &DMX_DQBUF.
 | 
			
		||||
 * @count:	monotonic counter for filled buffers. Helps to identify
 | 
			
		||||
 *		data stream loses. Filled only at &DMX_DQBUF.
 | 
			
		||||
 *
 | 
			
		||||
 * Contains data exchanged by application and driver using one of the streaming
 | 
			
		||||
 * I/O methods.
 | 
			
		||||
 *
 | 
			
		||||
 * Please notice that, for &DMX_QBUF, only @index should be filled.
 | 
			
		||||
 * On &DMX_DQBUF calls, all fields will be filled by the Kernel.
 | 
			
		||||
 */
 | 
			
		||||
struct dmx_buffer {
 | 
			
		||||
	__u32			index;
 | 
			
		||||
	__u32			bytesused;
 | 
			
		||||
	__u32			offset;
 | 
			
		||||
	__u32			length;
 | 
			
		||||
	__u32			flags;
 | 
			
		||||
	__u32			count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dmx_requestbuffers - request dmx buffer information
 | 
			
		||||
 *
 | 
			
		||||
 * @count:	number of requested buffers,
 | 
			
		||||
 * @size:	size in bytes of the requested buffer
 | 
			
		||||
 *
 | 
			
		||||
 * Contains data used for requesting a dmx buffer.
 | 
			
		||||
 * All reserved fields must be set to zero.
 | 
			
		||||
 */
 | 
			
		||||
struct dmx_requestbuffers {
 | 
			
		||||
	__u32			count;
 | 
			
		||||
	__u32			size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dmx_exportbuffer - export of dmx buffer as DMABUF file descriptor
 | 
			
		||||
 *
 | 
			
		||||
 * @index:	id number of the buffer
 | 
			
		||||
 * @flags:	flags for newly created file, currently only O_CLOEXEC is
 | 
			
		||||
 *		supported, refer to manual of open syscall for more details
 | 
			
		||||
 * @fd:		file descriptor associated with DMABUF (set by driver)
 | 
			
		||||
 *
 | 
			
		||||
 * Contains data used for exporting a dmx buffer as DMABUF file descriptor.
 | 
			
		||||
 * The buffer is identified by a 'cookie' returned by DMX_QUERYBUF
 | 
			
		||||
 * (identical to the cookie used to mmap() the buffer to userspace). All
 | 
			
		||||
 * reserved fields must be set to zero. The field reserved0 is expected to
 | 
			
		||||
 * become a structure 'type' allowing an alternative layout of the structure
 | 
			
		||||
 * content. Therefore this field should not be used for any other extensions.
 | 
			
		||||
 */
 | 
			
		||||
struct dmx_exportbuffer {
 | 
			
		||||
	__u32		index;
 | 
			
		||||
	__u32		flags;
 | 
			
		||||
	__s32		fd;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DMX_START                _IO('o', 41)
 | 
			
		||||
#define DMX_STOP                 _IO('o', 42)
 | 
			
		||||
#define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
 | 
			
		||||
@@ -230,4 +321,10 @@ typedef struct dmx_filter dmx_filter_t;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _UAPI_DVBDMX_H_ */
 | 
			
		||||
#define DMX_REQBUFS              _IOWR('o', 60, struct dmx_requestbuffers)
 | 
			
		||||
#define DMX_QUERYBUF             _IOWR('o', 61, struct dmx_buffer)
 | 
			
		||||
#define DMX_EXPBUF               _IOWR('o', 62, struct dmx_exportbuffer)
 | 
			
		||||
#define DMX_QBUF                 _IOWR('o', 63, struct dmx_buffer)
 | 
			
		||||
#define DMX_DQBUF                _IOWR('o', 64, struct dmx_buffer)
 | 
			
		||||
 | 
			
		||||
#endif /* _DVBDMX_H_ */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
 | 
			
		||||
/*
 | 
			
		||||
 * frontend.h
 | 
			
		||||
 *
 | 
			
		||||
@@ -769,16 +770,15 @@ enum fecap_scale_params {
 | 
			
		||||
/**
 | 
			
		||||
 * struct dtv_stats - Used for reading a DTV status property
 | 
			
		||||
 *
 | 
			
		||||
 * @scale:	Filled with enum fecap_scale_params - the scale
 | 
			
		||||
 *		in usage for that parameter
 | 
			
		||||
 * @scale:
 | 
			
		||||
 *    Filled with enum fecap_scale_params - the scale in usage
 | 
			
		||||
 *    for that parameter
 | 
			
		||||
 *
 | 
			
		||||
 * The ``{unnamed_union}`` may have either one of the values below:
 | 
			
		||||
 *
 | 
			
		||||
 * %svalue
 | 
			
		||||
 * @svalue:
 | 
			
		||||
 *	integer value of the measure, for %FE_SCALE_DECIBEL,
 | 
			
		||||
 *	used for dB measures. The unit is 0.001 dB.
 | 
			
		||||
 *
 | 
			
		||||
 * %uvalue
 | 
			
		||||
 * @uvalue:
 | 
			
		||||
 *	unsigned integer value of the measure, used when @scale is
 | 
			
		||||
 *	either %FE_SCALE_RELATIVE or %FE_SCALE_COUNTER.
 | 
			
		||||
 *
 | 
			
		||||
@@ -844,16 +844,16 @@ struct dtv_fe_stats {
 | 
			
		||||
 * @cmd:	Digital TV command.
 | 
			
		||||
 * @reserved:	Not used.
 | 
			
		||||
 * @u:		Union with the values for the command.
 | 
			
		||||
 * @result:	Result of the command set (currently unused).
 | 
			
		||||
 * @u.data:           A unsigned 32 bits integer with command value.
 | 
			
		||||
 * @u.buffer:         Struct to store bigger properties.
 | 
			
		||||
 *                    Currently unused.
 | 
			
		||||
 * @u.buffer.data:    an unsigned 32-bits array.
 | 
			
		||||
 * @u.buffer.len:     number of elements of the buffer.
 | 
			
		||||
 * @u.buffer.reserved1:       Reserved.
 | 
			
		||||
 * @u.buffer.reserved2:       Reserved.
 | 
			
		||||
 * @u.st:             a &struct dtv_fe_stats array of statistics.
 | 
			
		||||
 * @result:           Currently unused.
 | 
			
		||||
 *
 | 
			
		||||
 * The @u union may have either one of the values below:
 | 
			
		||||
 *
 | 
			
		||||
 * %data
 | 
			
		||||
 *	an unsigned 32-bits number.
 | 
			
		||||
 * %st
 | 
			
		||||
 *	a &struct dtv_fe_stats array of statistics.
 | 
			
		||||
 * %buffer
 | 
			
		||||
 *	a buffer of up to 32 characters (currently unused).
 | 
			
		||||
 */
 | 
			
		||||
struct dtv_property {
 | 
			
		||||
	__u32 cmd;
 | 
			
		||||
 
 | 
			
		||||
@@ -38,9 +38,14 @@ struct dvb_mod_channel_params {
 | 
			
		||||
 | 
			
		||||
enum mod_output_rate {
 | 
			
		||||
	SYS_DVBT_6 = 0,
 | 
			
		||||
	SYS_DVBT_7,
 | 
			
		||||
	SYS_DVBT_8,
 | 
			
		||||
	SYS_DVBT_7 = 1,
 | 
			
		||||
	SYS_DVBT_8 = 2,
 | 
			
		||||
	SYS_DVBC_6900 = 8,
 | 
			
		||||
	SYS_ISDBT_6 = 16,
 | 
			
		||||
	SYS_J83B_64_6 = 24,
 | 
			
		||||
	SYS_J83B_256_6 = 25,
 | 
			
		||||
	SYS_DVBS2_22 = 32,
 | 
			
		||||
	SYS_DVBS2_24 = 33,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
 | 
			
		||||
/*
 | 
			
		||||
 * net.h
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
 | 
			
		||||
/*
 | 
			
		||||
 * osd.h
 | 
			
		||||
 * osd.h - DEPRECATED On Screen Display API
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: should not be used on future drivers
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2001 Ralph  Metzler <ralph@convergence.de>
 | 
			
		||||
 *                  & Marcus Metzler <marcus@convergence.de>
 | 
			
		||||
@@ -26,79 +29,109 @@
 | 
			
		||||
 | 
			
		||||
#include <linux/compiler.h>
 | 
			
		||||
 | 
			
		||||
#ifndef __user
 | 
			
		||||
#define __user
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  // All functions return -2 on "not open"
 | 
			
		||||
  OSD_Close=1,    // ()
 | 
			
		||||
  // Disables OSD and releases the buffers
 | 
			
		||||
  // returns 0 on success
 | 
			
		||||
  OSD_Open,       // (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0))
 | 
			
		||||
  // Opens OSD with this size and bit depth
 | 
			
		||||
  // returns 0 on success, -1 on DRAM allocation error, -2 on "already open"
 | 
			
		||||
  OSD_Show,       // ()
 | 
			
		||||
  // enables OSD mode
 | 
			
		||||
  // returns 0 on success
 | 
			
		||||
  OSD_Hide,       // ()
 | 
			
		||||
  // disables OSD mode
 | 
			
		||||
  // returns 0 on success
 | 
			
		||||
  OSD_Clear,      // ()
 | 
			
		||||
  // Sets all pixel to color 0
 | 
			
		||||
  // returns 0 on success
 | 
			
		||||
  OSD_Fill,       // (color)
 | 
			
		||||
  // Sets all pixel to color <col>
 | 
			
		||||
  // returns 0 on success
 | 
			
		||||
  OSD_SetColor,   // (color,R{x0},G{y0},B{x1},opacity{y1})
 | 
			
		||||
  // set palette entry <num> to <r,g,b>, <mix> and <trans> apply
 | 
			
		||||
  // R,G,B: 0..255
 | 
			
		||||
  // R=Red, G=Green, B=Blue
 | 
			
		||||
  // opacity=0:      pixel opacity 0% (only video pixel shows)
 | 
			
		||||
  // opacity=1..254: pixel opacity as specified in header
 | 
			
		||||
  // opacity=255:    pixel opacity 100% (only OSD pixel shows)
 | 
			
		||||
  // returns 0 on success, -1 on error
 | 
			
		||||
  OSD_SetPalette, // (firstcolor{color},lastcolor{x0},data)
 | 
			
		||||
  // Set a number of entries in the palette
 | 
			
		||||
  // sets the entries "firstcolor" through "lastcolor" from the array "data"
 | 
			
		||||
  // data has 4 byte for each color:
 | 
			
		||||
  // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel
 | 
			
		||||
  OSD_SetTrans,   // (transparency{color})
 | 
			
		||||
  // Sets transparency of mixed pixel (0..15)
 | 
			
		||||
  // returns 0 on success
 | 
			
		||||
  OSD_SetPixel,   // (x0,y0,color)
 | 
			
		||||
  // sets pixel <x>,<y> to color number <col>
 | 
			
		||||
  // returns 0 on success, -1 on error
 | 
			
		||||
  OSD_GetPixel,   // (x0,y0)
 | 
			
		||||
  // returns color number of pixel <x>,<y>,  or -1
 | 
			
		||||
  OSD_SetRow,     // (x0,y0,x1,data)
 | 
			
		||||
  // fills pixels x0,y through  x1,y with the content of data[]
 | 
			
		||||
  // returns 0 on success, -1 on clipping all pixel (no pixel drawn)
 | 
			
		||||
  OSD_SetBlock,   // (x0,y0,x1,y1,increment{color},data)
 | 
			
		||||
  // fills pixels x0,y0 through  x1,y1 with the content of data[]
 | 
			
		||||
  // inc contains the width of one line in the data block,
 | 
			
		||||
  // inc<=0 uses blockwidth as linewidth
 | 
			
		||||
  // returns 0 on success, -1 on clipping all pixel
 | 
			
		||||
  OSD_FillRow,    // (x0,y0,x1,color)
 | 
			
		||||
  // fills pixels x0,y through  x1,y with the color <col>
 | 
			
		||||
  // returns 0 on success, -1 on clipping all pixel
 | 
			
		||||
  OSD_FillBlock,  // (x0,y0,x1,y1,color)
 | 
			
		||||
  // fills pixels x0,y0 through  x1,y1 with the color <col>
 | 
			
		||||
  // returns 0 on success, -1 on clipping all pixel
 | 
			
		||||
  OSD_Line,       // (x0,y0,x1,y1,color)
 | 
			
		||||
  // draw a line from x0,y0 to x1,y1 with the color <col>
 | 
			
		||||
  // returns 0 on success
 | 
			
		||||
  OSD_Query,      // (x0,y0,x1,y1,xasp{color}}), yasp=11
 | 
			
		||||
  // fills parameters with the picture dimensions and the pixel aspect ratio
 | 
			
		||||
  // returns 0 on success
 | 
			
		||||
  OSD_Test,       // ()
 | 
			
		||||
  // draws a test picture. for debugging purposes only
 | 
			
		||||
  // returns 0 on success
 | 
			
		||||
// TODO: remove "test" in final version
 | 
			
		||||
  OSD_Text,       // (x0,y0,size,color,text)
 | 
			
		||||
  OSD_SetWindow, //  (x0) set window with number 0<x0<8 as current
 | 
			
		||||
  OSD_MoveWindow, //  move current window to (x0, y0)
 | 
			
		||||
  OSD_OpenRaw,	// Open other types of OSD windows
 | 
			
		||||
	/* All functions return -2 on "not open" */
 | 
			
		||||
	OSD_Close = 1,	/* () */
 | 
			
		||||
	/*
 | 
			
		||||
	 * Disables OSD and releases the buffers
 | 
			
		||||
	 * returns 0 on success
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_Open,	/* (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0)) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * Opens OSD with this size and bit depth
 | 
			
		||||
	 * returns 0 on success, -1 on DRAM allocation error, -2 on "already open"
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_Show,	/* () */
 | 
			
		||||
	/*
 | 
			
		||||
	 * enables OSD mode
 | 
			
		||||
	 * returns 0 on success
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_Hide,	/* () */
 | 
			
		||||
	/*
 | 
			
		||||
	 * disables OSD mode
 | 
			
		||||
	 * returns 0 on success
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_Clear,	/* () */
 | 
			
		||||
	/*
 | 
			
		||||
	 * Sets all pixel to color 0
 | 
			
		||||
	 * returns 0 on success
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_Fill,	/* (color) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * Sets all pixel to color <col>
 | 
			
		||||
	 * returns 0 on success
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_SetColor,	/* (color,R{x0},G{y0},B{x1},opacity{y1}) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * set palette entry <num> to <r,g,b>, <mix> and <trans> apply
 | 
			
		||||
	 * R,G,B: 0..255
 | 
			
		||||
	 * R=Red, G=Green, B=Blue
 | 
			
		||||
	 * opacity=0:      pixel opacity 0% (only video pixel shows)
 | 
			
		||||
	 * opacity=1..254: pixel opacity as specified in header
 | 
			
		||||
	 * opacity=255:    pixel opacity 100% (only OSD pixel shows)
 | 
			
		||||
	 * returns 0 on success, -1 on error
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_SetPalette,	/* (firstcolor{color},lastcolor{x0},data) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * Set a number of entries in the palette
 | 
			
		||||
	 * sets the entries "firstcolor" through "lastcolor" from the array "data"
 | 
			
		||||
	 * data has 4 byte for each color:
 | 
			
		||||
	 * R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_SetTrans,	/* (transparency{color}) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * Sets transparency of mixed pixel (0..15)
 | 
			
		||||
	 * returns 0 on success
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_SetPixel,	/* (x0,y0,color) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * sets pixel <x>,<y> to color number <col>
 | 
			
		||||
	 * returns 0 on success, -1 on error
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_GetPixel,	/* (x0,y0) */
 | 
			
		||||
	/* returns color number of pixel <x>,<y>,  or -1 */
 | 
			
		||||
	OSD_SetRow,	/* (x0,y0,x1,data) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * fills pixels x0,y through  x1,y with the content of data[]
 | 
			
		||||
	 * returns 0 on success, -1 on clipping all pixel (no pixel drawn)
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_SetBlock,	/* (x0,y0,x1,y1,increment{color},data) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * fills pixels x0,y0 through  x1,y1 with the content of data[]
 | 
			
		||||
	 * inc contains the width of one line in the data block,
 | 
			
		||||
	 * inc<=0 uses blockwidth as linewidth
 | 
			
		||||
	 * returns 0 on success, -1 on clipping all pixel
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_FillRow,	/* (x0,y0,x1,color) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * fills pixels x0,y through  x1,y with the color <col>
 | 
			
		||||
	 * returns 0 on success, -1 on clipping all pixel
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_FillBlock,	/* (x0,y0,x1,y1,color) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * fills pixels x0,y0 through  x1,y1 with the color <col>
 | 
			
		||||
	 * returns 0 on success, -1 on clipping all pixel
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_Line,	/* (x0,y0,x1,y1,color) */
 | 
			
		||||
	/*
 | 
			
		||||
	 * draw a line from x0,y0 to x1,y1 with the color <col>
 | 
			
		||||
	 * returns 0 on success
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_Query,	/* (x0,y0,x1,y1,xasp{color}}), yasp=11 */
 | 
			
		||||
	/*
 | 
			
		||||
	 * fills parameters with the picture dimensions and the pixel aspect ratio
 | 
			
		||||
	 * returns 0 on success
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_Test,       /* () */
 | 
			
		||||
	/*
 | 
			
		||||
	 * draws a test picture. for debugging purposes only
 | 
			
		||||
	 * returns 0 on success
 | 
			
		||||
	 * TODO: remove "test" in final version
 | 
			
		||||
	 */
 | 
			
		||||
	OSD_Text,	/* (x0,y0,size,color,text) */
 | 
			
		||||
	OSD_SetWindow,	/* (x0) set window with number 0<x0<8 as current */
 | 
			
		||||
	OSD_MoveWindow,	/* move current window to (x0, y0) */
 | 
			
		||||
	OSD_OpenRaw,	/* Open other types of OSD windows */
 | 
			
		||||
} OSD_Command;
 | 
			
		||||
 | 
			
		||||
typedef struct osd_cmd_s {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
 | 
			
		||||
/*
 | 
			
		||||
 * version.h
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
 | 
			
		||||
/*
 | 
			
		||||
 * video.h
 | 
			
		||||
 * video.h - DEPRECATED MPEG-TS video decoder API
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: should not be used on future drivers
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
 | 
			
		||||
 *                  & Ralph  Metzler <ralph@convergence.de>
 | 
			
		||||
@@ -29,10 +32,6 @@
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef __user
 | 
			
		||||
#define __user
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
	VIDEO_FORMAT_4_3,     /* Select 4:3 format */
 | 
			
		||||
	VIDEO_FORMAT_16_9,    /* Select 16:9 format. */
 | 
			
		||||
@@ -40,18 +39,6 @@ typedef enum {
 | 
			
		||||
} video_format_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
	 VIDEO_SYSTEM_PAL,
 | 
			
		||||
	 VIDEO_SYSTEM_NTSC,
 | 
			
		||||
	 VIDEO_SYSTEM_PALN,
 | 
			
		||||
	 VIDEO_SYSTEM_PALNc,
 | 
			
		||||
	 VIDEO_SYSTEM_PALM,
 | 
			
		||||
	 VIDEO_SYSTEM_NTSC60,
 | 
			
		||||
	 VIDEO_SYSTEM_PAL60,
 | 
			
		||||
	 VIDEO_SYSTEM_PALM60
 | 
			
		||||
} video_system_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
	VIDEO_PAN_SCAN,       /* use pan and scan format */
 | 
			
		||||
	VIDEO_LETTER_BOX,     /* use letterbox format */
 | 
			
		||||
@@ -163,44 +150,6 @@ struct video_still_picture {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
struct video_highlight {
 | 
			
		||||
	int     active;      /*    1=show highlight, 0=hide highlight */
 | 
			
		||||
	__u8    contrast1;   /*    7- 4  Pattern pixel contrast */
 | 
			
		||||
			     /*    3- 0  Background pixel contrast */
 | 
			
		||||
	__u8    contrast2;   /*    7- 4  Emphasis pixel-2 contrast */
 | 
			
		||||
			     /*    3- 0  Emphasis pixel-1 contrast */
 | 
			
		||||
	__u8    color1;      /*    7- 4  Pattern pixel color */
 | 
			
		||||
			     /*    3- 0  Background pixel color */
 | 
			
		||||
	__u8    color2;      /*    7- 4  Emphasis pixel-2 color */
 | 
			
		||||
			     /*    3- 0  Emphasis pixel-1 color */
 | 
			
		||||
	__u32    ypos;       /*   23-22  auto action mode */
 | 
			
		||||
			     /*   21-12  start y */
 | 
			
		||||
			     /*    9- 0  end y */
 | 
			
		||||
	__u32    xpos;       /*   23-22  button color number */
 | 
			
		||||
			     /*   21-12  start x */
 | 
			
		||||
			     /*    9- 0  end x */
 | 
			
		||||
} video_highlight_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct video_spu {
 | 
			
		||||
	int active;
 | 
			
		||||
	int stream_id;
 | 
			
		||||
} video_spu_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct video_spu_palette {      /* SPU Palette information */
 | 
			
		||||
	int length;
 | 
			
		||||
	__u8 __user *palette;
 | 
			
		||||
} video_spu_palette_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct video_navi_pack {
 | 
			
		||||
	int length;          /* 0 ... 1024 */
 | 
			
		||||
	__u8 data[1024];
 | 
			
		||||
} video_navi_pack_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef __u16 video_attributes_t;
 | 
			
		||||
/*   bits: descr. */
 | 
			
		||||
/*   15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */
 | 
			
		||||
@@ -245,17 +194,9 @@ typedef __u16 video_attributes_t;
 | 
			
		||||
#define VIDEO_SLOWMOTION           _IO('o', 32)
 | 
			
		||||
#define VIDEO_GET_CAPABILITIES     _IOR('o', 33, unsigned int)
 | 
			
		||||
#define VIDEO_CLEAR_BUFFER         _IO('o',  34)
 | 
			
		||||
#define VIDEO_SET_ID               _IO('o', 35)
 | 
			
		||||
#define VIDEO_SET_STREAMTYPE       _IO('o', 36)
 | 
			
		||||
#define VIDEO_SET_FORMAT           _IO('o', 37)
 | 
			
		||||
#define VIDEO_SET_SYSTEM           _IO('o', 38)
 | 
			
		||||
#define VIDEO_SET_HIGHLIGHT        _IOW('o', 39, video_highlight_t)
 | 
			
		||||
#define VIDEO_SET_SPU              _IOW('o', 50, video_spu_t)
 | 
			
		||||
#define VIDEO_SET_SPU_PALETTE      _IOW('o', 51, video_spu_palette_t)
 | 
			
		||||
#define VIDEO_GET_NAVI             _IOR('o', 52, video_navi_pack_t)
 | 
			
		||||
#define VIDEO_SET_ATTRIBUTES       _IO('o', 53)
 | 
			
		||||
#define VIDEO_GET_SIZE             _IOR('o', 55, video_size_t)
 | 
			
		||||
#define VIDEO_GET_FRAME_RATE       _IOR('o', 56, unsigned int)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * VIDEO_GET_PTS
 | 
			
		||||
 
 | 
			
		||||
@@ -117,7 +117,7 @@ struct dmx_ts_feed {
 | 
			
		||||
 *		  specified by @filter_value that will be used on the filter
 | 
			
		||||
 *		  match logic.
 | 
			
		||||
 * @filter_mode:  Contains a 16 bytes (128 bits) filter mode.
 | 
			
		||||
 * @parent:	  Pointer to struct dmx_section_feed.
 | 
			
		||||
 * @parent:	  Back-pointer to struct dmx_section_feed.
 | 
			
		||||
 * @priv:	  Pointer to private data of the API client.
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
@@ -130,8 +130,9 @@ struct dmx_section_filter {
 | 
			
		||||
	u8 filter_value[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
	u8 filter_mask[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
	u8 filter_mode[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
	struct dmx_section_feed *parent; /* Back-pointer */
 | 
			
		||||
	void *priv; /* Pointer to private data of the API client */
 | 
			
		||||
	struct dmx_section_feed *parent;
 | 
			
		||||
 | 
			
		||||
	void *priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -193,6 +194,10 @@ struct dmx_section_feed {
 | 
			
		||||
 * @buffer2:		Pointer to the tail of the filtered TS packets, or NULL.
 | 
			
		||||
 * @buffer2_length:	Length of the TS data in buffer2.
 | 
			
		||||
 * @source:		Indicates which TS feed is the source of the callback.
 | 
			
		||||
 * @buffer_flags:	Address where buffer flags are stored. Those are
 | 
			
		||||
 *			used to report discontinuity users via DVB
 | 
			
		||||
 *			memory mapped API, as defined by
 | 
			
		||||
 *			&enum dmx_buffer_flags.
 | 
			
		||||
 *
 | 
			
		||||
 * This function callback prototype, provided by the client of the demux API,
 | 
			
		||||
 * is called from the demux code. The function is only called when filtering
 | 
			
		||||
@@ -245,7 +250,8 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1,
 | 
			
		||||
			 size_t buffer1_length,
 | 
			
		||||
			 const u8 *buffer2,
 | 
			
		||||
			 size_t buffer2_length,
 | 
			
		||||
			 struct dmx_ts_feed *source);
 | 
			
		||||
			 struct dmx_ts_feed *source,
 | 
			
		||||
			 u32 *buffer_flags);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * typedef dmx_section_cb - DVB demux TS filter callback function prototype
 | 
			
		||||
@@ -261,6 +267,10 @@ typedef int (*dmx_ts_cb)(const u8 *buffer1,
 | 
			
		||||
 *			including headers and CRC.
 | 
			
		||||
 * @source:		Indicates which section feed is the source of the
 | 
			
		||||
 *			callback.
 | 
			
		||||
 * @buffer_flags:	Address where buffer flags are stored. Those are
 | 
			
		||||
 *			used to report discontinuity users via DVB
 | 
			
		||||
 *			memory mapped API, as defined by
 | 
			
		||||
 *			&enum dmx_buffer_flags.
 | 
			
		||||
 *
 | 
			
		||||
 * This function callback prototype, provided by the client of the demux API,
 | 
			
		||||
 * is called from the demux code. The function is only called when
 | 
			
		||||
@@ -286,7 +296,8 @@ typedef int (*dmx_section_cb)(const u8 *buffer1,
 | 
			
		||||
			      size_t buffer1_len,
 | 
			
		||||
			      const u8 *buffer2,
 | 
			
		||||
			      size_t buffer2_len,
 | 
			
		||||
			      struct dmx_section_filter *source);
 | 
			
		||||
			      struct dmx_section_filter *source,
 | 
			
		||||
			      u32 *buffer_flags);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DVB Front-End
 | 
			
		||||
							
								
								
									
										220
									
								
								include/linux/media/dmxdev.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								include/linux/media/dmxdev.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,220 @@
 | 
			
		||||
/*
 | 
			
		||||
 * dmxdev.h
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
 | 
			
		||||
 *                    for convergence integrated media GmbH
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2.1
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _DMXDEV_H_
 | 
			
		||||
#define _DMXDEV_H_
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/time.h>
 | 
			
		||||
#include <linux/timer.h>
 | 
			
		||||
#include <linux/wait.h>
 | 
			
		||||
#include <linux/fs.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/dvb/dmx.h>
 | 
			
		||||
 | 
			
		||||
#include <media/dvbdev.h>
 | 
			
		||||
#include <media/demux.h>
 | 
			
		||||
#include <media/dvb_ringbuffer.h>
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
#include <media/dvb_vb2.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum dmxdev_type - type of demux filter type.
 | 
			
		||||
 *
 | 
			
		||||
 * @DMXDEV_TYPE_NONE:	no filter set.
 | 
			
		||||
 * @DMXDEV_TYPE_SEC:	section filter.
 | 
			
		||||
 * @DMXDEV_TYPE_PES:	Program Elementary Stream (PES) filter.
 | 
			
		||||
 */
 | 
			
		||||
enum dmxdev_type {
 | 
			
		||||
	DMXDEV_TYPE_NONE,
 | 
			
		||||
	DMXDEV_TYPE_SEC,
 | 
			
		||||
	DMXDEV_TYPE_PES,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum dmxdev_state - state machine for the dmxdev.
 | 
			
		||||
 *
 | 
			
		||||
 * @DMXDEV_STATE_FREE:		indicates that the filter is freed.
 | 
			
		||||
 * @DMXDEV_STATE_ALLOCATED:	indicates that the filter was allocated
 | 
			
		||||
 *				to be used.
 | 
			
		||||
 * @DMXDEV_STATE_SET:		indicates that the filter parameters are set.
 | 
			
		||||
 * @DMXDEV_STATE_GO:		indicates that the filter is running.
 | 
			
		||||
 * @DMXDEV_STATE_DONE:		indicates that a packet was already filtered
 | 
			
		||||
 *				and the filter is now disabled.
 | 
			
		||||
 *				Set only if %DMX_ONESHOT. See
 | 
			
		||||
 *				&dmx_sct_filter_params.
 | 
			
		||||
 * @DMXDEV_STATE_TIMEDOUT:	Indicates a timeout condition.
 | 
			
		||||
 */
 | 
			
		||||
enum dmxdev_state {
 | 
			
		||||
	DMXDEV_STATE_FREE,
 | 
			
		||||
	DMXDEV_STATE_ALLOCATED,
 | 
			
		||||
	DMXDEV_STATE_SET,
 | 
			
		||||
	DMXDEV_STATE_GO,
 | 
			
		||||
	DMXDEV_STATE_DONE,
 | 
			
		||||
	DMXDEV_STATE_TIMEDOUT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dmxdev_feed - digital TV dmxdev feed
 | 
			
		||||
 *
 | 
			
		||||
 * @pid:	Program ID to be filtered
 | 
			
		||||
 * @ts:		pointer to &struct dmx_ts_feed
 | 
			
		||||
 * @next:	&struct list_head pointing to the next feed.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct dmxdev_feed {
 | 
			
		||||
	u16 pid;
 | 
			
		||||
	struct dmx_ts_feed *ts;
 | 
			
		||||
	struct list_head next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dmxdev_filter - digital TV dmxdev filter
 | 
			
		||||
 *
 | 
			
		||||
 * @filter:	a union describing a dmxdev filter.
 | 
			
		||||
 *		Currently used only for section filters.
 | 
			
		||||
 * @filter.sec: a &struct dmx_section_filter pointer.
 | 
			
		||||
 *		For section filter only.
 | 
			
		||||
 * @feed:	a union describing a dmxdev feed.
 | 
			
		||||
 *		Depending on the filter type, it can be either
 | 
			
		||||
 *		@feed.ts or @feed.sec.
 | 
			
		||||
 * @feed.ts:	a &struct list_head list.
 | 
			
		||||
 *		For TS and PES feeds.
 | 
			
		||||
 * @feed.sec:	a &struct dmx_section_feed pointer.
 | 
			
		||||
 *		For section feed only.
 | 
			
		||||
 * @params:	a union describing dmxdev filter parameters.
 | 
			
		||||
 *		Depending on the filter type, it can be either
 | 
			
		||||
 *		@params.sec or @params.pes.
 | 
			
		||||
 * @params.sec:	a &struct dmx_sct_filter_params embedded struct.
 | 
			
		||||
 *		For section filter only.
 | 
			
		||||
 * @params.pes:	a &struct dmx_pes_filter_params embedded struct.
 | 
			
		||||
 *		For PES filter only.
 | 
			
		||||
 * @type:	type of the dmxdev filter, as defined by &enum dmxdev_type.
 | 
			
		||||
 * @state:	state of the dmxdev filter, as defined by &enum dmxdev_state.
 | 
			
		||||
 * @dev:	pointer to &struct dmxdev.
 | 
			
		||||
 * @buffer:	an embedded &struct dvb_ringbuffer buffer.
 | 
			
		||||
 * @vb2_ctx:	control struct for VB2 handler
 | 
			
		||||
 * @mutex:	protects the access to &struct dmxdev_filter.
 | 
			
		||||
 * @timer:	&struct timer_list embedded timer, used to check for
 | 
			
		||||
 *		feed timeouts.
 | 
			
		||||
 *		Only for section filter.
 | 
			
		||||
 * @todo:	index for the @secheader.
 | 
			
		||||
 *		Only for section filter.
 | 
			
		||||
 * @secheader:	buffer cache to parse the section header.
 | 
			
		||||
 *		Only for section filter.
 | 
			
		||||
 */
 | 
			
		||||
struct dmxdev_filter {
 | 
			
		||||
	union {
 | 
			
		||||
		struct dmx_section_filter *sec;
 | 
			
		||||
	} filter;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		/* list of TS and PES feeds (struct dmxdev_feed) */
 | 
			
		||||
		struct list_head ts;
 | 
			
		||||
		struct dmx_section_feed *sec;
 | 
			
		||||
	} feed;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct dmx_sct_filter_params sec;
 | 
			
		||||
		struct dmx_pes_filter_params pes;
 | 
			
		||||
	} params;
 | 
			
		||||
 | 
			
		||||
	enum dmxdev_type type;
 | 
			
		||||
	enum dmxdev_state state;
 | 
			
		||||
	struct dmxdev *dev;
 | 
			
		||||
	struct dvb_ringbuffer buffer;
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	struct dvb_vb2_ctx vb2_ctx;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	struct mutex mutex;
 | 
			
		||||
 | 
			
		||||
	/* only for sections */
 | 
			
		||||
	struct timer_list timer;
 | 
			
		||||
	int todo;
 | 
			
		||||
	u8 secheader[3];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dmxdev - Describes a digital TV demux device.
 | 
			
		||||
 *
 | 
			
		||||
 * @dvbdev:		pointer to &struct dvb_device associated with
 | 
			
		||||
 *			the demux device node.
 | 
			
		||||
 * @dvr_dvbdev:		pointer to &struct dvb_device associated with
 | 
			
		||||
 *			the dvr device node.
 | 
			
		||||
 * @filter:		pointer to &struct dmxdev_filter.
 | 
			
		||||
 * @demux:		pointer to &struct dmx_demux.
 | 
			
		||||
 * @filternum:		number of filters.
 | 
			
		||||
 * @capabilities:	demux capabilities as defined by &enum dmx_demux_caps.
 | 
			
		||||
 * @may_do_mmap:	flag used to indicate if the device may do mmap.
 | 
			
		||||
 * @exit:		flag to indicate that the demux is being released.
 | 
			
		||||
 * @dvr_orig_fe:	pointer to &struct dmx_frontend.
 | 
			
		||||
 * @dvr_buffer:		embedded &struct dvb_ringbuffer for DVB output.
 | 
			
		||||
 * @dvr_vb2_ctx:	control struct for VB2 handler
 | 
			
		||||
 * @mutex:		protects the usage of this structure.
 | 
			
		||||
 * @lock:		protects access to &dmxdev->filter->data.
 | 
			
		||||
 */
 | 
			
		||||
struct dmxdev {
 | 
			
		||||
	struct dvb_device *dvbdev;
 | 
			
		||||
	struct dvb_device *dvr_dvbdev;
 | 
			
		||||
 | 
			
		||||
	struct dmxdev_filter *filter;
 | 
			
		||||
	struct dmx_demux *demux;
 | 
			
		||||
 | 
			
		||||
	int filternum;
 | 
			
		||||
	int capabilities;
 | 
			
		||||
 | 
			
		||||
	unsigned int may_do_mmap:1;
 | 
			
		||||
	unsigned int exit:1;
 | 
			
		||||
#define DMXDEV_CAP_DUPLEX 1
 | 
			
		||||
	struct dmx_frontend *dvr_orig_fe;
 | 
			
		||||
 | 
			
		||||
	struct dvb_ringbuffer dvr_buffer;
 | 
			
		||||
#define DVR_BUFFER_SIZE (10*188*1024)
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_MMAP
 | 
			
		||||
	struct dvb_vb2_ctx dvr_vb2_ctx;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	struct mutex mutex;
 | 
			
		||||
	spinlock_t lock;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_dmxdev_init - initializes a digital TV demux and registers both demux
 | 
			
		||||
 *	and DVR devices.
 | 
			
		||||
 *
 | 
			
		||||
 * @dmxdev: pointer to &struct dmxdev.
 | 
			
		||||
 * @adap: pointer to &struct dvb_adapter.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *adap);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_dmxdev_release - releases a digital TV demux and unregisters it.
 | 
			
		||||
 *
 | 
			
		||||
 * @dmxdev: pointer to &struct dmxdev.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_dmxdev_release(struct dmxdev *dmxdev);
 | 
			
		||||
 | 
			
		||||
#endif /* _DMXDEV_H_ */
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
#include <linux/list.h>
 | 
			
		||||
#include <linux/dvb/ca.h>
 | 
			
		||||
 | 
			
		||||
#include "dvbdev.h"
 | 
			
		||||
#include <media/dvbdev.h>
 | 
			
		||||
 | 
			
		||||
#define DVB_CA_EN50221_POLL_CAM_PRESENT	1
 | 
			
		||||
#define DVB_CA_EN50221_POLL_CAM_CHANGED	2
 | 
			
		||||
							
								
								
									
										354
									
								
								include/linux/media/dvb_demux.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								include/linux/media/dvb_demux.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,354 @@
 | 
			
		||||
/*
 | 
			
		||||
 * dvb_demux.h: DVB kernel demux API
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler
 | 
			
		||||
 *                         for convergence integrated media GmbH
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2.1
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _DVB_DEMUX_H_
 | 
			
		||||
#define _DVB_DEMUX_H_
 | 
			
		||||
 | 
			
		||||
#include <linux/time.h>
 | 
			
		||||
#include <linux/timer.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
 | 
			
		||||
#include <media/demux.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum dvb_dmx_filter_type - type of demux feed.
 | 
			
		||||
 *
 | 
			
		||||
 * @DMX_TYPE_TS:	feed is in TS mode.
 | 
			
		||||
 * @DMX_TYPE_SEC:	feed is in Section mode.
 | 
			
		||||
 */
 | 
			
		||||
enum dvb_dmx_filter_type {
 | 
			
		||||
	DMX_TYPE_TS,
 | 
			
		||||
	DMX_TYPE_SEC,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum dvb_dmx_state - state machine for a demux filter.
 | 
			
		||||
 *
 | 
			
		||||
 * @DMX_STATE_FREE:		indicates that the filter is freed.
 | 
			
		||||
 * @DMX_STATE_ALLOCATED:	indicates that the filter was allocated
 | 
			
		||||
 *				to be used.
 | 
			
		||||
 * @DMX_STATE_READY:		indicates that the filter is ready
 | 
			
		||||
 *				to be used.
 | 
			
		||||
 * @DMX_STATE_GO:		indicates that the filter is running.
 | 
			
		||||
 */
 | 
			
		||||
enum dvb_dmx_state {
 | 
			
		||||
	DMX_STATE_FREE,
 | 
			
		||||
	DMX_STATE_ALLOCATED,
 | 
			
		||||
	DMX_STATE_READY,
 | 
			
		||||
	DMX_STATE_GO,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DVB_DEMUX_MASK_MAX 18
 | 
			
		||||
 | 
			
		||||
#define MAX_PID 0x1fff
 | 
			
		||||
 | 
			
		||||
#define SPEED_PKTS_INTERVAL 50000
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_demux_filter - Describes a DVB demux section filter.
 | 
			
		||||
 *
 | 
			
		||||
 * @filter:		Section filter as defined by &struct dmx_section_filter.
 | 
			
		||||
 * @maskandmode:	logical ``and`` bit mask.
 | 
			
		||||
 * @maskandnotmode:	logical ``and not`` bit mask.
 | 
			
		||||
 * @doneq:		flag that indicates when a filter is ready.
 | 
			
		||||
 * @next:		pointer to the next section filter.
 | 
			
		||||
 * @feed:		&struct dvb_demux_feed pointer.
 | 
			
		||||
 * @index:		index of the used demux filter.
 | 
			
		||||
 * @state:		state of the filter as described by &enum dvb_dmx_state.
 | 
			
		||||
 * @type:		type of the filter as described
 | 
			
		||||
 *			by &enum dvb_dmx_filter_type.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct dvb_demux_filter {
 | 
			
		||||
	struct dmx_section_filter filter;
 | 
			
		||||
	u8 maskandmode[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
	u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
 | 
			
		||||
	bool doneq;
 | 
			
		||||
 | 
			
		||||
	struct dvb_demux_filter *next;
 | 
			
		||||
	struct dvb_demux_feed *feed;
 | 
			
		||||
	int index;
 | 
			
		||||
	enum dvb_dmx_state state;
 | 
			
		||||
	enum dvb_dmx_filter_type type;
 | 
			
		||||
 | 
			
		||||
	/* private: used only by av7110 */
 | 
			
		||||
	u16 hw_handle;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_demux_feed - describes a DVB field
 | 
			
		||||
 *
 | 
			
		||||
 * @feed:	a union describing a digital TV feed.
 | 
			
		||||
 *		Depending on the feed type, it can be either
 | 
			
		||||
 *		@feed.ts or @feed.sec.
 | 
			
		||||
 * @feed.ts:	a &struct dmx_ts_feed pointer.
 | 
			
		||||
 *		For TS feed only.
 | 
			
		||||
 * @feed.sec:	a &struct dmx_section_feed pointer.
 | 
			
		||||
 *		For section feed only.
 | 
			
		||||
 * @cb:		a union describing digital TV callbacks.
 | 
			
		||||
 *		Depending on the feed type, it can be either
 | 
			
		||||
 *		@cb.ts or @cb.sec.
 | 
			
		||||
 * @cb.ts:	a dmx_ts_cb() calback function pointer.
 | 
			
		||||
 *		For TS feed only.
 | 
			
		||||
 * @cb.sec:	a dmx_section_cb() callback function pointer.
 | 
			
		||||
 *		For section feed only.
 | 
			
		||||
 * @demux:	pointer to &struct dvb_demux.
 | 
			
		||||
 * @priv:	private data that can optionally be used by a DVB driver.
 | 
			
		||||
 * @type:	type of the filter, as defined by &enum dvb_dmx_filter_type.
 | 
			
		||||
 * @state:	state of the filter as defined by &enum dvb_dmx_state.
 | 
			
		||||
 * @pid:	PID to be filtered.
 | 
			
		||||
 * @timeout:	feed timeout.
 | 
			
		||||
 * @filter:	pointer to &struct dvb_demux_filter.
 | 
			
		||||
 * @buffer_flags: Buffer flags used to report discontinuity users via DVB
 | 
			
		||||
 *		  memory mapped API, as defined by &enum dmx_buffer_flags.
 | 
			
		||||
 * @ts_type:	type of TS, as defined by &enum ts_filter_type.
 | 
			
		||||
 * @pes_type:	type of PES, as defined by &enum dmx_ts_pes.
 | 
			
		||||
 * @cc:		MPEG-TS packet continuity counter
 | 
			
		||||
 * @pusi_seen:	if true, indicates that a discontinuity was detected.
 | 
			
		||||
 *		it is used to prevent feeding of garbage from previous section.
 | 
			
		||||
 * @peslen:	length of the PES (Packet Elementary Stream).
 | 
			
		||||
 * @list_head:	head for the list of digital TV demux feeds.
 | 
			
		||||
 * @index:	a unique index for each feed. Can be used as hardware
 | 
			
		||||
 *		pid filter index.
 | 
			
		||||
 */
 | 
			
		||||
struct dvb_demux_feed {
 | 
			
		||||
	union {
 | 
			
		||||
		struct dmx_ts_feed ts;
 | 
			
		||||
		struct dmx_section_feed sec;
 | 
			
		||||
	} feed;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		dmx_ts_cb ts;
 | 
			
		||||
		dmx_section_cb sec;
 | 
			
		||||
	} cb;
 | 
			
		||||
 | 
			
		||||
	struct dvb_demux *demux;
 | 
			
		||||
	void *priv;
 | 
			
		||||
	enum dvb_dmx_filter_type type;
 | 
			
		||||
	enum dvb_dmx_state state;
 | 
			
		||||
	u16 pid;
 | 
			
		||||
 | 
			
		||||
	ktime_t timeout;
 | 
			
		||||
	struct dvb_demux_filter *filter;
 | 
			
		||||
 | 
			
		||||
	u32 buffer_flags;
 | 
			
		||||
 | 
			
		||||
	enum ts_filter_type ts_type;
 | 
			
		||||
	enum dmx_ts_pes pes_type;
 | 
			
		||||
 | 
			
		||||
	int cc;
 | 
			
		||||
	bool pusi_seen;
 | 
			
		||||
 | 
			
		||||
	u16 peslen;
 | 
			
		||||
 | 
			
		||||
	struct list_head list_head;
 | 
			
		||||
	unsigned int index;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_demux - represents a digital TV demux
 | 
			
		||||
 * @dmx:		embedded &struct dmx_demux with demux capabilities
 | 
			
		||||
 *			and callbacks.
 | 
			
		||||
 * @priv:		private data that can optionally be used by
 | 
			
		||||
 *			a DVB driver.
 | 
			
		||||
 * @filternum:		maximum amount of DVB filters.
 | 
			
		||||
 * @feednum:		maximum amount of DVB feeds.
 | 
			
		||||
 * @start_feed:		callback routine to be called in order to start
 | 
			
		||||
 *			a DVB feed.
 | 
			
		||||
 * @stop_feed:		callback routine to be called in order to stop
 | 
			
		||||
 *			a DVB feed.
 | 
			
		||||
 * @write_to_decoder:	callback routine to be called if the feed is TS and
 | 
			
		||||
 *			it is routed to an A/V decoder, when a new TS packet
 | 
			
		||||
 *			is received.
 | 
			
		||||
 *			Used only on av7110-av.c.
 | 
			
		||||
 * @check_crc32:	callback routine to check CRC. If not initialized,
 | 
			
		||||
 *			dvb_demux will use an internal one.
 | 
			
		||||
 * @memcopy:		callback routine to memcopy received data.
 | 
			
		||||
 *			If not initialized, dvb_demux will default to memcpy().
 | 
			
		||||
 * @users:		counter for the number of demux opened file descriptors.
 | 
			
		||||
 *			Currently, it is limited to 10 users.
 | 
			
		||||
 * @filter:		pointer to &struct dvb_demux_filter.
 | 
			
		||||
 * @feed:		pointer to &struct dvb_demux_feed.
 | 
			
		||||
 * @frontend_list:	&struct list_head with frontends used by the demux.
 | 
			
		||||
 * @pesfilter:		array of &struct dvb_demux_feed with the PES types
 | 
			
		||||
 *			that will be filtered.
 | 
			
		||||
 * @pids:		list of filtered program IDs.
 | 
			
		||||
 * @feed_list:		&struct list_head with feeds.
 | 
			
		||||
 * @tsbuf:		temporary buffer used internally to store TS packets.
 | 
			
		||||
 * @tsbufp:		temporary buffer index used internally.
 | 
			
		||||
 * @mutex:		pointer to &struct mutex used to protect feed set
 | 
			
		||||
 *			logic.
 | 
			
		||||
 * @lock:		pointer to &spinlock_t, used to protect buffer handling.
 | 
			
		||||
 * @cnt_storage:	buffer used for TS/TEI continuity check.
 | 
			
		||||
 * @speed_last_time:	&ktime_t used for TS speed check.
 | 
			
		||||
 * @speed_pkts_cnt:	packets count used for TS speed check.
 | 
			
		||||
 */
 | 
			
		||||
struct dvb_demux {
 | 
			
		||||
	struct dmx_demux dmx;
 | 
			
		||||
	void *priv;
 | 
			
		||||
	int filternum;
 | 
			
		||||
	int feednum;
 | 
			
		||||
	int (*start_feed)(struct dvb_demux_feed *feed);
 | 
			
		||||
	int (*stop_feed)(struct dvb_demux_feed *feed);
 | 
			
		||||
	int (*write_to_decoder)(struct dvb_demux_feed *feed,
 | 
			
		||||
				 const u8 *buf, size_t len);
 | 
			
		||||
	u32 (*check_crc32)(struct dvb_demux_feed *feed,
 | 
			
		||||
			    const u8 *buf, size_t len);
 | 
			
		||||
	void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
 | 
			
		||||
			 const u8 *src, size_t len);
 | 
			
		||||
 | 
			
		||||
	int users;
 | 
			
		||||
#define MAX_DVB_DEMUX_USERS 10
 | 
			
		||||
	struct dvb_demux_filter *filter;
 | 
			
		||||
	struct dvb_demux_feed *feed;
 | 
			
		||||
 | 
			
		||||
	struct list_head frontend_list;
 | 
			
		||||
 | 
			
		||||
	struct dvb_demux_feed *pesfilter[DMX_PES_OTHER];
 | 
			
		||||
	u16 pids[DMX_PES_OTHER];
 | 
			
		||||
 | 
			
		||||
#define DMX_MAX_PID 0x2000
 | 
			
		||||
	struct list_head feed_list;
 | 
			
		||||
	u8 tsbuf[204];
 | 
			
		||||
	int tsbufp;
 | 
			
		||||
 | 
			
		||||
	struct mutex mutex;
 | 
			
		||||
	spinlock_t lock;
 | 
			
		||||
 | 
			
		||||
	uint8_t *cnt_storage; /* for TS continuity check */
 | 
			
		||||
 | 
			
		||||
	ktime_t speed_last_time; /* for TS speed check */
 | 
			
		||||
	uint32_t speed_pkts_cnt; /* for TS speed check */
 | 
			
		||||
 | 
			
		||||
	/* private: used only on av7110 */
 | 
			
		||||
	int playing;
 | 
			
		||||
	int recording;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_dmx_init - initialize a digital TV demux struct.
 | 
			
		||||
 *
 | 
			
		||||
 * @demux: &struct dvb_demux to be initialized.
 | 
			
		||||
 *
 | 
			
		||||
 * Before being able to register a digital TV demux struct, drivers
 | 
			
		||||
 * should call this routine. On its typical usage, some fields should
 | 
			
		||||
 * be initialized at the driver before calling it.
 | 
			
		||||
 *
 | 
			
		||||
 * A typical usecase is::
 | 
			
		||||
 *
 | 
			
		||||
 *	dvb->demux.dmx.capabilities =
 | 
			
		||||
 *		DMX_TS_FILTERING | DMX_SECTION_FILTERING |
 | 
			
		||||
 *		DMX_MEMORY_BASED_FILTERING;
 | 
			
		||||
 *	dvb->demux.priv       = dvb;
 | 
			
		||||
 *	dvb->demux.filternum  = 256;
 | 
			
		||||
 *	dvb->demux.feednum    = 256;
 | 
			
		||||
 *	dvb->demux.start_feed = driver_start_feed;
 | 
			
		||||
 *	dvb->demux.stop_feed  = driver_stop_feed;
 | 
			
		||||
 *	ret = dvb_dmx_init(&dvb->demux);
 | 
			
		||||
 *	if (ret < 0)
 | 
			
		||||
 *		return ret;
 | 
			
		||||
 */
 | 
			
		||||
int dvb_dmx_init(struct dvb_demux *demux);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_dmx_release - releases a digital TV demux internal buffers.
 | 
			
		||||
 *
 | 
			
		||||
 * @demux: &struct dvb_demux to be released.
 | 
			
		||||
 *
 | 
			
		||||
 * The DVB core internally allocates data at @demux. This routine
 | 
			
		||||
 * releases those data. Please notice that the struct itelf is not
 | 
			
		||||
 * released, as it can be embedded on other structs.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_dmx_release(struct dvb_demux *demux);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_dmx_swfilter_packets - use dvb software filter for a buffer with
 | 
			
		||||
 *	multiple MPEG-TS packets with 188 bytes each.
 | 
			
		||||
 *
 | 
			
		||||
 * @demux: pointer to &struct dvb_demux
 | 
			
		||||
 * @buf: buffer with data to be filtered
 | 
			
		||||
 * @count: number of MPEG-TS packets with size of 188.
 | 
			
		||||
 *
 | 
			
		||||
 * The routine will discard a DVB packet that don't start with 0x47.
 | 
			
		||||
 *
 | 
			
		||||
 * Use this routine if the DVB demux fills MPEG-TS buffers that are
 | 
			
		||||
 * already aligned.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: The @buf size should have size equal to ``count * 188``.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
 | 
			
		||||
			      size_t count);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_dmx_swfilter -  use dvb software filter for a buffer with
 | 
			
		||||
 *	multiple MPEG-TS packets with 188 bytes each.
 | 
			
		||||
 *
 | 
			
		||||
 * @demux: pointer to &struct dvb_demux
 | 
			
		||||
 * @buf: buffer with data to be filtered
 | 
			
		||||
 * @count: number of MPEG-TS packets with size of 188.
 | 
			
		||||
 *
 | 
			
		||||
 * If a DVB packet doesn't start with 0x47, it will seek for the first
 | 
			
		||||
 * byte that starts with 0x47.
 | 
			
		||||
 *
 | 
			
		||||
 * Use this routine if the DVB demux fill buffers that may not start with
 | 
			
		||||
 * a packet start mark (0x47).
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: The @buf size should have size equal to ``count * 188``.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_dmx_swfilter_204 -  use dvb software filter for a buffer with
 | 
			
		||||
 *	multiple MPEG-TS packets with 204 bytes each.
 | 
			
		||||
 *
 | 
			
		||||
 * @demux: pointer to &struct dvb_demux
 | 
			
		||||
 * @buf: buffer with data to be filtered
 | 
			
		||||
 * @count: number of MPEG-TS packets with size of 204.
 | 
			
		||||
 *
 | 
			
		||||
 * If a DVB packet doesn't start with 0x47, it will seek for the first
 | 
			
		||||
 * byte that starts with 0x47.
 | 
			
		||||
 *
 | 
			
		||||
 * Use this routine if the DVB demux fill buffers that may not start with
 | 
			
		||||
 * a packet start mark (0x47).
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: The @buf size should have size equal to ``count * 204``.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
 | 
			
		||||
			  size_t count);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_dmx_swfilter_raw -  make the raw data available to userspace without
 | 
			
		||||
 *	filtering
 | 
			
		||||
 *
 | 
			
		||||
 * @demux: pointer to &struct dvb_demux
 | 
			
		||||
 * @buf: buffer with data
 | 
			
		||||
 * @count: number of packets to be passed. The actual size of each packet
 | 
			
		||||
 *	depends on the &dvb_demux->feed->cb.ts logic.
 | 
			
		||||
 *
 | 
			
		||||
 * Use it if the driver needs to deliver the raw payload to userspace without
 | 
			
		||||
 * passing through the kernel demux. That is meant to support some
 | 
			
		||||
 * delivery systems that aren't based on MPEG-TS.
 | 
			
		||||
 *
 | 
			
		||||
 * This function relies on &dvb_demux->feed->cb.ts to actually handle the
 | 
			
		||||
 * buffer.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf,
 | 
			
		||||
			  size_t count);
 | 
			
		||||
 | 
			
		||||
#endif /* _DVB_DEMUX_H_ */
 | 
			
		||||
@@ -46,10 +46,11 @@
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/dvb/frontend.h>
 | 
			
		||||
 | 
			
		||||
#include "dvbdev.h"
 | 
			
		||||
#include <media/dvbdev.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Maximum number of Delivery systems per frontend. It
 | 
			
		||||
@@ -57,6 +58,10 @@
 | 
			
		||||
 */
 | 
			
		||||
#define MAX_DELSYS	16
 | 
			
		||||
 | 
			
		||||
/* Helper definitions to be used at frontend drivers */
 | 
			
		||||
#define kHz 1000UL
 | 
			
		||||
#define MHz 1000000UL
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_frontend_tune_settings - parameters to adjust frontend tuning
 | 
			
		||||
 *
 | 
			
		||||
@@ -78,22 +83,19 @@ struct dvb_frontend;
 | 
			
		||||
 * struct dvb_tuner_info - Frontend name and min/max ranges/bandwidths
 | 
			
		||||
 *
 | 
			
		||||
 * @name:		name of the Frontend
 | 
			
		||||
 * @frequency_min:	minimal frequency supported
 | 
			
		||||
 * @frequency_max:	maximum frequency supported
 | 
			
		||||
 * @frequency_step:	frequency step
 | 
			
		||||
 * @frequency_min_hz:	minimal frequency supported in Hz
 | 
			
		||||
 * @frequency_max_hz:	maximum frequency supported in Hz
 | 
			
		||||
 * @frequency_step_hz:	frequency step in Hz
 | 
			
		||||
 * @bandwidth_min:	minimal frontend bandwidth supported
 | 
			
		||||
 * @bandwidth_max:	maximum frontend bandwidth supported
 | 
			
		||||
 * @bandwidth_step:	frontend bandwidth step
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: frequency parameters are in Hz, for terrestrial/cable or kHz for
 | 
			
		||||
 * satellite.
 | 
			
		||||
 */
 | 
			
		||||
struct dvb_tuner_info {
 | 
			
		||||
	char name[128];
 | 
			
		||||
 | 
			
		||||
	u32 frequency_min;
 | 
			
		||||
	u32 frequency_max;
 | 
			
		||||
	u32 frequency_step;
 | 
			
		||||
	u32 frequency_min_hz;
 | 
			
		||||
	u32 frequency_max_hz;
 | 
			
		||||
	u32 frequency_step_hz;
 | 
			
		||||
 | 
			
		||||
	u32 bandwidth_min;
 | 
			
		||||
	u32 bandwidth_max;
 | 
			
		||||
@@ -145,10 +147,10 @@ struct analog_parameters {
 | 
			
		||||
 *	These devices have AUTO recovery capabilities from LOCK failure
 | 
			
		||||
 */
 | 
			
		||||
enum dvbfe_algo {
 | 
			
		||||
	DVBFE_ALGO_HW			= (1 <<  0),
 | 
			
		||||
	DVBFE_ALGO_SW			= (1 <<  1),
 | 
			
		||||
	DVBFE_ALGO_CUSTOM		= (1 <<  2),
 | 
			
		||||
	DVBFE_ALGO_RECOVERY		= (1 << 31)
 | 
			
		||||
	DVBFE_ALGO_HW			= BIT(0),
 | 
			
		||||
	DVBFE_ALGO_SW			= BIT(1),
 | 
			
		||||
	DVBFE_ALGO_CUSTOM		= BIT(2),
 | 
			
		||||
	DVBFE_ALGO_RECOVERY		= BIT(31),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -164,7 +166,7 @@ enum dvbfe_algo {
 | 
			
		||||
 *	The frontend search for a signal failed
 | 
			
		||||
 *
 | 
			
		||||
 * @DVBFE_ALGO_SEARCH_INVALID:
 | 
			
		||||
 *	The frontend search algorith was probably supplied with invalid
 | 
			
		||||
 *	The frontend search algorithm was probably supplied with invalid
 | 
			
		||||
 *	parameters and the search is an invalid one
 | 
			
		||||
 *
 | 
			
		||||
 * @DVBFE_ALGO_SEARCH_ERROR:
 | 
			
		||||
@@ -174,19 +176,19 @@ enum dvbfe_algo {
 | 
			
		||||
 *	The frontend search algorithm was requested to search again
 | 
			
		||||
 */
 | 
			
		||||
enum dvbfe_search {
 | 
			
		||||
	DVBFE_ALGO_SEARCH_SUCCESS	= (1 <<  0),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_ASLEEP	= (1 <<  1),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_FAILED	= (1 <<  2),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_INVALID	= (1 <<  3),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_AGAIN		= (1 <<  4),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_ERROR		= (1 << 31),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_SUCCESS	= BIT(0),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_ASLEEP	= BIT(1),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_FAILED	= BIT(2),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_INVALID	= BIT(3),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_AGAIN		= BIT(4),
 | 
			
		||||
	DVBFE_ALGO_SEARCH_ERROR		= BIT(31),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_tuner_ops - Tuner information and callbacks
 | 
			
		||||
 *
 | 
			
		||||
 * @info:		embedded struct dvb_tuner_info with tuner properties
 | 
			
		||||
 * @release:		callback function called when frontend is dettached.
 | 
			
		||||
 * @info:		embedded &struct dvb_tuner_info with tuner properties
 | 
			
		||||
 * @release:		callback function called when frontend is detached.
 | 
			
		||||
 *			drivers should free any allocated memory.
 | 
			
		||||
 * @init:		callback function used to initialize the tuner device.
 | 
			
		||||
 * @sleep:		callback function used to put the tuner to sleep.
 | 
			
		||||
@@ -196,25 +198,25 @@ enum dvbfe_search {
 | 
			
		||||
 *			resuming from suspend.
 | 
			
		||||
 * @set_params:		callback function used to inform the tuner to tune
 | 
			
		||||
 *			into a digital TV channel. The properties to be used
 | 
			
		||||
 *			are stored at @dvb_frontend.dtv_property_cache;. The
 | 
			
		||||
 *			tuner demod can change the parameters to reflect the
 | 
			
		||||
 *			changes needed for the channel to be tuned, and
 | 
			
		||||
 *			are stored at &struct dvb_frontend.dtv_property_cache.
 | 
			
		||||
 *			The tuner demod can change the parameters to reflect
 | 
			
		||||
 *			the changes needed for the channel to be tuned, and
 | 
			
		||||
 *			update statistics. This is the recommended way to set
 | 
			
		||||
 *			the tuner parameters and should be used on newer
 | 
			
		||||
 *			drivers.
 | 
			
		||||
 * @set_analog_params:	callback function used to tune into an analog TV
 | 
			
		||||
 *			channel on hybrid tuners. It passes @analog_parameters;
 | 
			
		||||
 *			channel on hybrid tuners. It passes @analog_parameters
 | 
			
		||||
 *			to the driver.
 | 
			
		||||
 * @set_config:		callback function used to send some tuner-specific
 | 
			
		||||
 *			parameters.
 | 
			
		||||
 * @get_frequency:	get the actual tuned frequency
 | 
			
		||||
 * @get_bandwidth:	get the bandwitdh used by the low pass filters
 | 
			
		||||
 * @get_bandwidth:	get the bandwidth used by the low pass filters
 | 
			
		||||
 * @get_if_frequency:	get the Intermediate Frequency, in Hz. For baseband,
 | 
			
		||||
 *			should return 0.
 | 
			
		||||
 * @get_status:		returns the frontend lock status
 | 
			
		||||
 * @get_rf_strength:	returns the RF signal strengh. Used mostly to support
 | 
			
		||||
 * @get_rf_strength:	returns the RF signal strength. Used mostly to support
 | 
			
		||||
 *			analog TV and radio. Digital TV should report, instead,
 | 
			
		||||
 *			via DVBv5 API (@dvb_frontend.dtv_property_cache;).
 | 
			
		||||
 *			via DVBv5 API (&struct dvb_frontend.dtv_property_cache).
 | 
			
		||||
 * @get_afc:		Used only by analog TV core. Reports the frequency
 | 
			
		||||
 *			drift due to AFC.
 | 
			
		||||
 * @calc_regs:		callback function used to pass register data settings
 | 
			
		||||
@@ -222,7 +224,7 @@ enum dvbfe_search {
 | 
			
		||||
 * @set_frequency:	Set a new frequency. Shouldn't be used on newer drivers.
 | 
			
		||||
 * @set_bandwidth:	Set a new frequency. Shouldn't be used on newer drivers.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: frequencies used on get_frequency and set_frequency are in Hz for
 | 
			
		||||
 * NOTE: frequencies used on @get_frequency and @set_frequency are in Hz for
 | 
			
		||||
 * terrestrial/cable or kHz for satellite.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
@@ -236,7 +238,7 @@ struct dvb_tuner_ops {
 | 
			
		||||
	int (*suspend)(struct dvb_frontend *fe);
 | 
			
		||||
	int (*resume)(struct dvb_frontend *fe);
 | 
			
		||||
 | 
			
		||||
	/* This is the recomended way to set the tuner */
 | 
			
		||||
	/* This is the recommended way to set the tuner */
 | 
			
		||||
	int (*set_params)(struct dvb_frontend *fe);
 | 
			
		||||
	int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
 | 
			
		||||
 | 
			
		||||
@@ -288,14 +290,14 @@ struct analog_demod_info {
 | 
			
		||||
 * @set_params:		callback function used to inform the demod to set the
 | 
			
		||||
 *			demodulator parameters needed to decode an analog or
 | 
			
		||||
 *			radio channel. The properties are passed via
 | 
			
		||||
 *			struct @analog_params;.
 | 
			
		||||
 *			&struct analog_params.
 | 
			
		||||
 * @has_signal:		returns 0xffff if has signal, or 0 if it doesn't.
 | 
			
		||||
 * @get_afc:		Used only by analog TV core. Reports the frequency
 | 
			
		||||
 *			drift due to AFC.
 | 
			
		||||
 * @tuner_status:	callback function that returns tuner status bits, e. g.
 | 
			
		||||
 *			TUNER_STATUS_LOCKED and TUNER_STATUS_STEREO.
 | 
			
		||||
 *			%TUNER_STATUS_LOCKED and %TUNER_STATUS_STEREO.
 | 
			
		||||
 * @standby:		set the tuner to standby mode.
 | 
			
		||||
 * @release:		callback function called when frontend is dettached.
 | 
			
		||||
 * @release:		callback function called when frontend is detached.
 | 
			
		||||
 *			drivers should free any allocated memory.
 | 
			
		||||
 * @i2c_gate_ctrl:	controls the I2C gate. Newer drivers should use I2C
 | 
			
		||||
 *			mux support instead.
 | 
			
		||||
@@ -321,20 +323,48 @@ struct analog_demod_ops {
 | 
			
		||||
 | 
			
		||||
struct dtv_frontend_properties;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_frontend_internal_info - Frontend properties and capabilities
 | 
			
		||||
 *
 | 
			
		||||
 * @name:			Name of the frontend
 | 
			
		||||
 * @frequency_min_hz:		Minimal frequency supported by the frontend.
 | 
			
		||||
 * @frequency_max_hz:		Minimal frequency supported by the frontend.
 | 
			
		||||
 * @frequency_stepsize_hz:	All frequencies are multiple of this value.
 | 
			
		||||
 * @frequency_tolerance_hz:	Frequency tolerance.
 | 
			
		||||
 * @symbol_rate_min:		Minimal symbol rate, in bauds
 | 
			
		||||
 *				(for Cable/Satellite systems).
 | 
			
		||||
 * @symbol_rate_max:		Maximal symbol rate, in bauds
 | 
			
		||||
 *				(for Cable/Satellite systems).
 | 
			
		||||
 * @symbol_rate_tolerance:	Maximal symbol rate tolerance, in ppm
 | 
			
		||||
 *				(for Cable/Satellite systems).
 | 
			
		||||
 * @caps:			Capabilities supported by the frontend,
 | 
			
		||||
 *				as specified in &enum fe_caps.
 | 
			
		||||
 */
 | 
			
		||||
struct dvb_frontend_internal_info {
 | 
			
		||||
	char	name[128];
 | 
			
		||||
	u32	frequency_min_hz;
 | 
			
		||||
	u32	frequency_max_hz;
 | 
			
		||||
	u32	frequency_stepsize_hz;
 | 
			
		||||
	u32	frequency_tolerance_hz;
 | 
			
		||||
	u32	symbol_rate_min;
 | 
			
		||||
	u32	symbol_rate_max;
 | 
			
		||||
	u32	symbol_rate_tolerance;
 | 
			
		||||
	enum fe_caps caps;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_frontend_ops - Demodulation information and callbacks for
 | 
			
		||||
 *			      ditialt TV
 | 
			
		||||
 *
 | 
			
		||||
 * @info:		embedded struct dvb_tuner_info with tuner properties
 | 
			
		||||
 * @info:		embedded &struct dvb_tuner_info with tuner properties
 | 
			
		||||
 * @delsys:		Delivery systems supported by the frontend
 | 
			
		||||
 * @detach:		callback function called when frontend is detached.
 | 
			
		||||
 *			drivers should clean up, but not yet free the struct
 | 
			
		||||
 *			drivers should clean up, but not yet free the &struct
 | 
			
		||||
 *			dvb_frontend allocation.
 | 
			
		||||
 * @release:		callback function called when frontend is ready to be
 | 
			
		||||
 *			freed.
 | 
			
		||||
 *			drivers should free any allocated memory.
 | 
			
		||||
 * @release_sec:	callback function requesting that the Satelite Equipment
 | 
			
		||||
 * @release_sec:	callback function requesting that the Satellite Equipment
 | 
			
		||||
 *			Control (SEC) driver to release and free any memory
 | 
			
		||||
 *			allocated by the driver.
 | 
			
		||||
 * @init:		callback function used to initialize the tuner device.
 | 
			
		||||
@@ -343,57 +373,57 @@ struct dtv_frontend_properties;
 | 
			
		||||
 *			allow other drivers to write data into their registers.
 | 
			
		||||
 *			Should not be used on new drivers.
 | 
			
		||||
 * @tune:		callback function used by demod drivers that use
 | 
			
		||||
 *			@DVBFE_ALGO_HW; to tune into a frequency.
 | 
			
		||||
 *			@DVBFE_ALGO_HW to tune into a frequency.
 | 
			
		||||
 * @get_frontend_algo:	returns the desired hardware algorithm.
 | 
			
		||||
 * @set_frontend:	callback function used to inform the demod to set the
 | 
			
		||||
 *			parameters for demodulating a digital TV channel.
 | 
			
		||||
 *			The properties to be used are stored at
 | 
			
		||||
 *			@dvb_frontend.dtv_property_cache;. The demod can change
 | 
			
		||||
 *			The properties to be used are stored at &struct
 | 
			
		||||
 *			dvb_frontend.dtv_property_cache. The demod can change
 | 
			
		||||
 *			the parameters to reflect the changes needed for the
 | 
			
		||||
 *			channel to be decoded, and update statistics.
 | 
			
		||||
 * @get_tune_settings:	callback function
 | 
			
		||||
 * @get_frontend:	callback function used to inform the parameters
 | 
			
		||||
 *			actuall in use. The properties to be used are stored at
 | 
			
		||||
 *			@dvb_frontend.dtv_property_cache; and update
 | 
			
		||||
 *			&struct dvb_frontend.dtv_property_cache and update
 | 
			
		||||
 *			statistics. Please notice that it should not return
 | 
			
		||||
 *			an error code if the statistics are not available
 | 
			
		||||
 *			because the demog is not locked.
 | 
			
		||||
 * @read_status:	returns the locking status of the frontend.
 | 
			
		||||
 * @read_ber:		legacy callback function to return the bit error rate.
 | 
			
		||||
 *			Newer drivers should provide such info via DVBv5 API,
 | 
			
		||||
 *			e. g. @set_frontend;/@get_frontend;, implementing this
 | 
			
		||||
 *			e. g. @set_frontend;/@get_frontend, implementing this
 | 
			
		||||
 *			callback only if DVBv3 API compatibility is wanted.
 | 
			
		||||
 * @read_signal_strength: legacy callback function to return the signal
 | 
			
		||||
 *			strength. Newer drivers should provide such info via
 | 
			
		||||
 *			DVBv5 API, e. g. @set_frontend;/@get_frontend;,
 | 
			
		||||
 *			DVBv5 API, e. g. @set_frontend/@get_frontend,
 | 
			
		||||
 *			implementing this callback only if DVBv3 API
 | 
			
		||||
 *			compatibility is wanted.
 | 
			
		||||
 * @read_snr:		legacy callback function to return the Signal/Noise
 | 
			
		||||
 *			rate. Newer drivers should provide such info via
 | 
			
		||||
 *			DVBv5 API, e. g. @set_frontend;/@get_frontend;,
 | 
			
		||||
 *			DVBv5 API, e. g. @set_frontend/@get_frontend,
 | 
			
		||||
 *			implementing this callback only if DVBv3 API
 | 
			
		||||
 *			compatibility is wanted.
 | 
			
		||||
 * @read_ucblocks:	legacy callback function to return the Uncorrected Error
 | 
			
		||||
 *			Blocks. Newer drivers should provide such info via
 | 
			
		||||
 *			DVBv5 API, e. g. @set_frontend;/@get_frontend;,
 | 
			
		||||
 *			DVBv5 API, e. g. @set_frontend/@get_frontend,
 | 
			
		||||
 *			implementing this callback only if DVBv3 API
 | 
			
		||||
 *			compatibility is wanted.
 | 
			
		||||
 * @diseqc_reset_overload: callback function to implement the
 | 
			
		||||
 *			FE_DISEQC_RESET_OVERLOAD ioctl (only Satellite)
 | 
			
		||||
 *			FE_DISEQC_RESET_OVERLOAD() ioctl (only Satellite)
 | 
			
		||||
 * @diseqc_send_master_cmd: callback function to implement the
 | 
			
		||||
 *			FE_DISEQC_SEND_MASTER_CMD ioctl (only Satellite).
 | 
			
		||||
 *			FE_DISEQC_SEND_MASTER_CMD() ioctl (only Satellite).
 | 
			
		||||
 * @diseqc_recv_slave_reply: callback function to implement the
 | 
			
		||||
 *			FE_DISEQC_RECV_SLAVE_REPLY ioctl (only Satellite)
 | 
			
		||||
 *			FE_DISEQC_RECV_SLAVE_REPLY() ioctl (only Satellite)
 | 
			
		||||
 * @diseqc_send_burst:	callback function to implement the
 | 
			
		||||
 *			FE_DISEQC_SEND_BURST ioctl (only Satellite).
 | 
			
		||||
 *			FE_DISEQC_SEND_BURST() ioctl (only Satellite).
 | 
			
		||||
 * @set_tone:		callback function to implement the
 | 
			
		||||
 *			FE_SET_TONE ioctl (only Satellite).
 | 
			
		||||
 *			FE_SET_TONE() ioctl (only Satellite).
 | 
			
		||||
 * @set_voltage:	callback function to implement the
 | 
			
		||||
 *			FE_SET_VOLTAGE ioctl (only Satellite).
 | 
			
		||||
 *			FE_SET_VOLTAGE() ioctl (only Satellite).
 | 
			
		||||
 * @enable_high_lnb_voltage: callback function to implement the
 | 
			
		||||
 *			FE_ENABLE_HIGH_LNB_VOLTAGE ioctl (only Satellite).
 | 
			
		||||
 *			FE_ENABLE_HIGH_LNB_VOLTAGE() ioctl (only Satellite).
 | 
			
		||||
 * @dishnetwork_send_legacy_command: callback function to implement the
 | 
			
		||||
 *			FE_DISHNETWORK_SEND_LEGACY_CMD ioctl (only Satellite).
 | 
			
		||||
 *			FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl (only Satellite).
 | 
			
		||||
 *			Drivers should not use this, except when the DVB
 | 
			
		||||
 *			core emulation fails to provide proper support (e.g.
 | 
			
		||||
 *			if @set_voltage takes more than 8ms to work), and
 | 
			
		||||
@@ -404,16 +434,12 @@ struct dtv_frontend_properties;
 | 
			
		||||
 * @ts_bus_ctrl:	callback function used to take control of the TS bus.
 | 
			
		||||
 * @set_lna:		callback function to power on/off/auto the LNA.
 | 
			
		||||
 * @search:		callback function used on some custom algo search algos.
 | 
			
		||||
 * @tuner_ops:		pointer to struct dvb_tuner_ops
 | 
			
		||||
 * @analog_ops:		pointer to struct analog_demod_ops
 | 
			
		||||
 * @set_property:	callback function to allow the frontend to validade
 | 
			
		||||
 *			incoming properties. Should not be used on new drivers.
 | 
			
		||||
 * @get_property:	callback function to allow the frontend to override
 | 
			
		||||
 *			outcoming properties. Should not be used on new drivers.
 | 
			
		||||
 * @tuner_ops:		pointer to &struct dvb_tuner_ops
 | 
			
		||||
 * @analog_ops:		pointer to &struct analog_demod_ops
 | 
			
		||||
 */
 | 
			
		||||
struct dvb_frontend_ops {
 | 
			
		||||
 | 
			
		||||
	struct dvb_frontend_info info;
 | 
			
		||||
	struct dvb_frontend_internal_info info;
 | 
			
		||||
 | 
			
		||||
	u8 delsys[MAX_DELSYS];
 | 
			
		||||
 | 
			
		||||
@@ -473,9 +499,6 @@ struct dvb_frontend_ops {
 | 
			
		||||
	struct dvb_tuner_ops tuner_ops;
 | 
			
		||||
	struct analog_demod_ops analog_ops;
 | 
			
		||||
 | 
			
		||||
	int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
 | 
			
		||||
	int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
 | 
			
		||||
 | 
			
		||||
	u8 xbar[3];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -642,11 +665,6 @@ struct dtv_frontend_properties {
 | 
			
		||||
	struct dtv_fe_stats	post_bit_count;
 | 
			
		||||
	struct dtv_fe_stats	block_error;
 | 
			
		||||
	struct dtv_fe_stats	block_count;
 | 
			
		||||
 | 
			
		||||
	/* private: */
 | 
			
		||||
	/* Cache State */
 | 
			
		||||
	u32			state;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DVB_FE_NO_EXIT  0
 | 
			
		||||
@@ -657,16 +675,16 @@ struct dtv_frontend_properties {
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_frontend - Frontend structure to be used on drivers.
 | 
			
		||||
 *
 | 
			
		||||
 * @refcount:		refcount to keep track of struct dvb_frontend
 | 
			
		||||
 * @refcount:		refcount to keep track of &struct dvb_frontend
 | 
			
		||||
 *			references
 | 
			
		||||
 * @ops:		embedded struct dvb_frontend_ops
 | 
			
		||||
 * @dvb:		pointer to struct dvb_adapter
 | 
			
		||||
 * @ops:		embedded &struct dvb_frontend_ops
 | 
			
		||||
 * @dvb:		pointer to &struct dvb_adapter
 | 
			
		||||
 * @demodulator_priv:	demod private data
 | 
			
		||||
 * @tuner_priv:		tuner private data
 | 
			
		||||
 * @frontend_priv:	frontend private data
 | 
			
		||||
 * @sec_priv:		SEC private data
 | 
			
		||||
 * @analog_demod_priv:	Analog demod private data
 | 
			
		||||
 * @dtv_property_cache:	embedded struct dtv_frontend_properties
 | 
			
		||||
 * @dtv_property_cache:	embedded &struct dtv_frontend_properties
 | 
			
		||||
 * @callback:		callback function used on some drivers to call
 | 
			
		||||
 *			either the tuner or the demodulator.
 | 
			
		||||
 * @id:			Frontend ID
 | 
			
		||||
@@ -695,8 +713,8 @@ struct dvb_frontend {
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_register_frontend() - Registers a DVB frontend at the adapter
 | 
			
		||||
 *
 | 
			
		||||
 * @dvb: pointer to the dvb adapter
 | 
			
		||||
 * @fe: pointer to the frontend struct
 | 
			
		||||
 * @dvb: pointer to &struct dvb_adapter
 | 
			
		||||
 * @fe: pointer to &struct dvb_frontend
 | 
			
		||||
 *
 | 
			
		||||
 * Allocate and initialize the private data needed by the frontend core to
 | 
			
		||||
 * manage the frontend and calls dvb_register_device() to register a new
 | 
			
		||||
@@ -709,7 +727,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_unregister_frontend() - Unregisters a DVB frontend
 | 
			
		||||
 *
 | 
			
		||||
 * @fe: pointer to the frontend struct
 | 
			
		||||
 * @fe: pointer to &struct dvb_frontend
 | 
			
		||||
 *
 | 
			
		||||
 * Stops the frontend kthread, calls dvb_unregister_device() and frees the
 | 
			
		||||
 * private frontend data allocated by dvb_register_frontend().
 | 
			
		||||
@@ -723,14 +741,14 @@ int dvb_unregister_frontend(struct dvb_frontend *fe);
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_frontend_detach() - Detaches and frees frontend specific data
 | 
			
		||||
 *
 | 
			
		||||
 * @fe: pointer to the frontend struct
 | 
			
		||||
 * @fe: pointer to &struct dvb_frontend
 | 
			
		||||
 *
 | 
			
		||||
 * This function should be called after dvb_unregister_frontend(). It
 | 
			
		||||
 * calls the SEC, tuner and demod release functions:
 | 
			
		||||
 * &dvb_frontend_ops.release_sec, &dvb_frontend_ops.tuner_ops.release,
 | 
			
		||||
 * &dvb_frontend_ops.analog_ops.release and &dvb_frontend_ops.release.
 | 
			
		||||
 *
 | 
			
		||||
 * If the driver is compiled with CONFIG_MEDIA_ATTACH, it also decreases
 | 
			
		||||
 * If the driver is compiled with %CONFIG_MEDIA_ATTACH, it also decreases
 | 
			
		||||
 * the module reference count, needed to allow userspace to remove the
 | 
			
		||||
 * previously used DVB frontend modules.
 | 
			
		||||
 */
 | 
			
		||||
@@ -739,7 +757,7 @@ void dvb_frontend_detach(struct dvb_frontend *fe);
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_frontend_suspend() - Suspends a Digital TV frontend
 | 
			
		||||
 *
 | 
			
		||||
 * @fe: pointer to the frontend struct
 | 
			
		||||
 * @fe: pointer to &struct dvb_frontend
 | 
			
		||||
 *
 | 
			
		||||
 * This function prepares a Digital TV frontend to suspend.
 | 
			
		||||
 *
 | 
			
		||||
@@ -757,7 +775,7 @@ int dvb_frontend_suspend(struct dvb_frontend *fe);
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_frontend_resume() - Resumes a Digital TV frontend
 | 
			
		||||
 *
 | 
			
		||||
 * @fe: pointer to the frontend struct
 | 
			
		||||
 * @fe: pointer to &struct dvb_frontend
 | 
			
		||||
 *
 | 
			
		||||
 * This function resumes the usual operation of the tuner after resume.
 | 
			
		||||
 *
 | 
			
		||||
@@ -778,7 +796,7 @@ int dvb_frontend_resume(struct dvb_frontend *fe);
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_frontend_reinitialise() - forces a reinitialisation at the frontend
 | 
			
		||||
 *
 | 
			
		||||
 * @fe: pointer to the frontend struct
 | 
			
		||||
 * @fe: pointer to &struct dvb_frontend
 | 
			
		||||
 *
 | 
			
		||||
 * Calls &dvb_frontend_ops.init\(\) and &dvb_frontend_ops.tuner_ops.init\(\),
 | 
			
		||||
 * and resets SEC tone and voltage (for Satellite systems).
 | 
			
		||||
@@ -793,16 +811,16 @@ void dvb_frontend_reinitialise(struct dvb_frontend *fe);
 | 
			
		||||
 * dvb_frontend_sleep_until() - Sleep for the amount of time given by
 | 
			
		||||
 *                      add_usec parameter
 | 
			
		||||
 *
 | 
			
		||||
 * @waketime: pointer to a struct ktime_t
 | 
			
		||||
 * @waketime: pointer to &struct ktime_t
 | 
			
		||||
 * @add_usec: time to sleep, in microseconds
 | 
			
		||||
 *
 | 
			
		||||
 * This function is used to measure the time required for the
 | 
			
		||||
 * %FE_DISHNETWORK_SEND_LEGACY_CMD ioctl to work. It needs to be as precise
 | 
			
		||||
 * FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl to work. It needs to be as precise
 | 
			
		||||
 * as possible, as it affects the detection of the dish tone command at the
 | 
			
		||||
 * satellite subsystem.
 | 
			
		||||
 *
 | 
			
		||||
 * Its used internally by the DVB frontend core, in order to emulate
 | 
			
		||||
 * %FE_DISHNETWORK_SEND_LEGACY_CMD using the &dvb_frontend_ops.set_voltage\(\)
 | 
			
		||||
 * FE_DISHNETWORK_SEND_LEGACY_CMD() using the &dvb_frontend_ops.set_voltage\(\)
 | 
			
		||||
 * callback.
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: it should not be used at the drivers, as the emulation for the
 | 
			
		||||
@@ -24,12 +24,28 @@
 | 
			
		||||
#include <linux/etherdevice.h>
 | 
			
		||||
#include <linux/skbuff.h>
 | 
			
		||||
 | 
			
		||||
#include "dvbdev.h"
 | 
			
		||||
#include <media/dvbdev.h>
 | 
			
		||||
 | 
			
		||||
#define DVB_NET_DEVICES_MAX 10
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DVB_NET
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_net - describes a DVB network interface
 | 
			
		||||
 *
 | 
			
		||||
 * @dvbdev:		pointer to &struct dvb_device.
 | 
			
		||||
 * @device:		array of pointers to &struct net_device.
 | 
			
		||||
 * @state:		array of integers to each net device. A value
 | 
			
		||||
 *			different than zero means that the interface is
 | 
			
		||||
 *			in usage.
 | 
			
		||||
 * @exit:		flag to indicate when the device is being removed.
 | 
			
		||||
 * @demux:		pointer to &struct dmx_demux.
 | 
			
		||||
 * @ioctl_mutex:	protect access to this struct.
 | 
			
		||||
 *
 | 
			
		||||
 * Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network
 | 
			
		||||
 * devices.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct dvb_net {
 | 
			
		||||
	struct dvb_device *dvbdev;
 | 
			
		||||
	struct net_device *device[DVB_NET_DEVICES_MAX];
 | 
			
		||||
@@ -39,8 +55,22 @@ struct dvb_net {
 | 
			
		||||
	struct mutex ioctl_mutex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void dvb_net_release(struct dvb_net *);
 | 
			
		||||
int  dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *);
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_net_init - nitializes a digital TV network device and registers it.
 | 
			
		||||
 *
 | 
			
		||||
 * @adap:	pointer to &struct dvb_adapter.
 | 
			
		||||
 * @dvbnet:	pointer to &struct dvb_net.
 | 
			
		||||
 * @dmxdemux:	pointer to &struct dmx_demux.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet,
 | 
			
		||||
		  struct dmx_demux *dmxdemux);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_net_release - releases a digital TV network device and unregisters it.
 | 
			
		||||
 *
 | 
			
		||||
 * @dvbnet:	pointer to &struct dvb_net.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_net_release(struct dvb_net *dvbnet);
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										280
									
								
								include/linux/media/dvb_vb2.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								include/linux/media/dvb_vb2.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,280 @@
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * dvb-vb2.h - DVB driver helper framework for streaming I/O
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2015 Samsung Electronics
 | 
			
		||||
 *
 | 
			
		||||
 * Author: jh1009.sung@samsung.com
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _DVB_VB2_H
 | 
			
		||||
#define _DVB_VB2_H
 | 
			
		||||
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/poll.h>
 | 
			
		||||
#include <linux/dvb/dmx.h>
 | 
			
		||||
#include <media/videobuf2-core.h>
 | 
			
		||||
#include <media/videobuf2-dma-contig.h>
 | 
			
		||||
#include <media/videobuf2-vmalloc.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum dvb_buf_type - types of Digital TV memory-mapped buffers
 | 
			
		||||
 *
 | 
			
		||||
 * @DVB_BUF_TYPE_CAPTURE: buffer is filled by the Kernel,
 | 
			
		||||
 *			  with a received Digital TV stream
 | 
			
		||||
 */
 | 
			
		||||
enum dvb_buf_type {
 | 
			
		||||
	DVB_BUF_TYPE_CAPTURE        = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum dvb_vb2_states - states to control VB2 state machine
 | 
			
		||||
 * @DVB_VB2_STATE_NONE:
 | 
			
		||||
 *	VB2 engine not initialized yet, init failed or VB2 was released.
 | 
			
		||||
 * @DVB_VB2_STATE_INIT:
 | 
			
		||||
 *	VB2 engine initialized.
 | 
			
		||||
 * @DVB_VB2_STATE_REQBUFS:
 | 
			
		||||
 *	Buffers were requested
 | 
			
		||||
 * @DVB_VB2_STATE_STREAMON:
 | 
			
		||||
 *	VB2 is streaming. Callers should not check it directly. Instead,
 | 
			
		||||
 *	they should use dvb_vb2_is_streaming().
 | 
			
		||||
 *
 | 
			
		||||
 * Note:
 | 
			
		||||
 *
 | 
			
		||||
 * Callers should not touch at the state machine directly. This
 | 
			
		||||
 * is handled inside dvb_vb2.c.
 | 
			
		||||
 */
 | 
			
		||||
enum dvb_vb2_states {
 | 
			
		||||
	DVB_VB2_STATE_NONE	= 0x0,
 | 
			
		||||
	DVB_VB2_STATE_INIT	= 0x1,
 | 
			
		||||
	DVB_VB2_STATE_REQBUFS	= 0x2,
 | 
			
		||||
	DVB_VB2_STATE_STREAMON	= 0x4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DVB_VB2_NAME_MAX (20)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_buffer - video buffer information for v4l2.
 | 
			
		||||
 *
 | 
			
		||||
 * @vb:		embedded struct &vb2_buffer.
 | 
			
		||||
 * @list:	list of &struct dvb_buffer.
 | 
			
		||||
 */
 | 
			
		||||
struct dvb_buffer {
 | 
			
		||||
	struct vb2_buffer	vb;
 | 
			
		||||
	struct list_head	list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct dvb_vb2_ctx - control struct for VB2 handler
 | 
			
		||||
 * @vb_q:	pointer to &struct vb2_queue with videobuf2 queue.
 | 
			
		||||
 * @mutex:	mutex to serialize vb2 operations. Used by
 | 
			
		||||
 *		vb2 core %wait_prepare and %wait_finish operations.
 | 
			
		||||
 * @slock:	spin lock used to protect buffer filling at dvb_vb2.c.
 | 
			
		||||
 * @dvb_q:	List of buffers that are not filled yet.
 | 
			
		||||
 * @buf:	Pointer to the buffer that are currently being filled.
 | 
			
		||||
 * @offset:	index to the next position at the @buf to be filled.
 | 
			
		||||
 * @remain:	How many bytes are left to be filled at @buf.
 | 
			
		||||
 * @state:	bitmask of buffer states as defined by &enum dvb_vb2_states.
 | 
			
		||||
 * @buf_siz:	size of each VB2 buffer.
 | 
			
		||||
 * @buf_cnt:	number of VB2 buffers.
 | 
			
		||||
 * @nonblocking:
 | 
			
		||||
 *		If different than zero, device is operating on non-blocking
 | 
			
		||||
 *		mode.
 | 
			
		||||
 * @flags:	buffer flags as defined by &enum dmx_buffer_flags.
 | 
			
		||||
 *		Filled only at &DMX_DQBUF. &DMX_QBUF should zero this field.
 | 
			
		||||
 * @count:	monotonic counter for filled buffers. Helps to identify
 | 
			
		||||
 *		data stream loses. Filled only at &DMX_DQBUF. &DMX_QBUF should
 | 
			
		||||
 *		zero this field.
 | 
			
		||||
 *
 | 
			
		||||
 * @name:	name of the device type. Currently, it can either be
 | 
			
		||||
 *		"dvr" or "demux_filter".
 | 
			
		||||
 */
 | 
			
		||||
struct dvb_vb2_ctx {
 | 
			
		||||
	struct vb2_queue	vb_q;
 | 
			
		||||
	struct mutex		mutex;
 | 
			
		||||
	spinlock_t		slock;
 | 
			
		||||
	struct list_head	dvb_q;
 | 
			
		||||
	struct dvb_buffer	*buf;
 | 
			
		||||
	int	offset;
 | 
			
		||||
	int	remain;
 | 
			
		||||
	int	state;
 | 
			
		||||
	int	buf_siz;
 | 
			
		||||
	int	buf_cnt;
 | 
			
		||||
	int	nonblocking;
 | 
			
		||||
 | 
			
		||||
	enum dmx_buffer_flags flags;
 | 
			
		||||
	u32	count;
 | 
			
		||||
 | 
			
		||||
	char	name[DVB_VB2_NAME_MAX + 1];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifndef CONFIG_DVB_MMAP
 | 
			
		||||
static inline int dvb_vb2_init(struct dvb_vb2_ctx *ctx,
 | 
			
		||||
			       const char *name, int non_blocking)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
};
 | 
			
		||||
static inline int dvb_vb2_release(struct dvb_vb2_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
};
 | 
			
		||||
#define dvb_vb2_is_streaming(ctx) (0)
 | 
			
		||||
#define dvb_vb2_fill_buffer(ctx, file, wait, flags) (0)
 | 
			
		||||
 | 
			
		||||
static inline __poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx,
 | 
			
		||||
				    struct file *file,
 | 
			
		||||
				    poll_table *wait)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_init - initializes VB2 handler
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 * @name:	name for the VB2 handler
 | 
			
		||||
 * @non_blocking:
 | 
			
		||||
 *		if not zero, it means that the device is at non-blocking mode
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int non_blocking);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_release - Releases the VB2 handler allocated resources and
 | 
			
		||||
 *	put @ctx at DVB_VB2_STATE_NONE state.
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_release(struct dvb_vb2_ctx *ctx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_is_streaming - checks if the VB2 handler is streaming
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 if not streaming, 1 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_is_streaming(struct dvb_vb2_ctx *ctx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_fill_buffer - fills a VB2 buffer
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 * @src:	place where the data is stored
 | 
			
		||||
 * @len:	number of bytes to be copied from @src
 | 
			
		||||
 * @buffer_flags:
 | 
			
		||||
 *		pointer to buffer flags as defined by &enum dmx_buffer_flags.
 | 
			
		||||
 *		can be NULL.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx,
 | 
			
		||||
			const unsigned char *src, int len,
 | 
			
		||||
			enum dmx_buffer_flags *buffer_flags);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_poll - Wrapper to vb2_core_streamon() for Digital TV
 | 
			
		||||
 *      buffer handling.
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 * @file:	&struct file argument passed to the poll
 | 
			
		||||
 *		file operation handler.
 | 
			
		||||
 * @wait:	&poll_table wait argument passed to the poll
 | 
			
		||||
 *		file operation handler.
 | 
			
		||||
 *
 | 
			
		||||
 * Implements poll syscall() logic.
 | 
			
		||||
 */
 | 
			
		||||
__poll_t dvb_vb2_poll(struct dvb_vb2_ctx *ctx, struct file *file,
 | 
			
		||||
		      poll_table *wait);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_stream_on() - Wrapper to vb2_core_streamon() for Digital TV
 | 
			
		||||
 *	buffer handling.
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 *
 | 
			
		||||
 * Starts dvb streaming
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_stream_on(struct dvb_vb2_ctx *ctx);
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_stream_off() - Wrapper to vb2_core_streamoff() for Digital TV
 | 
			
		||||
 *	buffer handling.
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 *
 | 
			
		||||
 * Stops dvb streaming
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_stream_off(struct dvb_vb2_ctx *ctx);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_reqbufs() - Wrapper to vb2_core_reqbufs() for Digital TV
 | 
			
		||||
 *	buffer handling.
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 * @req:	&struct dmx_requestbuffers passed from userspace in
 | 
			
		||||
 *		order to handle &DMX_REQBUFS.
 | 
			
		||||
 *
 | 
			
		||||
 * Initiate streaming by requesting a number of buffers. Also used to
 | 
			
		||||
 * free previously requested buffers, is ``req->count`` is zero.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_querybuf() - Wrapper to vb2_core_querybuf() for Digital TV
 | 
			
		||||
 *	buffer handling.
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 * @b:		&struct dmx_buffer passed from userspace in
 | 
			
		||||
 *		order to handle &DMX_QUERYBUF.
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_expbuf() - Wrapper to vb2_core_expbuf() for Digital TV
 | 
			
		||||
 *	buffer handling.
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 * @exp:	&struct dmx_exportbuffer passed from userspace in
 | 
			
		||||
 *		order to handle &DMX_EXPBUF.
 | 
			
		||||
 *
 | 
			
		||||
 * Export a buffer as a file descriptor.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_qbuf() - Wrapper to vb2_core_qbuf() for Digital TV buffer handling.
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 * @b:		&struct dmx_buffer passed from userspace in
 | 
			
		||||
 *		order to handle &DMX_QBUF.
 | 
			
		||||
 *
 | 
			
		||||
 * Queue a Digital TV buffer as requested by userspace
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_dqbuf() - Wrapper to vb2_core_dqbuf() for Digital TV
 | 
			
		||||
 *	buffer handling.
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 * @b:		&struct dmx_buffer passed from userspace in
 | 
			
		||||
 *		order to handle &DMX_DQBUF.
 | 
			
		||||
 *
 | 
			
		||||
 * Dequeue a Digital TV buffer to the userspace
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_vb2_mmap() - Wrapper to vb2_mmap() for Digital TV buffer handling.
 | 
			
		||||
 *
 | 
			
		||||
 * @ctx:	control struct for VB2 handler
 | 
			
		||||
 * @vma:        pointer to &struct vm_area_struct with the vma passed
 | 
			
		||||
 *              to the mmap file operation handler in the driver.
 | 
			
		||||
 *
 | 
			
		||||
 * map Digital TV video buffers into application address space.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_vb2_mmap(struct dvb_vb2_ctx *ctx, struct vm_area_struct *vma);
 | 
			
		||||
 | 
			
		||||
#endif /* _DVB_VB2_H */
 | 
			
		||||
@@ -35,19 +35,42 @@
 | 
			
		||||
 | 
			
		||||
#define DVB_UNSET (-1)
 | 
			
		||||
 | 
			
		||||
#define DVB_DEVICE_VIDEO      0
 | 
			
		||||
#define DVB_DEVICE_AUDIO      1
 | 
			
		||||
#define DVB_DEVICE_SEC        2
 | 
			
		||||
#define DVB_DEVICE_FRONTEND   3
 | 
			
		||||
#define DVB_DEVICE_DEMUX      4
 | 
			
		||||
#define DVB_DEVICE_DVR        5
 | 
			
		||||
#define DVB_DEVICE_CA         6
 | 
			
		||||
#define DVB_DEVICE_NET        7
 | 
			
		||||
#define DVB_DEVICE_OSD        8
 | 
			
		||||
#define DVB_DEVICE_CI         9
 | 
			
		||||
#define DVB_DEVICE_MOD       10
 | 
			
		||||
#define DVB_DEVICE_NS        11
 | 
			
		||||
#define DVB_DEVICE_NSD       12
 | 
			
		||||
/* List of DVB device types */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum dvb_device_type - type of the Digital TV device
 | 
			
		||||
 *
 | 
			
		||||
 * @DVB_DEVICE_SEC:		Digital TV standalone Common Interface (CI)
 | 
			
		||||
 * @DVB_DEVICE_FRONTEND:	Digital TV frontend.
 | 
			
		||||
 * @DVB_DEVICE_DEMUX:		Digital TV demux.
 | 
			
		||||
 * @DVB_DEVICE_DVR:		Digital TV digital video record (DVR).
 | 
			
		||||
 * @DVB_DEVICE_CA:		Digital TV Conditional Access (CA).
 | 
			
		||||
 * @DVB_DEVICE_NET:		Digital TV network.
 | 
			
		||||
 *
 | 
			
		||||
 * @DVB_DEVICE_VIDEO:		Digital TV video decoder.
 | 
			
		||||
 *				Deprecated. Used only on av7110-av.
 | 
			
		||||
 * @DVB_DEVICE_AUDIO:		Digital TV audio decoder.
 | 
			
		||||
 *				Deprecated. Used only on av7110-av.
 | 
			
		||||
 * @DVB_DEVICE_OSD:		Digital TV On Screen Display (OSD).
 | 
			
		||||
 *				Deprecated. Used only on av7110.
 | 
			
		||||
 */
 | 
			
		||||
enum dvb_device_type {
 | 
			
		||||
	DVB_DEVICE_SEC,
 | 
			
		||||
	DVB_DEVICE_FRONTEND,
 | 
			
		||||
	DVB_DEVICE_DEMUX,
 | 
			
		||||
	DVB_DEVICE_DVR,
 | 
			
		||||
	DVB_DEVICE_CA,
 | 
			
		||||
	DVB_DEVICE_NET,
 | 
			
		||||
 | 
			
		||||
	DVB_DEVICE_VIDEO,
 | 
			
		||||
	DVB_DEVICE_AUDIO,
 | 
			
		||||
	DVB_DEVICE_OSD,
 | 
			
		||||
 | 
			
		||||
	DVB_DEVICE_CI,
 | 
			
		||||
	DVB_DEVICE_MOD,
 | 
			
		||||
	DVB_DEVICE_NS,
 | 
			
		||||
	DVB_DEVICE_NSD,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
 | 
			
		||||
	static short adapter_nr[] = \
 | 
			
		||||
@@ -68,11 +91,12 @@ struct dvb_frontend;
 | 
			
		||||
 * @priv:		private data
 | 
			
		||||
 * @device:		pointer to struct device
 | 
			
		||||
 * @module:		pointer to struct module
 | 
			
		||||
 * @mfe_shared:		mfe shared: indicates mutually exclusive frontends
 | 
			
		||||
 *			Thie usage of this flag is currently deprecated
 | 
			
		||||
 * @mfe_shared:		indicates mutually exclusive frontends.
 | 
			
		||||
 *			Use of this flag is currently deprecated.
 | 
			
		||||
 * @mfe_dvbdev:		Frontend device in use, in the case of MFE
 | 
			
		||||
 * @mfe_lock:		Lock to prevent using the other frontends when MFE is
 | 
			
		||||
 *			used.
 | 
			
		||||
 * @mdev_lock:          Protect access to the mdev pointer.
 | 
			
		||||
 * @mdev:		pointer to struct media_device, used when the media
 | 
			
		||||
 *			controller is used.
 | 
			
		||||
 * @conn:		RF connector. Used only if the device has no separate
 | 
			
		||||
@@ -96,6 +120,7 @@ struct dvb_adapter {
 | 
			
		||||
	struct mutex mfe_lock;		/* access lock for thread creation */
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
 | 
			
		||||
	struct mutex mdev_lock;
 | 
			
		||||
	struct media_device *mdev;
 | 
			
		||||
	struct media_entity *conn;
 | 
			
		||||
	struct media_pad *conn_pads;
 | 
			
		||||
@@ -108,8 +133,7 @@ struct dvb_adapter {
 | 
			
		||||
 * @list_head:	List head with all DVB devices
 | 
			
		||||
 * @fops:	pointer to struct file_operations
 | 
			
		||||
 * @adapter:	pointer to the adapter that holds this device node
 | 
			
		||||
 * @type:	type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND,
 | 
			
		||||
 *		DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET
 | 
			
		||||
 * @type:	type of the device, as defined by &enum dvb_device_type.
 | 
			
		||||
 * @minor:	devnode minor number. Major number is always DVB_MAJOR.
 | 
			
		||||
 * @id:		device ID number, inside the adapter
 | 
			
		||||
 * @readers:	Initialized by the caller. Each call to open() in Read Only mode
 | 
			
		||||
@@ -139,7 +163,7 @@ struct dvb_device {
 | 
			
		||||
	struct list_head list_head;
 | 
			
		||||
	const struct file_operations *fops;
 | 
			
		||||
	struct dvb_adapter *adapter;
 | 
			
		||||
	int type;
 | 
			
		||||
	enum dvb_device_type type;
 | 
			
		||||
	int minor;
 | 
			
		||||
	u32 id;
 | 
			
		||||
 | 
			
		||||
@@ -198,9 +222,7 @@ int dvb_unregister_adapter(struct dvb_adapter *adap);
 | 
			
		||||
 *		stored
 | 
			
		||||
 * @template:	Template used to create &pdvbdev;
 | 
			
		||||
 * @priv:	private data
 | 
			
		||||
 * @type:	type of the device: %DVB_DEVICE_SEC, %DVB_DEVICE_FRONTEND,
 | 
			
		||||
 *		%DVB_DEVICE_DEMUX, %DVB_DEVICE_DVR, %DVB_DEVICE_CA,
 | 
			
		||||
 *		%DVB_DEVICE_NET
 | 
			
		||||
 * @type:	type of the device, as defined by &enum dvb_device_type.
 | 
			
		||||
 * @demux_sink_pads: Number of demux outputs, to be used to create the TS
 | 
			
		||||
 *		outputs via the Media Controller.
 | 
			
		||||
 */
 | 
			
		||||
@@ -208,7 +230,7 @@ int dvb_register_device(struct dvb_adapter *adap,
 | 
			
		||||
			struct dvb_device **pdvbdev,
 | 
			
		||||
			const struct dvb_device *template,
 | 
			
		||||
			void *priv,
 | 
			
		||||
			int type,
 | 
			
		||||
			enum dvb_device_type type,
 | 
			
		||||
			int demux_sink_pads);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -246,7 +268,7 @@ void dvb_unregister_device(struct dvb_device *dvbdev);
 | 
			
		||||
 * dvb_create_media_graph - Creates media graph for the Digital TV part of the
 | 
			
		||||
 *				device.
 | 
			
		||||
 *
 | 
			
		||||
 * @adap:			pointer to struct dvb_adapter
 | 
			
		||||
 * @adap:			pointer to &struct dvb_adapter
 | 
			
		||||
 * @create_rf_connector:	if true, it creates the RF connector too
 | 
			
		||||
 *
 | 
			
		||||
 * This function checks all DVB-related functions at the media controller
 | 
			
		||||
@@ -259,14 +281,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev);
 | 
			
		||||
__must_check int dvb_create_media_graph(struct dvb_adapter *adap,
 | 
			
		||||
					bool create_rf_connector);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_register_media_controller - registers a media controller at DVB adapter
 | 
			
		||||
 *
 | 
			
		||||
 * @adap:			pointer to &struct dvb_adapter
 | 
			
		||||
 * @mdev:			pointer to &struct media_device
 | 
			
		||||
 */
 | 
			
		||||
static inline void dvb_register_media_controller(struct dvb_adapter *adap,
 | 
			
		||||
						 struct media_device *mdev)
 | 
			
		||||
{
 | 
			
		||||
	adap->mdev = mdev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct media_device
 | 
			
		||||
*dvb_get_media_controller(struct dvb_adapter *adap)
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_get_media_controller - gets the associated media controller
 | 
			
		||||
 *
 | 
			
		||||
 * @adap:			pointer to &struct dvb_adapter
 | 
			
		||||
 */
 | 
			
		||||
static inline struct media_device *
 | 
			
		||||
dvb_get_media_controller(struct dvb_adapter *adap)
 | 
			
		||||
{
 | 
			
		||||
	return adap->mdev;
 | 
			
		||||
}
 | 
			
		||||
@@ -281,20 +314,131 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 | 
			
		||||
#define dvb_get_media_controller(a) NULL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int dvb_generic_open (struct inode *inode, struct file *file);
 | 
			
		||||
int dvb_generic_release (struct inode *inode, struct file *file);
 | 
			
		||||
long dvb_generic_ioctl (struct file *file,
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_generic_open - Digital TV open function, used by DVB devices
 | 
			
		||||
 *
 | 
			
		||||
 * @inode: pointer to &struct inode.
 | 
			
		||||
 * @file: pointer to &struct file.
 | 
			
		||||
 *
 | 
			
		||||
 * Checks if a DVB devnode is still valid, and if the permissions are
 | 
			
		||||
 * OK and increment negative use count.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_generic_open(struct inode *inode, struct file *file);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_generic_close - Digital TV close function, used by DVB devices
 | 
			
		||||
 *
 | 
			
		||||
 * @inode: pointer to &struct inode.
 | 
			
		||||
 * @file: pointer to &struct file.
 | 
			
		||||
 *
 | 
			
		||||
 * Checks if a DVB devnode is still valid, and if the permissions are
 | 
			
		||||
 * OK and decrement negative use count.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_generic_release(struct inode *inode, struct file *file);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_generic_ioctl - Digital TV close function, used by DVB devices
 | 
			
		||||
 *
 | 
			
		||||
 * @file: pointer to &struct file.
 | 
			
		||||
 * @cmd: Ioctl name.
 | 
			
		||||
 * @arg: Ioctl argument.
 | 
			
		||||
 *
 | 
			
		||||
 * Checks if a DVB devnode and struct dvbdev.kernel_ioctl is still valid.
 | 
			
		||||
 * If so, calls dvb_usercopy().
 | 
			
		||||
 */
 | 
			
		||||
long dvb_generic_ioctl(struct file *file,
 | 
			
		||||
		       unsigned int cmd, unsigned long arg);
 | 
			
		||||
 | 
			
		||||
/* we don't mess with video_usercopy() any more,
 | 
			
		||||
we simply define out own dvb_usercopy(), which will hopefully become
 | 
			
		||||
generic_usercopy()  someday... */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_usercopy - copies data from/to userspace memory when an ioctl is
 | 
			
		||||
 *      issued.
 | 
			
		||||
 *
 | 
			
		||||
 * @file: Pointer to struct &file.
 | 
			
		||||
 * @cmd: Ioctl name.
 | 
			
		||||
 * @arg: Ioctl argument.
 | 
			
		||||
 * @func: function that will actually handle the ioctl
 | 
			
		||||
 *
 | 
			
		||||
 * Ancillary function that uses ioctl direction and size to copy from
 | 
			
		||||
 * userspace. Then, it calls @func, and, if needed, data is copied back
 | 
			
		||||
 * to userspace.
 | 
			
		||||
 */
 | 
			
		||||
int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
 | 
			
		||||
		 int (*func)(struct file *file, unsigned int cmd, void *arg));
 | 
			
		||||
 | 
			
		||||
/** generic DVB attach function. */
 | 
			
		||||
#if IS_ENABLED(CONFIG_I2C)
 | 
			
		||||
 | 
			
		||||
struct i2c_adapter;
 | 
			
		||||
struct i2c_client;
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_module_probe - helper routine to probe an I2C module
 | 
			
		||||
 *
 | 
			
		||||
 * @module_name:
 | 
			
		||||
 *	Name of the I2C module to be probed
 | 
			
		||||
 * @name:
 | 
			
		||||
 *	Optional name for the I2C module. Used for debug purposes.
 | 
			
		||||
 * 	If %NULL, defaults to @module_name.
 | 
			
		||||
 * @adap:
 | 
			
		||||
 *	pointer to &struct i2c_adapter that describes the I2C adapter where
 | 
			
		||||
 *	the module will be bound.
 | 
			
		||||
 * @addr:
 | 
			
		||||
 *	I2C address of the adapter, in 7-bit notation.
 | 
			
		||||
 * @platform_data:
 | 
			
		||||
 *	Platform data to be passed to the I2C module probed.
 | 
			
		||||
 *
 | 
			
		||||
 * This function binds an I2C device into the DVB core. Should be used by
 | 
			
		||||
 * all drivers that use I2C bus to control the hardware. A module bound
 | 
			
		||||
 * with dvb_module_probe() should use dvb_module_release() to unbind.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *	On success, return an &struct i2c_client, pointing to the bound
 | 
			
		||||
 *	I2C device. %NULL otherwise.
 | 
			
		||||
 *
 | 
			
		||||
 * .. note::
 | 
			
		||||
 *
 | 
			
		||||
 *    In the past, DVB modules (mainly, frontends) were bound via dvb_attach()
 | 
			
		||||
 *    macro, with does an ugly hack, using I2C low level functions. Such
 | 
			
		||||
 *    usage is deprecated and will be removed soon. Instead, use this routine.
 | 
			
		||||
 */
 | 
			
		||||
struct i2c_client *dvb_module_probe(const char *module_name,
 | 
			
		||||
				    const char *name,
 | 
			
		||||
				    struct i2c_adapter *adap,
 | 
			
		||||
				    unsigned char addr,
 | 
			
		||||
				    void *platform_data);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_module_release - releases an I2C device allocated with
 | 
			
		||||
 *	 dvb_module_probe().
 | 
			
		||||
 *
 | 
			
		||||
 * @client: pointer to &struct i2c_client with the I2C client to be released.
 | 
			
		||||
 *	    can be %NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * This function should be used to free all resources reserved by
 | 
			
		||||
 * dvb_module_probe() and unbinding the I2C hardware.
 | 
			
		||||
 */
 | 
			
		||||
void dvb_module_release(struct i2c_client *client);
 | 
			
		||||
 | 
			
		||||
#endif /* CONFIG_I2C */
 | 
			
		||||
 | 
			
		||||
/* Legacy generic DVB attach function. */
 | 
			
		||||
#ifdef CONFIG_MEDIA_ATTACH
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_attach - attaches a DVB frontend into the DVB core.
 | 
			
		||||
 *
 | 
			
		||||
 * @FUNCTION:	function on a frontend module to be called.
 | 
			
		||||
 * @ARGS...:	@FUNCTION arguments.
 | 
			
		||||
 *
 | 
			
		||||
 * This ancillary function loads a frontend module in runtime and runs
 | 
			
		||||
 * the @FUNCTION function there, with @ARGS.
 | 
			
		||||
 * As it increments symbol usage cont, at unregister, dvb_detach()
 | 
			
		||||
 * should be called.
 | 
			
		||||
 *
 | 
			
		||||
 * .. note::
 | 
			
		||||
 *
 | 
			
		||||
 *    In the past, DVB modules (mainly, frontends) were bound via dvb_attach()
 | 
			
		||||
 *    macro, with does an ugly hack, using I2C low level functions. Such
 | 
			
		||||
 *    usage is deprecated and will be removed soon. Instead, you should use
 | 
			
		||||
 *    dvb_module_probe().
 | 
			
		||||
 */
 | 
			
		||||
#define dvb_attach(FUNCTION, ARGS...) ({ \
 | 
			
		||||
	void *__r = NULL; \
 | 
			
		||||
	typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
 | 
			
		||||
@@ -308,6 +452,14 @@ int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
 | 
			
		||||
	__r; \
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * dvb_detach - detaches a DVB frontend loaded via dvb_attach()
 | 
			
		||||
 *
 | 
			
		||||
 * @FUNC:	attach function
 | 
			
		||||
 *
 | 
			
		||||
 * Decrements usage count for a function previously called via dvb_attach().
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define dvb_detach(FUNC)	symbol_put_addr(FUNC)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
@@ -317,6 +469,6 @@ int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
 | 
			
		||||
 | 
			
		||||
#define dvb_detach(FUNC)	{}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif	/* CONFIG_MEDIA_ATTACH */
 | 
			
		||||
 | 
			
		||||
#endif /* #ifndef _DVBDEV_H_ */
 | 
			
		||||
@@ -16,7 +16,7 @@ dddvb_test: dddvb_test.o
 | 
			
		||||
	$(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 -l dvben50221 -l dvbapi -l ucsi
 | 
			
		||||
	$(CC) -o ddzap  $< -L ./src -l dddvb -l pthread -l dvben50221 -l dvbapi -l ucsi -lm
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	make -C ./src clean
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										312
									
								
								lib/ddzap.c
									
									
									
									
									
								
							
							
						
						
									
										312
									
								
								lib/ddzap.c
									
									
									
									
									
								
							@@ -10,7 +10,248 @@
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
char line_start[16] = "";
 | 
			
		||||
char line_end[16]   = "\r";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t cc_errors = 0;
 | 
			
		||||
uint32_t packets = 0;
 | 
			
		||||
uint32_t payload_packets = 0;
 | 
			
		||||
uint32_t packet_errors = 0;
 | 
			
		||||
 | 
			
		||||
uint8_t cc[8192] = { 0 };
 | 
			
		||||
 | 
			
		||||
enum { IQ_RED=1, IQ_GREE, IQ_BLUE , IQ_EVIL, IQ_LOG_RED, IQ_LOG_GREEN, IQ_LOG_BLUE , IQ_LOG_EVIL , IQ_TEST, };
 | 
			
		||||
 | 
			
		||||
typedef struct pamdata_
 | 
			
		||||
{
 | 
			
		||||
    unsigned char *data_points;
 | 
			
		||||
    uint64_t *data;
 | 
			
		||||
    int col;
 | 
			
		||||
} pamdata;
 | 
			
		||||
 | 
			
		||||
int init_pamdata(pamdata *iq,int color)
 | 
			
		||||
{
 | 
			
		||||
    iq->col = 0;
 | 
			
		||||
    if (!( iq->data=(uint64_t *) malloc(sizeof(uint64_t) *256*256)))
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr,"not enough memory\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    memset(iq->data,0,256*256*sizeof(uint64_t));
 | 
			
		||||
    if (!( iq->data_points=(unsigned char *) malloc(sizeof(unsigned char) *
 | 
			
		||||
                                             256*256*3)))
 | 
			
		||||
    {
 | 
			
		||||
        fprintf(stderr,"not enough memory\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    memset(iq->data_points,0,256*256*3*sizeof(char));
 | 
			
		||||
    iq->col = color;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static long getutime(){
 | 
			
		||||
        struct timespec t0;
 | 
			
		||||
        clock_gettime(CLOCK_MONOTONIC_RAW,&t0);
 | 
			
		||||
        return t0.tv_sec * (int)1e9 + t0.tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pam_coordinate_axes(pamdata *iq, unsigned char r,
 | 
			
		||||
                         unsigned char g, unsigned char b){
 | 
			
		||||
    int i;
 | 
			
		||||
    for (i = 0; i < 256*3; i+=3){
 | 
			
		||||
        // coordinate axes
 | 
			
		||||
        int xr = i    + 256*128*3;
 | 
			
		||||
        int yr =128*3 + i*256;
 | 
			
		||||
        iq->data_points[xr] = r;
 | 
			
		||||
        iq->data_points[yr] = r;
 | 
			
		||||
        iq->data_points[xr+1] = g;
 | 
			
		||||
        iq->data_points[yr+1] = g;
 | 
			
		||||
        iq->data_points[xr+2] = b;
 | 
			
		||||
        iq->data_points[yr+2] = b;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
void pam_data_convert(pamdata *iq ,uint64_t maxd)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    uint64_t m = 255*maxd;
 | 
			
		||||
    double lm = log((double)m);
 | 
			
		||||
    memset(iq->data_points,0,256*256*3*sizeof(char));
 | 
			
		||||
    for (i = 0; i < 256*256*3; i+=3){
 | 
			
		||||
        // IQ data plot
 | 
			
		||||
        int r = i; 
 | 
			
		||||
        int g = i+1;
 | 
			
		||||
        int b = i+2;
 | 
			
		||||
        uint64_t odata = iq->data[i/3];
 | 
			
		||||
        uint64_t data = 255*iq->data[i/3];
 | 
			
		||||
        double lod = log((double)odata); 
 | 
			
		||||
        double q = lod/lm;
 | 
			
		||||
     if (data){
 | 
			
		||||
            switch (iq->col){
 | 
			
		||||
            case IQ_LOG_EVIL:
 | 
			
		||||
                if ( q < 0.25){
 | 
			
		||||
                    iq->data_points[b] = (int)(1024.0*q);
 | 
			
		||||
                } else {
 | 
			
		||||
                        if (q >0.5) iq->data_points[g] = (int)(255.0*q);
 | 
			
		||||
                    else
 | 
			
		||||
                        iq->data_points[r] = (int)(512.0*q);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case IQ_LOG_RED:
 | 
			
		||||
                iq->data_points[r] = (int)(255.0*q)&0xff;
 | 
			
		||||
                break;
 | 
			
		||||
            case IQ_LOG_GREEN:
 | 
			
		||||
                iq->data_points[g] = (int)(255.0*q)&0xff;
 | 
			
		||||
                break;
 | 
			
		||||
            case IQ_LOG_BLUE:
 | 
			
		||||
                iq->data_points[b] = (int)(255.0*q)&0xff;
 | 
			
		||||
                break;
 | 
			
		||||
            case IQ_EVIL:
 | 
			
		||||
                if  (data < m/4){
 | 
			
		||||
                    iq->data_points[b] = ((4*data)/maxd)&0xff;
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (data >m/2) iq->data_points[g] = (data/maxd)&0xff;
 | 
			
		||||
                    else iq->data_points[r] = (2*data/maxd)&0xff;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case IQ_TEST:
 | 
			
		||||
                if  (data < m/4){
 | 
			
		||||
                    iq->data_points[b] = ((4*data)/maxd)&0xff;
 | 
			
		||||
                    iq->data_points[g] = ((4*data)/maxd)&0xff;
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (data >m/2) {
 | 
			
		||||
                        iq->data_points[g] = (data/maxd)&0xff;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        iq->data_points[g] = (2*data/maxd)&0xff;
 | 
			
		||||
                        iq->data_points[r] = (2*data/maxd)&0xff;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
          case IQ_RED:
 | 
			
		||||
                iq->data_points[r] = (data/maxd)&0xff;
 | 
			
		||||
                break;
 | 
			
		||||
            case IQ_BLUE:
 | 
			
		||||
                iq->data_points[b] = (data/maxd)&0xff;
 | 
			
		||||
                break;
 | 
			
		||||
                
 | 
			
		||||
            default:
 | 
			
		||||
            case IQ_GREE:
 | 
			
		||||
                iq->data_points[g] = (data/maxd)&0xff;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#define TS_SIZE 188
 | 
			
		||||
#define BSIZE 100*TS_SIZE
 | 
			
		||||
#define DTIME 40000000ULL
 | 
			
		||||
void pam_read_data (int fdin, pamdata *iq)
 | 
			
		||||
{
 | 
			
		||||
    int8_t buf[BSIZE];
 | 
			
		||||
    int i,j;
 | 
			
		||||
    
 | 
			
		||||
    long t0;
 | 
			
		||||
    long t1;
 | 
			
		||||
    uint64_t maxd = 0;
 | 
			
		||||
    
 | 
			
		||||
    t0 = getutime();
 | 
			
		||||
    t1 = t0;
 | 
			
		||||
 | 
			
		||||
    while ((t1 - t0) < DTIME){
 | 
			
		||||
        int re =0;
 | 
			
		||||
        if ((re=read(fdin,(char *)buf, BSIZE)) < 0){
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        for (i=0; i < re; i+=TS_SIZE){
 | 
			
		||||
            for (j=4; j<TS_SIZE; j+=2){
 | 
			
		||||
                uint8_t ix = buf[i+j]+128;
 | 
			
		||||
                uint8_t qy = 128-buf[i+j+1];
 | 
			
		||||
                iq->data[ix|(qy<<8)] += 1;
 | 
			
		||||
                uint64_t c = iq->data[ix|(qy<<8)];
 | 
			
		||||
                if ( c > maxd) maxd = c;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        t1 = getutime();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pam_data_convert(iq, maxd);
 | 
			
		||||
    pam_coordinate_axes(iq, 255,255 ,0);
 | 
			
		||||
    memset(iq->data,0,256*256*sizeof(uint64_t));        
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pam_write (int fd, pamdata *iq){
 | 
			
		||||
    char *HEAD="P7\nWIDTH 256\nHEIGHT 256\nDEPTH 3\nMAXVAL 255\nTUPLTYPE RGB\nENDHDR\n";
 | 
			
		||||
    int headlen = strlen(HEAD);
 | 
			
		||||
    int we=0;
 | 
			
		||||
    we=write(fd,HEAD,headlen);
 | 
			
		||||
    we=write(fd,iq->data_points,256*256*3);
 | 
			
		||||
    memset(iq->data_points,0,256*256*3*sizeof(char));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void proc_ts(int i, uint8_t *buf)
 | 
			
		||||
{
 | 
			
		||||
  uint16_t pid=0x1fff&((buf[1]<<8)|buf[2]);
 | 
			
		||||
  uint8_t ccin = buf[3] & 0x1F;
 | 
			
		||||
  
 | 
			
		||||
	if (buf[0] == 0x47 && (buf[1] & 0x80) == 0) {
 | 
			
		||||
		if( pid != 8191 ) {
 | 
			
		||||
			if (ccin & 0x10) {
 | 
			
		||||
				if ( cc[pid]) {
 | 
			
		||||
					// TODO: 1 repetition allowed
 | 
			
		||||
					if( ( ccin & 0x10 ) != 0 && (((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) )  
 | 
			
		||||
						cc_errors += 1;
 | 
			
		||||
				}
 | 
			
		||||
				cc[pid] = ccin;
 | 
			
		||||
			}
 | 
			
		||||
			payload_packets += 1;
 | 
			
		||||
		}
 | 
			
		||||
	} else
 | 
			
		||||
		packet_errors += 1;
 | 
			
		||||
	
 | 
			
		||||
	if( (packets & 0x3FFF ) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		printf("%s  Packets: %12u non null %12u, errors: %12u, CC errors: %12u%s", line_start, packets, payload_packets, packet_errors, cc_errors, line_end);
 | 
			
		||||
		fflush(stdout);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	packets += 1;  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define TSBUFSIZE (100*188)
 | 
			
		||||
 | 
			
		||||
void tscheck(int ts)
 | 
			
		||||
{
 | 
			
		||||
        uint8_t *buf;
 | 
			
		||||
        uint8_t id;
 | 
			
		||||
        int i, nts;
 | 
			
		||||
        int len;
 | 
			
		||||
 | 
			
		||||
	buf=(uint8_t *)malloc(TSBUFSIZE);
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        while(1) {
 | 
			
		||||
                len=read(ts, buf, TSBUFSIZE);
 | 
			
		||||
                if (len<0) {
 | 
			
		||||
                        continue;
 | 
			
		||||
                }
 | 
			
		||||
                if (buf[0]!=0x47) {
 | 
			
		||||
                        read(ts, buf, 1);
 | 
			
		||||
                        continue;
 | 
			
		||||
                }
 | 
			
		||||
                if (len%188) { /* should not happen */
 | 
			
		||||
                        printf("blah\n");
 | 
			
		||||
                        continue;
 | 
			
		||||
                }
 | 
			
		||||
                nts=len/188;
 | 
			
		||||
                for (i=0; i<nts; i++)
 | 
			
		||||
                        proc_ts(i, buf+i*188);
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
		    
 | 
			
		||||
static uint32_t root2gold(uint32_t root)
 | 
			
		||||
{
 | 
			
		||||
@@ -29,16 +270,21 @@ int main(int argc, char **argv)
 | 
			
		||||
	struct dddvb *dd;
 | 
			
		||||
	struct dddvb_fe *fe;
 | 
			
		||||
	struct dddvb_params p;
 | 
			
		||||
	uint32_t bandwidth = 8000000, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF;
 | 
			
		||||
	uint32_t bandwidth = DDDVB_UNDEF, frequency = 0, symbol_rate = 0, pol = DDDVB_UNDEF;
 | 
			
		||||
	uint32_t id = DDDVB_UNDEF, ssi = DDDVB_UNDEF, num = DDDVB_UNDEF, source = 0;
 | 
			
		||||
	uint32_t mtype= DDDVB_UNDEF;
 | 
			
		||||
	uint32_t verbosity = 0;
 | 
			
		||||
	uint32_t get_ts = 1;
 | 
			
		||||
	enum fe_code_rate fec = FEC_AUTO;
 | 
			
		||||
	enum fe_delivery_system delsys = ~0;
 | 
			
		||||
	char *config = "config/";
 | 
			
		||||
	int fd = 0;
 | 
			
		||||
	int odvr = 0;
 | 
			
		||||
	FILE *fout = stdout;
 | 
			
		||||
	int line = -1;
 | 
			
		||||
	int color = 0;
 | 
			
		||||
        pamdata iq;
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	while (1) {
 | 
			
		||||
		int cur_optind = optind ? optind : 1;
 | 
			
		||||
@@ -59,21 +305,44 @@ int main(int argc, char **argv)
 | 
			
		||||
			{"mtype", required_argument, 0, 'm'},
 | 
			
		||||
			{"verbosity", required_argument, 0, 'v'},
 | 
			
		||||
			{"open_dvr", no_argument, 0, 'o'},
 | 
			
		||||
			{"tscheck", no_argument, 0, 't'},
 | 
			
		||||
			{"tscheck_l", required_argument, 0, 'a'},
 | 
			
		||||
			{"nodvr", no_argument , 0, 'q'},
 | 
			
		||||
			{"pam", no_argument , 0, 'a'},
 | 
			
		||||
			{"help", no_argument , 0, 'h'},
 | 
			
		||||
			{0, 0, 0, 0}
 | 
			
		||||
		};
 | 
			
		||||
                c = getopt_long(argc, argv, 
 | 
			
		||||
				"c:i:f:s:d:p:hg:r:n:b:l:v:m:o",
 | 
			
		||||
				"e:c:i:f:s:d:p:hg:r:n:b:l:v:m:ota:q",
 | 
			
		||||
				long_options, &option_index);
 | 
			
		||||
		if (c==-1)
 | 
			
		||||
 			break;
 | 
			
		||||
		
 | 
			
		||||
		switch (c) {
 | 
			
		||||
		case 'e':
 | 
			
		||||
		        odvr = 2;
 | 
			
		||||
		        color = strtoul(optarg, NULL, 0);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'o':
 | 
			
		||||
		        fout = stderr;
 | 
			
		||||
		        if (odvr) {
 | 
			
		||||
			    fprintf(fout,"Can't pipe dvr device when checking continuity\n");
 | 
			
		||||
			    break;
 | 
			
		||||
			}
 | 
			
		||||
		        fprintf(fout,"Reading from dvr\n");
 | 
			
		||||
		        odvr = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'a':
 | 
			
		||||
		        line = strtoul(optarg, NULL, 0);
 | 
			
		||||
		case 't':
 | 
			
		||||
		        fout = stderr;
 | 
			
		||||
		        if (odvr) {
 | 
			
		||||
			    fprintf(fout,"Can't check continuity when piping dvr device\n");
 | 
			
		||||
			    break;
 | 
			
		||||
			}
 | 
			
		||||
		        fprintf(fout,"performing continuity check\n");
 | 
			
		||||
		        odvr = 2;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'c':
 | 
			
		||||
		        config = strdup(optarg);
 | 
			
		||||
			break;
 | 
			
		||||
@@ -147,19 +416,24 @@ int main(int argc, char **argv)
 | 
			
		||||
				delsys = SYS_ISDBT;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'p':
 | 
			
		||||
			if (!strcmp(optarg, "h"))
 | 
			
		||||
			if (!strcmp(optarg, "h") || !strcmp(optarg, "H"))
 | 
			
		||||
				pol = 1;
 | 
			
		||||
			if (!strcmp(optarg, "v"))
 | 
			
		||||
			if (!strcmp(optarg, "v") || !strcmp(optarg, "V"))
 | 
			
		||||
				pol = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'q':
 | 
			
		||||
			get_ts = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'h':
 | 
			
		||||
		    fprintf(fout,"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"
 | 
			
		||||
			       "      [-o (write dvr to stdout)]\n"
 | 
			
		||||
			       "      [-l (tuner source for unicable)]\n"
 | 
			
		||||
			       "      [-t [display line](continuity check)]\n"
 | 
			
		||||
			       "\n"
 | 
			
		||||
			       "      delivery_system = C,S,S2,T,T2,J83B,ISDBC,ISDBT\n"
 | 
			
		||||
			       "      polarity        = h,v\n"
 | 
			
		||||
			       "      polarity        = h/H,v/V\n"
 | 
			
		||||
			       "\n");
 | 
			
		||||
			exit(-1);
 | 
			
		||||
		default:
 | 
			
		||||
@@ -188,6 +462,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		exit(-1);
 | 
			
		||||
	}
 | 
			
		||||
	fprintf(fout,"dvbnum = %u\n", dd->dvbfe_num);
 | 
			
		||||
	dddvb_get_ts(dd, get_ts);
 | 
			
		||||
 | 
			
		||||
	if (num != DDDVB_UNDEF)
 | 
			
		||||
		fe = dddvb_fe_alloc_num(dd, delsys, num);
 | 
			
		||||
@@ -208,6 +483,7 @@ int main(int argc, char **argv)
 | 
			
		||||
	dddvb_set_id(&p, id);
 | 
			
		||||
	dddvb_set_ssi(&p, ssi);
 | 
			
		||||
	dddvb_dvb_tune(fe, &p);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	{
 | 
			
		||||
		uint8_t ts[188];
 | 
			
		||||
@@ -226,7 +502,7 @@ int main(int argc, char **argv)
 | 
			
		||||
			cnr = dddvb_get_cnr(fe);
 | 
			
		||||
			
 | 
			
		||||
			printf("stat=%02x, str=%lld.%03llddB, snr=%lld.%03llddB \n",
 | 
			
		||||
			       stat, str/1000, abs(str%1000), cnr/1000, abs(cnr%1000));
 | 
			
		||||
			       stat, (long long int)str/1000,(long long int) abs(str%1000),(long long int) cnr/1000, (long long int)abs(cnr%1000));
 | 
			
		||||
		sleep(1);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
@@ -244,8 +520,8 @@ int main(int argc, char **argv)
 | 
			
		||||
			str = dddvb_get_strength(fe);
 | 
			
		||||
			cnr = dddvb_get_cnr(fe);
 | 
			
		||||
			
 | 
			
		||||
			printf("stat=%02x, str=%lld.%03llddB, snr=%lld.%03llddB \n",
 | 
			
		||||
			       stat, str/1000, abs(str%1000), cnr/1000, abs(cnr%1000));
 | 
			
		||||
			fprintf(stderr,"stat=%02x, str=%lld.%03llddB, snr=%lld.%03llddB \n",
 | 
			
		||||
			       stat,(long long int) str/1000,(long long int) abs(str%1000),(long long int) cnr/1000, (long long int)abs(cnr%1000));
 | 
			
		||||
			sleep(1);
 | 
			
		||||
		}
 | 
			
		||||
		fprintf(stderr,"got lock on %s\n", fe->name);
 | 
			
		||||
@@ -255,9 +531,29 @@ int main(int argc, char **argv)
 | 
			
		||||
		if ((fd = open(filename ,O_RDONLY)) < 0){
 | 
			
		||||
		    fprintf(stderr,"Error opening input file:%s\n",filename);
 | 
			
		||||
		}
 | 
			
		||||
		if (odvr > 0){
 | 
			
		||||
		    switch (odvr){
 | 
			
		||||
		    case 1:
 | 
			
		||||
			while(1){
 | 
			
		||||
			    read(fd,buf,BUFFSIZE);
 | 
			
		||||
			    write(fileno(stdout),buf,BUFFSIZE);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		    case 2:
 | 
			
		||||
                        fprintf(stderr,"writing pamdata\n");
 | 
			
		||||
                        init_pamdata(&iq,color);
 | 
			
		||||
                        while(1){
 | 
			
		||||
                            pam_read_data(fd, &iq);
 | 
			
		||||
                            pam_write(STDOUT_FILENO, &iq);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
		    }
 | 
			
		||||
		} else {
 | 
			
		||||
		    if( line >= 0 && line < 64 ){
 | 
			
		||||
			snprintf(line_start,sizeof(line_start)-1,"\0337\033[%d;0H",line);
 | 
			
		||||
			strncpy(line_end,"\0338",sizeof(line_end)-1);
 | 
			
		||||
		    }
 | 
			
		||||
		    tscheck(fd);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ int parse_config(struct dddvb *dd, char *name, char *sec,
 | 
			
		||||
		memcpy(fname + config_len, "dddvb.conf", 11);
 | 
			
		||||
	
 | 
			
		||||
	if ((f = fopen (fname, "r")) == NULL) {
 | 
			
		||||
		printf("config fiile %s not found\n", fname);
 | 
			
		||||
		printf("config file %s not found\n", fname);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 
 | 
			
		||||
@@ -89,6 +89,7 @@ LIBDDDVB_EXPORTED struct dddvb *dddvb_init(char *config, uint32_t flags)
 | 
			
		||||
	
 | 
			
		||||
	dddvb_dvb_init(dd);
 | 
			
		||||
	global_dd = dd;
 | 
			
		||||
	dd->get_ts = 1;
 | 
			
		||||
fail:
 | 
			
		||||
	pthread_mutex_unlock(&dddvb_mutex);
 | 
			
		||||
	return dd;
 | 
			
		||||
 
 | 
			
		||||
@@ -75,6 +75,7 @@ struct dddvb_fe {
 | 
			
		||||
	uint32_t level;
 | 
			
		||||
	uint32_t lock;
 | 
			
		||||
	uint32_t quality;
 | 
			
		||||
	uint32_t pls_code;
 | 
			
		||||
	int64_t strength;
 | 
			
		||||
	int64_t cnr;
 | 
			
		||||
	int64_t ber;
 | 
			
		||||
@@ -150,6 +151,9 @@ struct dddvb {
 | 
			
		||||
	
 | 
			
		||||
	struct dddvb_fe dvbfe[DDDVB_MAX_DVB_FE];
 | 
			
		||||
	struct dddvb_ca dvbca[DDDVB_MAX_DVB_CA];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	unsigned int get_ts:1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int dddvb_dvb_init(struct dddvb *dd);
 | 
			
		||||
 
 | 
			
		||||
@@ -128,6 +128,9 @@ static int set_fe_input(struct dddvb_fe *fe, uint32_t fr,
 | 
			
		||||
	}
 | 
			
		||||
	if (input != DDDVB_UNDEF)
 | 
			
		||||
		set_property(fd, DTV_INPUT, input);
 | 
			
		||||
	fprintf(stderr, "bw =%u\n", fe->param.param[PARAM_BW_HZ]);
 | 
			
		||||
	if (fe->param.param[PARAM_BW_HZ] != DDDVB_UNDEF)
 | 
			
		||||
		set_property(fd, DTV_BANDWIDTH_HZ, fe->param.param[PARAM_BW_HZ]);
 | 
			
		||||
	if (fe->param.param[PARAM_ISI] != DDDVB_UNDEF)
 | 
			
		||||
		set_property(fd, DTV_STREAM_ID, fe->param.param[PARAM_ISI]);
 | 
			
		||||
	if (fe->param.param[PARAM_SSI] != DDDVB_UNDEF)
 | 
			
		||||
@@ -228,6 +231,7 @@ static int set_en50607(struct dddvb_fe *fe, uint32_t freq, uint32_t sr,
 | 
			
		||||
	uint32_t input = 3 & (sat >> 6);
 | 
			
		||||
	int fd = fe->fd;
 | 
			
		||||
	
 | 
			
		||||
	//printf("input = %u, sat = %u\n", input, sat&0x3f);
 | 
			
		||||
	hor &= 1;
 | 
			
		||||
	cmd.msg[1] = slot << 3;
 | 
			
		||||
	cmd.msg[1] |= ((t >> 8) & 0x07);
 | 
			
		||||
@@ -314,9 +318,13 @@ static int tune_sat(struct dddvb_fe *fe)
 | 
			
		||||
			    fe->scif_slot, fe->scif_freq, ds);
 | 
			
		||||
		pthread_mutex_unlock(&fe->dd->uni_lock);
 | 
			
		||||
	} else {
 | 
			
		||||
		uint32_t input = lnb;
 | 
			
		||||
 | 
			
		||||
		if (input != DDDVB_UNDEF)
 | 
			
		||||
			input = 3 & (input >> 6);
 | 
			
		||||
		//set_property(fe->fd, DTV_INPUT, 3 & (lnb >> 6));
 | 
			
		||||
		diseqc(fe->fd, lnb, fe->param.param[PARAM_POL], hi);
 | 
			
		||||
		set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, ~(0U));
 | 
			
		||||
		set_fe_input(fe, freq, fe->param.param[PARAM_SR], ds, input);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -324,7 +332,7 @@ static int tune_c(struct dddvb_fe *fe)
 | 
			
		||||
{
 | 
			
		||||
	struct dtv_property p[] = {
 | 
			
		||||
		{ .cmd = DTV_CLEAR },
 | 
			
		||||
		{ .cmd = DTV_FREQUENCY, .u.data = fe->param.param[PARAM_FREQ] },
 | 
			
		||||
		{ .cmd = DTV_FREQUENCY, .u.data = fe->param.param[PARAM_FREQ] * 1000},
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = (fe->param.param[PARAM_BW_HZ] != DDDVB_UNDEF) ?
 | 
			
		||||
		  fe->param.param[PARAM_BW_HZ] : 8000000 },
 | 
			
		||||
		{ .cmd = DTV_SYMBOL_RATE, .u.data = fe->param.param[PARAM_SR] },
 | 
			
		||||
@@ -351,19 +359,28 @@ static int tune_c(struct dddvb_fe *fe)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int tune_cable(struct dddvb_fe *fe)
 | 
			
		||||
static int tune_j83b(struct dddvb_fe *fe)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t freq;
 | 
			
		||||
	struct dvb_frontend_parameters p = {
 | 
			
		||||
		.frequency = fe->param.param[PARAM_FREQ] * 1000,
 | 
			
		||||
		.u.qam.symbol_rate = fe->param.param[PARAM_SR],
 | 
			
		||||
		.u.qam.fec_inner = (fe->param.param[PARAM_FEC] != DDDVB_UNDEF) ?
 | 
			
		||||
		(fe->param.param[PARAM_FEC]) : FEC_AUTO,
 | 
			
		||||
		.u.qam.modulation = fe->param.param[PARAM_MTYPE],
 | 
			
		||||
	struct dtv_property p[] = {
 | 
			
		||||
		{ .cmd = DTV_CLEAR },
 | 
			
		||||
		{ .cmd = DTV_FREQUENCY, .u.data = fe->param.param[PARAM_FREQ] * 1000},
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = (fe->param.param[PARAM_BW_HZ] != DDDVB_UNDEF) ?
 | 
			
		||||
		  fe->param.param[PARAM_BW_HZ] : 6000000 },
 | 
			
		||||
		{ .cmd = DTV_SYMBOL_RATE, .u.data = (fe->param.param[PARAM_SR] != DDDVB_UNDEF) ?
 | 
			
		||||
		  fe->param.param[PARAM_SR] : 5056941},
 | 
			
		||||
		{ .cmd = DTV_TUNE },
 | 
			
		||||
	};		
 | 
			
		||||
	set_property(fe->fd, DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_A);
 | 
			
		||||
	if (ioctl(fe->fd, FE_SET_FRONTEND, &p) == -1) {
 | 
			
		||||
		perror("FE_SET_FRONTEND error");
 | 
			
		||||
	struct dtv_properties c;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	printf("tune_j83b()\n");
 | 
			
		||||
	set_property(fe->fd, DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_B);
 | 
			
		||||
 | 
			
		||||
	c.num = ARRAY_SIZE(p);
 | 
			
		||||
	c.props = p;
 | 
			
		||||
	ret = ioctl(fe->fd, FE_SET_PROPERTY, &c);
 | 
			
		||||
	if (ret < 0) {
 | 
			
		||||
		fprintf(stderr, "FE_SET_PROPERTY returned %d\n", ret);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -374,7 +391,8 @@ static int tune_terr(struct dddvb_fe *fe)
 | 
			
		||||
	struct dtv_property p[] = {
 | 
			
		||||
		{ .cmd = DTV_CLEAR },
 | 
			
		||||
		{ .cmd = DTV_FREQUENCY, .u.data = fe->param.param[PARAM_FREQ] * 1000 },
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = fe->param.param[PARAM_BW_HZ] },
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = (fe->param.param[PARAM_BW_HZ] != DDDVB_UNDEF) ?
 | 
			
		||||
		  fe->param.param[PARAM_BW_HZ] : 8000000 },
 | 
			
		||||
		{ .cmd = DTV_TUNE },
 | 
			
		||||
	};		
 | 
			
		||||
	struct dtv_properties c;
 | 
			
		||||
@@ -422,7 +440,8 @@ static int tune_c2(struct dddvb_fe *fe)
 | 
			
		||||
	struct dtv_property p[] = {
 | 
			
		||||
		{ .cmd = DTV_CLEAR },
 | 
			
		||||
		{ .cmd = DTV_FREQUENCY, .u.data = fe->param.param[PARAM_FREQ] * 1000 },
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = fe->param.param[PARAM_BW_HZ] },
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = (fe->param.param[PARAM_BW_HZ] != DDDVB_UNDEF) ?
 | 
			
		||||
		  fe->param.param[PARAM_BW_HZ] : 8000000 },
 | 
			
		||||
		{ .cmd = DTV_STREAM_ID, .u.data = fe->param.param[PARAM_PLP] },
 | 
			
		||||
		{ .cmd = DTV_TUNE },
 | 
			
		||||
	};		
 | 
			
		||||
@@ -446,7 +465,8 @@ static int tune_terr2(struct dddvb_fe *fe)
 | 
			
		||||
	struct dtv_property p[] = {
 | 
			
		||||
		{ .cmd = DTV_CLEAR },
 | 
			
		||||
		{ .cmd = DTV_FREQUENCY, .u.data = fe->param.param[PARAM_FREQ] * 1000 },
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = fe->param.param[PARAM_BW_HZ] },
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = (fe->param.param[PARAM_BW_HZ] != DDDVB_UNDEF) ?
 | 
			
		||||
		  fe->param.param[PARAM_BW_HZ] : 8000000 },
 | 
			
		||||
		{ .cmd = DTV_STREAM_ID, .u.data = fe->param.param[PARAM_PLP] },
 | 
			
		||||
		{ .cmd = DTV_TUNE },
 | 
			
		||||
	};		
 | 
			
		||||
@@ -470,7 +490,8 @@ static int tune_isdbt(struct dddvb_fe *fe)
 | 
			
		||||
	struct dtv_property p[] = {
 | 
			
		||||
		{ .cmd = DTV_CLEAR },
 | 
			
		||||
		{ .cmd = DTV_FREQUENCY, .u.data = fe->param.param[PARAM_FREQ] * 1000 },
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = fe->param.param[PARAM_BW_HZ] },
 | 
			
		||||
		{ .cmd = DTV_BANDWIDTH_HZ, .u.data = (fe->param.param[PARAM_BW_HZ] != DDDVB_UNDEF) ?
 | 
			
		||||
		  fe->param.param[PARAM_BW_HZ] : 6000000 },
 | 
			
		||||
		{ .cmd = DTV_TUNE },
 | 
			
		||||
	};		
 | 
			
		||||
	struct dtv_properties c;
 | 
			
		||||
@@ -501,6 +522,9 @@ static int tune(struct dddvb_fe *fe)
 | 
			
		||||
	case SYS_DVBC_ANNEX_A:
 | 
			
		||||
		ret = tune_c(fe);
 | 
			
		||||
		break;
 | 
			
		||||
	case SYS_DVBC_ANNEX_B:
 | 
			
		||||
		ret = tune_j83b(fe);
 | 
			
		||||
		break;
 | 
			
		||||
	case SYS_DVBT:
 | 
			
		||||
		ret = tune_terr(fe);
 | 
			
		||||
		break;
 | 
			
		||||
@@ -519,7 +543,7 @@ static int tune(struct dddvb_fe *fe)
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int open_dmx(struct dddvb_fe *fe)
 | 
			
		||||
int open_dmx(struct dddvb_fe *fe)
 | 
			
		||||
{
 | 
			
		||||
	char fname[80];
 | 
			
		||||
	struct dmx_pes_filter_params pesFilterParams; 
 | 
			
		||||
@@ -611,10 +635,9 @@ void dddvb_fe_handle(struct dddvb_fe *fe)
 | 
			
		||||
	uint32_t newtune, count = 0, max, nolock = 0;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	printf("fe_handle\n");
 | 
			
		||||
	
 | 
			
		||||
	if (fe->dd->get_ts)
 | 
			
		||||
		open_dmx(fe);
 | 
			
		||||
	printf("fe_handle 2\n");
 | 
			
		||||
	while (fe->state == 1) {
 | 
			
		||||
		pthread_mutex_lock(&fe->mutex);
 | 
			
		||||
		newtune = fe->n_tune;
 | 
			
		||||
 
 | 
			
		||||
@@ -331,6 +331,9 @@ static void calc_lq(struct dddvb_fe *fe)
 | 
			
		||||
	int64_t str, snr;
 | 
			
		||||
	uint32_t mod, fec, ber_num, ber_den, trans, pilot = 0, quality = 0;
 | 
			
		||||
	
 | 
			
		||||
	get_property(fe->fd, DTV_TRANSMISSION_MODE, &fe->pls_code);
 | 
			
		||||
	dbgprintf(DEBUG_DVB, "fe%d: pls=0x%02x\n", fe->nr, fe->pls_code);
 | 
			
		||||
	
 | 
			
		||||
	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);
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,9 @@ LIBDDDVB_EXPORTED int dddvb_ca_write(struct dddvb *dd, uint32_t nr, uint8_t *buf
 | 
			
		||||
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_get_ts(struct dddvb *dd, uint32_t val) {
 | 
			
		||||
	dd->get_ts = val;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline void dddvb_set_frequency(struct dddvb_params *p, uint32_t freq) {
 | 
			
		||||
	p->param[PARAM_FREQ] = freq;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user