mirror of
				https://github.com/DigitalDevices/dddvb.git
				synced 2025-03-01 10:35:23 +00:00 
			
		
		
		
	Merge branch 'internal'
This commit is contained in:
		
							
								
								
									
										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* | ||||
|   | ||||
| @@ -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,85 +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 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/ | ||||
|   | ||||
| @@ -329,7 +329,7 @@ int ddb_ci_attach(struct ddb_port *port, u32 bitrate) | ||||
| 	case DDB_CI_EXTERNAL_XO2_B: | ||||
| 		ci_xo2_attach(port); | ||||
| 		break; | ||||
| 		 | ||||
|  | ||||
| 	case DDB_CI_INTERNAL: | ||||
| 		ci_attach(port); | ||||
| 		break; | ||||
|   | ||||
| @@ -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 | ||||
| 		ddbwritel(dev, 0x09, TS_CONTROL(input)); | ||||
| 	else { | ||||
| 		if (raw_stream) | ||||
| 			ddbwritel(dev, 0x01 | ((raw_stream & 3) << 8), TS_CONTROL(input)); | ||||
| 		else | ||||
| 			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,20 +1033,20 @@ 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 | | ||||
| 		        FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | | ||||
| 		        FE_CAN_QAM_AUTO |  | ||||
| 			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||||
| 			FE_CAN_FEC_4_5 | | ||||
| 			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_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | | ||||
| 		FE_CAN_QAM_AUTO | | ||||
| 		FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||||
| 		FE_CAN_FEC_4_5 | | ||||
| 		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 | ||||
| 	}, | ||||
| 	.release = dummy_release, | ||||
| 	.read_status = dummy_read_status, | ||||
| @@ -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); | ||||
| 		dvb_dmx_swfilter_packets(&dvb->demux, | ||||
| 					 dma2->vbuf[dma->cbuf], | ||||
| 					 dma2->size / 188); | ||||
| 		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(); | ||||
| 	} | ||||
|   | ||||
| @@ -801,7 +801,7 @@ static const struct ddb_device_id ddb_device_ids[] = { | ||||
| 	DDB_DEVID(0x0013, 0x0044, ddb_ci_s2_pro_a), | ||||
| 	DDB_DEVID(0x0020, 0x0012, ddb_gtl_mini), | ||||
|  | ||||
|         /* Modulators */ | ||||
| 	/* Modulators */ | ||||
| 	DDB_DEVID(0x0201, 0x0001, ddb_mod), | ||||
| 	DDB_DEVID(0x0201, 0x0002, ddb_mod), | ||||
| 	DDB_DEVID(0x0201, 0x0004, ddb_mod_4),  /* dummy entry ! */ | ||||
| @@ -821,19 +821,22 @@ 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, | ||||
| 				    u16 subvendor, u16 subdevice) | ||||
| { | ||||
| 	int i; | ||||
| 	 | ||||
|  | ||||
| 	for (i = 0; i < ARRAY_SIZE(ddb_device_ids); i++) { | ||||
| 		const struct ddb_device_id *id = &ddb_device_ids[i]; | ||||
| 		 | ||||
|  | ||||
| 		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,33 +35,30 @@ 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) { | ||||
| 		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); | ||||
| #if 1 | ||||
| 		{ | ||||
| 			u32 istat = ddbreadl(dev, INTERRUPT_STATUS); | ||||
| 		dev_err(dev->dev, "DDBridge IRS %08x\n", istat); | ||||
|  | ||||
| 			dev_err(dev->dev, "DDBridge IRS %08x\n", istat); | ||||
| 			if (i2c->link) { | ||||
| 				u32 listat = | ||||
| 					ddbreadl(dev, | ||||
| 						 DDB_LINK_TAG(i2c->link) | | ||||
| 						 INTERRUPT_STATUS); | ||||
| 				dev_err(dev->dev, | ||||
| 					"DDBridge link %u IRS %08x\n", | ||||
| 					i2c->link, listat); | ||||
| 			} | ||||
| 			if (istat & 1) { | ||||
| 				ddbwritel(dev, istat & 1, INTERRUPT_ACK); | ||||
| 			} else { | ||||
| 				u32 mon = ddbreadl(dev, | ||||
| 						   i2c->regs + I2C_MONITOR); | ||||
|  | ||||
| 				dev_err(dev->dev, "I2C cmd=%08x mon=%08x\n", | ||||
| 					val, mon); | ||||
| 			} | ||||
| 		if (i2c->link) { | ||||
| 			u32 listat = | ||||
| 				ddbreadl(dev, | ||||
| 					 DDB_LINK_TAG(i2c->link) | | ||||
| 					 INTERRUPT_STATUS); | ||||
| 			dev_err(dev->dev, | ||||
| 				"DDBridge link %u IRS %08x\n", | ||||
| 				i2c->link, listat); | ||||
| 		} | ||||
| 		if (istat & 1) { | ||||
| 			ddbwritel(dev, istat & 1, INTERRUPT_ACK); | ||||
| 		} else { | ||||
| 			u32 mon = ddbreadl(dev, | ||||
| 					   i2c->regs + I2C_MONITOR); | ||||
|  | ||||
| 			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,21 +472,21 @@ 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 |  | ||||
| 			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||||
| 			FE_CAN_FEC_4_5 | | ||||
| 			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_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | | ||||
| 		FE_CAN_QAM_AUTO | | ||||
| 		FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||||
| 		FE_CAN_FEC_4_5 | | ||||
| 		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 | ||||
| 	}, | ||||
| 	.release                        = release, | ||||
| 	.get_frontend_algo              = get_algo, | ||||
|   | ||||
| @@ -360,17 +360,17 @@ static int __devinit ddb_probe(struct pci_dev *pdev, | ||||
| 	if (dev->link[0].info->type == DDB_MOD | ||||
| 	    && dev->link[0].info->version == 2) { | ||||
| 		u32 lic = ddbreadl(dev, 0x1c) & 7; | ||||
| 		 | ||||
|  | ||||
| 		switch (lic) { | ||||
| 		case 0:  | ||||
| 		case 0: | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0000); | ||||
| 			break; | ||||
| 		case 1:  | ||||
| 		case 1: | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0003); | ||||
| 			break; | ||||
| 		case 3:  | ||||
| 		case 3: | ||||
| 			dev->link[0].info = | ||||
| 				get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0002); | ||||
| 			break; | ||||
| @@ -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; | ||||
| @@ -479,7 +500,7 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type) | ||||
| 	int demod, tuner; | ||||
| 	struct mci_cfg cfg; | ||||
| 	int fm = fmode; | ||||
| 	 | ||||
|  | ||||
| 	demod = input->nr; | ||||
| 	tuner = demod & 3; | ||||
| 	switch (type) { | ||||
|   | ||||
| @@ -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); | ||||
| @@ -71,7 +72,7 @@ static int ddb_mci_cmd_raw_unlocked(struct mci *state, | ||||
| 	struct ddb_link *link = state->base->link; | ||||
| 	u32 i, val; | ||||
| 	unsigned long stat; | ||||
| 	 | ||||
|  | ||||
| 	val = ddblreadl(link, MCI_CONTROL); | ||||
| 	if (val & (MCI_CONTROL_RESET | MCI_CONTROL_START_COMMAND)) | ||||
| 		return -EIO; | ||||
| @@ -80,19 +81,21 @@ static int ddb_mci_cmd_raw_unlocked(struct mci *state, | ||||
| 			ddblwritel(link, cmd[i], MCI_COMMAND + i * 4); | ||||
| 	val |= (MCI_CONTROL_START_COMMAND | MCI_CONTROL_ENABLE_DONE_INTERRUPT); | ||||
| 	ddblwritel(link, val, MCI_CONTROL); | ||||
| 	 | ||||
|  | ||||
| 	stat = wait_for_completion_timeout(&state->base->completion, HZ); | ||||
| 	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); | ||||
| 			if (istat & 1)  | ||||
| 			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) | ||||
| 				ddbwritel(link->dev, 0xffffff, INTERRUPT_ACK); | ||||
| @@ -110,7 +113,7 @@ int ddb_mci_cmd_unlocked(struct mci *state, | ||||
| { | ||||
| 	u32 *cmd = (u32 *) command; | ||||
| 	u32 *res = (u32 *) result; | ||||
| 	 | ||||
|  | ||||
| 	return ddb_mci_cmd_raw_unlocked(state, cmd, sizeof(*command)/sizeof(u32), | ||||
| 					res, sizeof(*result)/sizeof(u32)); | ||||
| } | ||||
| @@ -141,7 +144,7 @@ int ddb_mci_cmd_raw(struct mci *state, | ||||
| 		    struct mci_result *result, u32 result_len) | ||||
| { | ||||
| 	int stat; | ||||
| 	 | ||||
|  | ||||
| 	mutex_lock(&state->base->mci_lock); | ||||
| 	stat = ddb_mci_cmd_raw_unlocked(state, | ||||
| 					(u32 *)command, command_len, | ||||
| @@ -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; | ||||
| } | ||||
|  | ||||
| @@ -249,7 +251,7 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p) | ||||
| 		ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_10, | ||||
| 		ROLLOFF_5, ROLLOFF_15, ROLLOFF_35, ROLLOFF_35 | ||||
| 	}; | ||||
| 	 | ||||
|  | ||||
| 	p->frequency = | ||||
| 		mci->signal_info.dvbs2_signal_info.frequency; | ||||
| 	switch (p->delivery_system) { | ||||
| @@ -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->rolloff = | ||||
| 				ro_lut[mci->signal_info. | ||||
| 				       dvbs2_signal_info.roll_off & 7]; | ||||
| 			p->pilot = (pls_code & 1) ? PILOT_ON : PILOT_OFF; | ||||
| 			p->fec_inner = modcod2fec[modcod]; | ||||
| 			p->modulation = modcod2mod[modcod]; | ||||
| 			p->transmission_mode = pls_code; | ||||
| 			p->rolloff = | ||||
| 				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]; | ||||
| 			} | ||||
| 		} 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; | ||||
| @@ -319,7 +323,7 @@ struct mci_command { | ||||
| 			uint8_t   gain;         /* Gain in 0.25 dB Steps */ | ||||
| 			/* Frequency, symbolrate and gain can be schanged while running */ | ||||
| 		} sx8_start_iq; | ||||
| 		 | ||||
| 	 | ||||
| 		struct { | ||||
| 			uint8_t   flags; | ||||
|                         /*   Bit 0:1 Preamp Mode;  0 = Preamp AGC, 1 == Minimum (~ -17dB) , | ||||
| @@ -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]; | ||||
| @@ -644,14 +663,13 @@ struct mci_result { | ||||
| 			u8  min_input_stream_id; | ||||
| 			u8  max_input_stream_id; | ||||
| 		} BBHeader; | ||||
| 		 | ||||
|  | ||||
| 		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  | ||||
| 			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; | ||||
| 		 | ||||
|  | ||||
| 		struct { | ||||
| 			u8   Change;  // 5 bits, increments with every change | ||||
| 			struct { | ||||
| @@ -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,34 +376,36 @@ static int start_iq(struct dvb_frontend *fe, u32 flags, | ||||
| 	u32 input = state->mci.tuner; | ||||
| 	int i, stat = 0; | ||||
|  | ||||
| 	mutex_lock(&mci_base->tuner_lock); | ||||
| 	if (sx8_base->iq_mode) { | ||||
| 		stat = -EBUSY; | ||||
| 		goto unlock; | ||||
| 	if (!state->iq_started) { | ||||
| 		mutex_lock(&mci_base->tuner_lock); | ||||
| 		if (sx8_base->iq_mode) { | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 		for (i = 0; i < SX8_DEMOD_NUM; i++) | ||||
| 			if (sx8_base->demod_in_use[i]) | ||||
| 				used_demods++; | ||||
| 		if (used_demods > 0) { | ||||
| 			stat = -EBUSY; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 		state->mci.demod = 0; | ||||
| 		if (!sx8_base->tuner_use_count[input]) | ||||
| 			mci_set_tuner(fe, input, 1); | ||||
| 		sx8_base->tuner_use_count[input]++; | ||||
| 		sx8_base->iq_mode = (ts_config > 1); | ||||
| 	unlock: | ||||
| 		mutex_unlock(&mci_base->tuner_lock); | ||||
| 		if (stat) | ||||
| 			return stat; | ||||
| 	} | ||||
| 	for (i = 0; i < SX8_DEMOD_NUM; i++) | ||||
| 		if (sx8_base->demod_in_use[i]) | ||||
| 			used_demods++; | ||||
|         if (used_demods > 0) { | ||||
| 		stat = -EBUSY; | ||||
| 		goto unlock; | ||||
| 	} | ||||
|         state->mci.demod = 0; | ||||
|         if (!sx8_base->tuner_use_count[input]) | ||||
| 		mci_set_tuner(fe, input, 1); | ||||
| 	sx8_base->tuner_use_count[input]++; | ||||
| 	sx8_base->iq_mode = (ts_config > 1); | ||||
| 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 | ||||
|  | ||||
|   | ||||
| @@ -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,19 +488,40 @@ 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; | ||||
| 	if (buffer->error) { | ||||
| 		spin_unlock(&dmxdevfilter->dev->lock); | ||||
| 		wake_up(&buffer->queue); | ||||
| 		return 0; | ||||
| #ifdef CONFIG_DVB_MMAP | ||||
| 		ctx = &dmxdevfilter->dev->dvr_vb2_ctx; | ||||
| #endif | ||||
| 	} | ||||
| 	ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); | ||||
| 	if (ret == buffer1_len) | ||||
| 		ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); | ||||
|  | ||||
| #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); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); | ||||
| 		if (ret == buffer1_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,8 +192,10 @@ 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 { | ||||
| @@ -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", | ||||
| 			       n, sec->tsfeedp); | ||||
| 			dprintk("dvb_demux.c pad data:"); | ||||
| 			for (i = 0; i < n; i++) | ||||
| 				pr_cont(" %02x", sec->secbuf[i]); | ||||
| 			pr_cont("\n"); | ||||
| 			set_buf_flags(feed, | ||||
| 				      DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); | ||||
| 			dprintk_sect_loss("section ts padding loss: %d/%d\n", | ||||
| 					  n, sec->tsfeedp); | ||||
| 			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", | ||||
| 		       sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, | ||||
| 		       DMX_MAX_SECFEED_SIZE); | ||||
| #endif | ||||
| 		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); | ||||
| 		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,9 +449,10 @@ 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); | ||||
| 				dprintk("TS speed %llu Kbits/sec \n", | ||||
| 					div64_u64(speed_bytes, | ||||
| 						  speed_timedelta)); | ||||
| 				if (speed_timedelta) | ||||
| 					dprintk("TS speed %llu Kbits/sec \n", | ||||
| 						div64_u64(speed_bytes, | ||||
| 							  speed_timedelta)); | ||||
| 			} | ||||
|  | ||||
| 			demux->speed_last_time = cur_time; | ||||
| @@ -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; | ||||
|  | ||||
| @@ -1010,12 +992,12 @@ 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) | ||||
| 				const u8 *buffer2, size_t buffer2_len, | ||||
| 				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 | ||||
|   | ||||
| @@ -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,8 +346,10 @@ 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) { | ||||
| @@ -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" | ||||
| @@ -345,10 +345,10 @@ 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, | ||||
| 		.name		   = "STV6110(A) Silicon Tuner", | ||||
| 		.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 */ | ||||
| @@ -86,11 +73,11 @@ typedef enum { | ||||
| #define VIDEO_CMD_CONTINUE    (3) | ||||
|  | ||||
| /* Flags for VIDEO_CMD_FREEZE */ | ||||
| #define VIDEO_CMD_FREEZE_TO_BLACK     	(1 << 0) | ||||
| #define VIDEO_CMD_FREEZE_TO_BLACK	(1 << 0) | ||||
|  | ||||
| /* Flags for VIDEO_CMD_STOP */ | ||||
| #define VIDEO_CMD_STOP_TO_BLACK      	(1 << 0) | ||||
| #define VIDEO_CMD_STOP_IMMEDIATELY     	(1 << 1) | ||||
| #define VIDEO_CMD_STOP_TO_BLACK		(1 << 0) | ||||
| #define VIDEO_CMD_STOP_IMMEDIATELY	(1 << 1) | ||||
|  | ||||
| /* Play input formats: */ | ||||
| /* The decoder has no special format requirements */ | ||||
| @@ -127,8 +114,8 @@ struct video_command { | ||||
| /* FIELD_UNKNOWN can be used if the hardware does not know whether | ||||
|    the Vsync is for an odd, even or progressive (i.e. non-interlaced) | ||||
|    field. */ | ||||
| #define VIDEO_VSYNC_FIELD_UNKNOWN  	(0) | ||||
| #define VIDEO_VSYNC_FIELD_ODD 		(1) | ||||
| #define VIDEO_VSYNC_FIELD_UNKNOWN	(0) | ||||
| #define VIDEO_VSYNC_FIELD_ODD		(1) | ||||
| #define VIDEO_VSYNC_FIELD_EVEN		(2) | ||||
| #define VIDEO_VSYNC_FIELD_PROGRESSIVE	(3) | ||||
|  | ||||
| @@ -136,8 +123,8 @@ struct video_event { | ||||
| 	__s32 type; | ||||
| #define VIDEO_EVENT_SIZE_CHANGED	1 | ||||
| #define VIDEO_EVENT_FRAME_RATE_CHANGED	2 | ||||
| #define VIDEO_EVENT_DECODER_STOPPED 	3 | ||||
| #define VIDEO_EVENT_VSYNC 		4 | ||||
| #define VIDEO_EVENT_DECODER_STOPPED	3 | ||||
| #define VIDEO_EVENT_VSYNC		4 | ||||
| 	/* unused, make sure to use atomic time for y2038 if it ever gets used */ | ||||
| 	long timestamp; | ||||
| 	union { | ||||
| @@ -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 | ||||
| @@ -271,9 +212,9 @@ typedef __u16 video_attributes_t; | ||||
| #define VIDEO_GET_PTS              _IOR('o', 57, __u64) | ||||
|  | ||||
| /* Read the number of displayed frames since the decoder was started */ | ||||
| #define VIDEO_GET_FRAME_COUNT  	   _IOR('o', 58, __u64) | ||||
| #define VIDEO_GET_FRAME_COUNT	   _IOR('o', 58, __u64) | ||||
|  | ||||
| #define VIDEO_COMMAND     	   _IOWR('o', 59, struct video_command) | ||||
| #define VIDEO_TRY_COMMAND 	   _IOWR('o', 60, struct video_command) | ||||
| #define VIDEO_COMMAND		   _IOWR('o', 59, struct video_command) | ||||
| #define VIDEO_TRY_COMMAND	   _IOWR('o', 60, struct video_command) | ||||
|  | ||||
| #endif /* _UAPI_DVBVIDEO_H_ */ | ||||
|   | ||||
| @@ -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; | ||||
| @@ -104,10 +106,10 @@ struct dvb_tuner_info { | ||||
|  * struct analog_parameters - Parameters to tune into an analog/radio channel | ||||
|  * | ||||
|  * @frequency:	Frequency used by analog TV tuner (either in 62.5 kHz step, | ||||
|  * 		for TV, or 62.5 Hz for radio) | ||||
|  *		for TV, or 62.5 Hz for radio) | ||||
|  * @mode:	Tuner mode, as defined on enum v4l2_tuner_type | ||||
|  * @audmode:	Audio mode as defined for the rxsubchans field at videodev2.h, | ||||
|  * 		e. g. V4L2_TUNER_MODE_* | ||||
|  *		e. g. V4L2_TUNER_MODE_* | ||||
|  * @std:	TV standard bitmap as defined at videodev2.h, e. g. V4L2_STD_* | ||||
|  * | ||||
|  * Hybrid tuners should be supported by both V4L2 and DVB APIs. This | ||||
| @@ -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. | ||||
|  *			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;, | ||||
|  *			rate. Newer drivers should provide such info via | ||||
|  *			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]; | ||||
| }; | ||||
| 
 | ||||
| @@ -506,7 +529,7 @@ struct dvb_fe_events { | ||||
|  * @fec_inner:		Forward error correction inner Code Rate | ||||
|  * @transmission_mode:	Transmission Mode | ||||
|  * @bandwidth_hz:	Bandwidth, in Hz. A zero value means that userspace | ||||
|  * 			wants to autodetect. | ||||
|  *			wants to autodetect. | ||||
|  * @guard_interval:	Guard Interval | ||||
|  * @hierarchy:		Hierarchy | ||||
|  * @symbol_rate:	Symbol Rate | ||||
| @@ -529,8 +552,8 @@ struct dvb_fe_events { | ||||
|  * @layer.interleaving:	 per layer interleaving. | ||||
|  * @stream_id:		If different than zero, enable substream filtering, if | ||||
|  *			hardware supports (DVB-S2 and DVB-T2). | ||||
|  * @scrambling_sequence_index: Carries the index of the DVB-S2 physical layer | ||||
|  *                             scrambling sequence. | ||||
|  * @scrambling_sequence_index:	Carries the index of the DVB-S2 physical layer | ||||
|  *				scrambling sequence. | ||||
|  * @atscmh_fic_ver:	Version number of the FIC (Fast Information Channel) | ||||
|  *			signaling data (only ATSC-M/H) | ||||
|  * @atscmh_parade_id:	Parade identification number (only ATSC-M/H) | ||||
| @@ -554,7 +577,7 @@ struct dvb_fe_events { | ||||
|  * @lna:		Power ON/OFF/AUTO the Linear Now-noise Amplifier (LNA) | ||||
|  * @strength:		DVBv5 API statistics: Signal Strength | ||||
|  * @cnr:		DVBv5 API statistics: Signal to Noise ratio of the | ||||
|  * 			(main) carrier | ||||
|  *			(main) carrier | ||||
|  * @pre_bit_error:	DVBv5 API statistics: pre-Viterbi bit error count | ||||
|  * @pre_bit_count:	DVBv5 API statistics: pre-Viterbi bit count | ||||
|  * @post_bit_error:	DVBv5 API statistics: post-Viterbi bit error count | ||||
| @@ -575,15 +598,15 @@ struct dtv_frontend_properties { | ||||
| 
 | ||||
| 	enum fe_sec_voltage	voltage; | ||||
| 	enum fe_sec_tone_mode	sectone; | ||||
| 	enum fe_spectral_inversion	inversion; | ||||
| 	enum fe_code_rate		fec_inner; | ||||
| 	enum fe_spectral_inversion inversion; | ||||
| 	enum fe_code_rate	fec_inner; | ||||
| 	enum fe_transmit_mode	transmission_mode; | ||||
| 	u32			bandwidth_hz;	/* 0 = AUTO */ | ||||
| 	enum fe_guard_interval	guard_interval; | ||||
| 	enum fe_hierarchy		hierarchy; | ||||
| 	enum fe_hierarchy	hierarchy; | ||||
| 	u32			symbol_rate; | ||||
| 	enum fe_code_rate		code_rate_HP; | ||||
| 	enum fe_code_rate		code_rate_LP; | ||||
| 	enum fe_code_rate	code_rate_HP; | ||||
| 	enum fe_code_rate	code_rate_LP; | ||||
| 
 | ||||
| 	enum fe_pilot		pilot; | ||||
| 	enum fe_rolloff		rolloff; | ||||
| @@ -610,7 +633,7 @@ struct dtv_frontend_properties { | ||||
| 	u32			stream_id; | ||||
| 
 | ||||
| 	/* Physical Layer Scrambling specifics */ | ||||
| 	u32                     scrambling_sequence_index; | ||||
| 	u32			scrambling_sequence_index; | ||||
| 
 | ||||
| 	/* ATSC-MH specifics */ | ||||
| 	u8			atscmh_fic_ver; | ||||
| @@ -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; | ||||
| 
 | ||||
| @@ -176,7 +200,7 @@ struct dvb_device { | ||||
|  * @module:	initialized with THIS_MODULE at the caller | ||||
|  * @device:	pointer to struct device that corresponds to the device driver | ||||
|  * @adapter_nums: Array with a list of the numbers for @dvb_register_adapter; | ||||
|  * 		to select among them. Typically, initialized with: | ||||
|  *		to select among them. Typically, initialized with: | ||||
|  *		DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums) | ||||
|  */ | ||||
| int dvb_register_adapter(struct dvb_adapter *adap, const char *name, | ||||
| @@ -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); | ||||
| 
 | ||||
| /**
 | ||||
| @@ -244,9 +266,9 @@ void dvb_unregister_device(struct dvb_device *dvbdev); | ||||
| #ifdef CONFIG_MEDIA_CONTROLLER_DVB | ||||
| /**
 | ||||
|  * dvb_create_media_graph - Creates media graph for the Digital TV part of the | ||||
|  * 				device. | ||||
|  *				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, | ||||
| 			      unsigned int cmd, unsigned long arg); | ||||
| /**
 | ||||
|  * 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); | ||||
| 
 | ||||
| /* we don't mess with video_usercopy() any more,
 | ||||
| we simply define out own dvb_usercopy(), which will hopefully become | ||||
| generic_usercopy()  someday... */ | ||||
| /**
 | ||||
|  * 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); | ||||
| 
 | ||||
| /**
 | ||||
|  * 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_ */ | ||||
| @@ -13,10 +13,10 @@ install: all | ||||
| 	$(CC) $(CFLAGS) -fPIC -c $<  | ||||
|  | ||||
| dddvb_test: dddvb_test.o | ||||
| 	$(CC) -o dddvb_test  $< -L ./src -l dddvb -l pthread -l dvben50221 -l dvbapi -l ucsi | ||||
| 	$(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 | ||||
|   | ||||
							
								
								
									
										320
									
								
								lib/ddzap.c
									
									
									
									
									
								
							
							
						
						
									
										320
									
								
								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; | ||||
| 		        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 { | ||||
| @@ -245,7 +521,7 @@ int main(int argc, char **argv) | ||||
| 			cnr = dddvb_get_cnr(fe); | ||||
| 			 | ||||
| 			fprintf(stderr,"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); | ||||
| 		} | ||||
| 		fprintf(stderr,"got lock on %s\n", fe->name); | ||||
| @@ -253,11 +529,31 @@ int main(int argc, char **argv) | ||||
| 			 "/dev/dvb/adapter%d/dvr%d",fe->anum, fe->fnum); | ||||
| 		fprintf(stderr,"opening %s\n", filename); | ||||
| 		if ((fd = open(filename ,O_RDONLY)) < 0){ | ||||
| 		        fprintf(stderr,"Error opening input file:%s\n",filename); | ||||
| 		    fprintf(stderr,"Error opening input file:%s\n",filename); | ||||
| 		} | ||||
| 		while(1){ | ||||
| 		    read(fd,buf,BUFFSIZE); | ||||
| 		    write(fileno(stdout),buf,BUFFSIZE); | ||||
| 		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], | ||||
| 	}; | ||||
| 	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_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 }, | ||||
| 	};		 | ||||
| 	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"); | ||||
| 	 | ||||
| 	open_dmx(fe); | ||||
| 	printf("fe_handle 2\n"); | ||||
| 	if (fe->dd->get_ts) | ||||
| 		open_dmx(fe); | ||||
| 	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