From d627e6995f0fe633bb0cd6fe83aa229c91da63c8 Mon Sep 17 00:00:00 2001 From: drmocm Date: Tue, 21 Jun 2022 15:08:25 +0200 Subject: [PATCH 01/18] added modconfig and chnaged Makefile accordingly --- apps/Makefile | 25 ++++++++++++++++++++++++- apps/modconfig.c | 4 ++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/apps/Makefile b/apps/Makefile index 7962616..9e6a504 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,4 +1,20 @@ -all: cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq +TARGETS = cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq modtest + +all: $(TARGETS) + +CFLAGS = -g -Wall -Wno-unused -Wno-format +FFMPEG := $(shell command -v ffmpeg 2> /dev/null) + +modtest: modtest.c + $(CC) -o modtest modtest.c -I../include/ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE + +test.ts: +ifndef FFMPEG + $(error "ffmpeg is not available please install to create test stream") +endif + ffmpeg -f lavfi -i testsrc=duration=10:size=1280x720:rate=30 \ + -f lavfi -i sine=f=440:b=4 -shortest -metadata \ + service_provider="DD" -metadata service_name="Test" test.ts cit: cit.c $(CC) -o cit cit.c -lpthread @@ -24,3 +40,10 @@ modconfig: modconfig.c %.o: %.c $(CC) $(CFLAGS) -I../ddbridge -o $@ $< + +clean: + for f in $(TARGETS) *.o *~ test.ts; do \ + if [ -e "$$f" ]; then \ + rm "$$f" || exit 1; \ + fi \ + done diff --git a/apps/modconfig.c b/apps/modconfig.c index 4124a9d..9c8f2e3 100644 --- a/apps/modconfig.c +++ b/apps/modconfig.c @@ -279,7 +279,7 @@ int mci_cmd(int dev, struct mci_command *cmd) //dump((uint8_t *) &msg.cmd, sizeof(msg.cmd)); ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); if (ret < 0) { - dprintf(2, "mci_cmd error %d\n", errno); + dprintf(2, "mci_cmd error %d (%s)\n", errno, strerror(errno)); return ret; } status = msg.res.status; @@ -486,7 +486,7 @@ int main(int argc, char*argv[]) {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "d:c:", + c = getopt_long(argc, argv, "d:c:", long_options, &option_index); if (c == -1) break; From 817a464f4a1441c7c01c134f54237e2a929f55c2 Mon Sep 17 00:00:00 2001 From: drmocm Date: Tue, 21 Jun 2022 15:19:04 +0200 Subject: [PATCH 02/18] same Makefile changes for test.ts --- apps/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/Makefile b/apps/Makefile index 9e6a504..d1cf395 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,4 +1,4 @@ -TARGETS = cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq modtest +TARGETS = cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq modtest test.ts all: $(TARGETS) @@ -10,7 +10,7 @@ modtest: modtest.c test.ts: ifndef FFMPEG - $(error "ffmpeg is not available please install to create test stream") + $(error "ffmpeg is not available please install to create test.ts") endif ffmpeg -f lavfi -i testsrc=duration=10:size=1280x720:rate=30 \ -f lavfi -i sine=f=440:b=4 -shortest -metadata \ @@ -42,7 +42,7 @@ modconfig: modconfig.c clean: - for f in $(TARGETS) *.o *~ test.ts; do \ + for f in $(TARGETS) *.o *~ ; do \ if [ -e "$$f" ]; then \ rm "$$f" || exit 1; \ fi \ From 5c2757d581192875bb2f8643bccbb1a8a7d3b757 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 7 Jun 2022 21:20:03 +0200 Subject: [PATCH 03/18] Use eth_hw_addr_set in newer kernels. --- dvb-core/dvb_net.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dvb-core/dvb_net.c b/dvb-core/dvb_net.c index 386330b..05cc5c1 100644 --- a/dvb-core/dvb_net.c +++ b/dvb-core/dvb_net.c @@ -1282,8 +1282,11 @@ static int dvb_net_set_mac (struct net_device *dev, void *p) struct dvb_net_priv *priv = netdev_priv(dev); struct sockaddr *addr=p; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)) memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - +#else + eth_hw_addr_set(dev, addr->sa_data); +#endif if (netif_running(dev)) schedule_work(&priv->restart_net_feed_wq); @@ -1381,8 +1384,11 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) dvbnet->dvbdev->adapter->num, if_num); net->addr_len = 6; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)) memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6); - +#else + eth_hw_addr_set(net, dvbnet->dvbdev->adapter->proposed_mac); +#endif dvbnet->device[if_num] = net; priv = netdev_priv(net); From 45c9f076bd1f3b48d6ba192930f7253977423423 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 7 Jun 2022 21:21:03 +0200 Subject: [PATCH 04/18] Do not use BIT_ULL, because older kernels do not have it. --- ddbridge/ddbridge-regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ddbridge/ddbridge-regs.h b/ddbridge/ddbridge-regs.h index 61216a8..73f172e 100644 --- a/ddbridge/ddbridge-regs.h +++ b/ddbridge/ddbridge-regs.h @@ -260,8 +260,8 @@ #define LNB_CMD_DISEQC 6 #define LNB_CMD_SCIF 7 -#define LNB_BUSY BIT_ULL(4) -#define LNB_TONE BIT_ULL(15) +#define LNB_BUSY (1ULL << 4) +#define LNB_TONE (1ULL << 15) #define LNB_INTERRUPT_BASE 4 From 09e8a15d78b78a971ec0616f483456e62e6a2bdb Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 7 Jun 2022 21:22:21 +0200 Subject: [PATCH 05/18] Add clean for apps directory. --- Makefile | 1 + apps/Makefile | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 5e1756a..4e875e9 100644 --- a/Makefile +++ b/Makefile @@ -34,5 +34,6 @@ install: all clean: rm -rf */.*.o.d */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules* + $(MAKE) -C apps clean diff --git a/apps/Makefile b/apps/Makefile index d1cf395..4560894 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -34,6 +34,9 @@ setmod3: setmod3.c modconfig: modconfig.c $(CC) -o modconfig modconfig.c -I../include/ +clean: + rm cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq + %: %.c $(CC) $(CFLAGS) -I../ddbridge -I../include/ $< -o $@ From 727fba48be9e9cbb3869c7a206b4e37d0d8fa476 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:05:15 +0200 Subject: [PATCH 06/18] ringbuffer fix from upstream --- dvb-core/dvb_ringbuffer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dvb-core/dvb_ringbuffer.c b/dvb-core/dvb_ringbuffer.c index 42f39af..60830ef 100644 --- a/dvb-core/dvb_ringbuffer.c +++ b/dvb-core/dvb_ringbuffer.c @@ -391,7 +391,9 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size; } - consumed = (idx - rbuf->pread) % rbuf->size; + consumed = idx - rbuf->pread; + if (consumed < 0) + consumed += rbuf->size; while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) { From 92f2132d79e363b6552e071ae1f2b7323902150b Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:07:24 +0200 Subject: [PATCH 07/18] fix printf type --- apps/pls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/pls.c b/apps/pls.c index 510b1b2..b21ca59 100644 --- a/apps/pls.c +++ b/apps/pls.c @@ -147,7 +147,7 @@ int main(int argc, char **argv) if (gold != 0xffffffff) { if (gold < 0x3ffff) { root = gold2root(gold); - printf("gold = %llu (0x%05x) root = %llu (0x%05x)\n", + printf("gold = %u (0x%05x) root = %u (0x%05x)\n", gold, gold, root, root); } else printf("Invalid gold code specified.\n"); From 22ffb0ecac31defa910fee9748a82b2842278761 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:19:29 +0200 Subject: [PATCH 08/18] allow alternative modules dir --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4e875e9..c7d0734 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ kernelver ?= $(shell uname -r) -KDIR ?= /lib/modules/$(kernelver)/build +MDIR ?= /lib/modules/$(kernelver) +KDIR ?= $(MDIR)/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=y DDDVB=y @@ -29,7 +30,7 @@ dep: DIR=`pwd`; (cd $(TOPDIR); make KBUILD_EXTMOD=$$DIR dep) install: all - $(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) modules_install + $(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) INSTALL_MOD_PATH=$(MDIR) modules_install depmod $(kernelver) clean: From ce06e50881cece2566a00b219f29e7ae1e260290 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:25:05 +0200 Subject: [PATCH 09/18] remove modulator from octonet --- ddbridge/Makefile.kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ddbridge/Makefile.kernel b/ddbridge/Makefile.kernel index a2b64d9..ff82c71 100644 --- a/ddbridge/Makefile.kernel +++ b/ddbridge/Makefile.kernel @@ -3,7 +3,7 @@ # 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 +octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.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 obj-$(CONFIG_DVB_OCTONET) += octonet.o From b8abf46d0675053eec7e18e562b89860e9a130e8 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:27:44 +0200 Subject: [PATCH 10/18] add consts --- apps/modconfig.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/modconfig.c b/apps/modconfig.c index 9c8f2e3..05e8530 100644 --- a/apps/modconfig.c +++ b/apps/modconfig.c @@ -276,7 +276,7 @@ int mci_cmd(int dev, struct mci_command *cmd) memset(&msg, 0, sizeof(msg)); msg.link = 0; memcpy(&msg.cmd, cmd, sizeof(msg.cmd)); - //dump((uint8_t *) &msg.cmd, sizeof(msg.cmd)); + //dump((const uint8_t *) &msg.cmd, sizeof(msg.cmd)); ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); if (ret < 0) { dprintf(2, "mci_cmd error %d (%s)\n", errno, strerror(errno)); @@ -458,7 +458,7 @@ int mci_lic(int dev) printf("MATYPE1: %02x\n", res->bb_header.matype_1); printf("MATYPE2: %02x\n", res->bb_header.matype_2); } - dump(&res->license, sizeof(res->license)); + dump((const uint8_t *)&res->license, sizeof(res->license)); return ret; } From 42a0b65235770dc4cf91f9b355ed875c583f81d8 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:28:36 +0200 Subject: [PATCH 11/18] use correct pointer type --- ddbridge/ddbridge-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index d137048..abc3195 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -370,7 +370,7 @@ static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir) if (!dma->vbuf[i]) return -ENOMEM; } - if (((u64)dma->vbuf[i] & 0xfff)) + if (((uintptr_t) dma->vbuf[i] & 0xfff)) dev_err(&pdev->dev, "DMA memory at %px not aligned!\n", dma->vbuf[i]); } return 0; From 29cc552a6b0a7119ac0f808b6c20029350417ed8 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:29:38 +0200 Subject: [PATCH 12/18] not only used on exit, also on failed init --- ddbridge/ddbridge-main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ddbridge/ddbridge-main.c b/ddbridge/ddbridge-main.c index fd483c2..955fb12 100644 --- a/ddbridge/ddbridge-main.c +++ b/ddbridge/ddbridge-main.c @@ -84,7 +84,7 @@ int pci_irq_vector(struct pci_dev *dev, unsigned int nr) /****************************************************************************/ /****************************************************************************/ -static void __devexit ddb_irq_disable(struct ddb *dev) +static void ddb_irq_disable(struct ddb *dev) { if (dev->link[0].info->regmap->irq_version == 2) { ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL); @@ -114,7 +114,7 @@ static void __devexit ddb_msi_exit(struct ddb *dev) #endif } -static void __devexit ddb_irq_exit(struct ddb *dev) +static void ddb_irq_exit(struct ddb *dev) { ddb_irq_disable(dev); if (dev->msi == 2) From fa4e3331d8d430a2dfeca62cb7c6b237f5eb57f9 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:30:52 +0200 Subject: [PATCH 13/18] move compatibility stuff to dd_compat.h --- include/dd_compat.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/dd_compat.h b/include/dd_compat.h index 50bcced..d1f019d 100644 --- a/include/dd_compat.h +++ b/include/dd_compat.h @@ -1,3 +1,11 @@ +#include + +#if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE) +#define __devexit +#define __devinit +#define __devinitconst +#endif + #ifndef __has_attribute #define __has_attribute(x) 0 #endif From 390f67c03be2f4cf26ac1f50277fe501505d9761 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:32:00 +0200 Subject: [PATCH 14/18] remove modulator calls for octonet --- ddbridge/ddbridge-core.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index abc3195..4f9a673 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -534,7 +534,9 @@ static int ddb_output_start_unlocked(struct ddb_output *output) ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma)); } if (output->port->class == DDB_PORT_MOD) { +#ifndef CONFIG_MACH_OCTONET err = ddbridge_mod_output_start(output); +#endif } else { if (output->port->input[0]->port->class == DDB_PORT_LOOP) con = (1UL << 13) | 0x14; @@ -578,9 +580,11 @@ static void ddb_output_stop_unlocked(struct ddb_output *output) { struct ddb *dev = output->port->dev; +#ifndef CONFIG_MACH_OCTONET if (output->port->class == DDB_PORT_MOD) ddbridge_mod_output_stop(output); else +#endif ddbwritel(dev, 0, TS_CONTROL(output)); if (output->dma) { ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma)); @@ -1062,8 +1066,12 @@ static struct dvb_device dvbdev_ci = { static long mod_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { +#ifndef CONFIG_MACH_OCTONET return ddb_dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl); -} +#else + return 0; +#endif + } static const struct file_operations mod_fops = { .owner = THIS_MODULE, @@ -1228,6 +1236,7 @@ static int demod_attach_stv0367dd(struct ddb_input *input) return 0; } +#ifdef CONFIG_DVB_DRXK static int tuner_attach_tda18271(struct ddb_input *input) { struct i2c_adapter *i2c = &input->port->i2c->adap; @@ -1246,6 +1255,7 @@ static int tuner_attach_tda18271(struct ddb_input *input) } return 0; } +#endif static int tuner_attach_tda18212dd(struct ddb_input *input) { @@ -1530,7 +1540,9 @@ static void dvb_input_detach(struct ddb_input *input) dvb_netstream_release(&dvb->dvbns); fallthrough; case 0x20: +#ifdef CONFIG_DVB_NET dvb_net_release(&dvb->dvbnet); +#endif fallthrough; case 0x12: dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, @@ -1709,9 +1721,11 @@ static int dvb_input_attach(struct ddb_input *input) return ret; dvb->attached = 0x12; +#ifdef CONFIG_DVB_NET ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux); if (ret < 0) return ret; +#endif dvb->attached = 0x20; if (input->port->dev->ns_num) { @@ -2720,10 +2734,12 @@ static void ddb_ports_init(struct ddb *dev) ddb_input_init(port, 2 * i + 1, 1, 2 * p + 1); break; case DDB_MOD: +#ifndef CONFIG_MACH_OCTONET ddb_output_init(port, i); ddb_irq_set(dev, 0, i + rm->irq_base_rate, &ddbridge_mod_rate_handler, &dev->output[i]); +#endif break; default: break; @@ -4455,8 +4471,10 @@ int ddb_init(struct ddb *dev) if (ddb_i2c_init(dev) < 0) goto fail; ddb_ports_init(dev); +#ifndef CONFIG_MACH_OCTONET if (dev->link[0].info->type == DDB_MOD) ddbridge_mod_init(dev); +#endif if (ddb_buffers_alloc(dev) < 0) { dev_info(dev->dev, "Could not allocate buffer memory\n"); From 24801ab41a558fc59e7bf930fbb139793a0e2e47 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:32:51 +0200 Subject: [PATCH 15/18] add error return values --- ddbridge/ddbridge-mci.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ddbridge/ddbridge-mci.h b/ddbridge/ddbridge-mci.h index b61102e..c604cf9 100644 --- a/ddbridge/ddbridge-mci.h +++ b/ddbridge/ddbridge-mci.h @@ -101,6 +101,8 @@ #define MCI_STATUS_OK (0x00) #define MCI_STATUS_UNSUPPORTED (0x80) +#define MCI_STATUS_BUSY (0xFA) +#define MCI_STATUS_HARDWARE_ERROR (0xFB) #define MCI_STATUS_INVALID_PARAMETER (0xFC) #define MCI_STATUS_RETRY (0xFD) #define MCI_STATUS_NOT_READY (0xFE) From be79cec76e57c10275835644cfe67bb932610c2d Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:33:25 +0200 Subject: [PATCH 16/18] set legacy signal strength workaround according to channel number --- ddbridge/ddbridge-modulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ddbridge/ddbridge-modulator.c b/ddbridge/ddbridge-modulator.c index 7127675..3c06ec6 100644 --- a/ddbridge/ddbridge-modulator.c +++ b/ddbridge/ddbridge-modulator.c @@ -643,7 +643,7 @@ static int mod_set_attenuator(struct ddb *dev, u32 Value) .mod_stream = 0, .mod_setup_output = { .connector = MOD_CONNECTOR_F, - .num_channels = 24, + .num_channels = dev->link[0].info->port_num, .unit = MOD_UNIT_DBUV, .channel_power = 9000 - Value * 100, }, From 6336bd3689dee2b837edb59cddc367afb35ff8a9 Mon Sep 17 00:00:00 2001 From: internal Date: Tue, 25 Oct 2022 19:35:16 +0200 Subject: [PATCH 17/18] comment out test init --- ddbridge/ddbridge-modulator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ddbridge/ddbridge-modulator.c b/ddbridge/ddbridge-modulator.c index 3c06ec6..8b6cb1b 100644 --- a/ddbridge/ddbridge-modulator.c +++ b/ddbridge/ddbridge-modulator.c @@ -1909,6 +1909,7 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg) return ret; } +#if 0 static int mod_init_2_1(struct ddb *dev, u32 Frequency) { int i, streams = dev->link[0].info->port_num; @@ -1920,6 +1921,7 @@ static int mod_init_2_1(struct ddb *dev, u32 Frequency) } return 0; } +#endif static int mod_init_2(struct ddb *dev, u32 Frequency) { From cc03d96de2119b8a45da77ed9b633bdaff2f72d4 Mon Sep 17 00:00:00 2001 From: drmocm Date: Wed, 26 Oct 2022 13:16:21 +0200 Subject: [PATCH 18/18] added modtest.c --- apps/modtest.c | 1313 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1313 insertions(+) create mode 100644 apps/modtest.c diff --git a/apps/modtest.c b/apps/modtest.c new file mode 100644 index 0000000..71784c5 --- /dev/null +++ b/apps/modtest.c @@ -0,0 +1,1313 @@ + +// for systems without O_LARGEFILE +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef int16_t s16; +typedef uint32_t u32; +typedef uint64_t u64; + +#include "../ddbridge/ddbridge-mci.h" +#include "../ddbridge/ddbridge-ioctl.h" + +#define NIT_PID 0x0010 +#define MAXNIT 1024 +#define DEFAULT_BIT_RATE_C (50870588ULL) +#define DEFAULT_BIT_RATE_T (31668449ULL) +#define TS_SIZE (188) +#define START_FREQ_T (474000000) +#define START_FREQ_C (114000000) +static int adapt = 1; +static uint32_t start_freq = START_FREQ_C; +static int dvbt = 0; +static int writeNIT = 0; + +int timest = 1; + +typedef struct section_data_t { + uint8_t *section; + uint16_t sec_length; + uint16_t sec_pos; + uint8_t pack_num; +} section_data; + + +typedef struct transponder_{ + uint16_t tpid; + uint8_t delsys; + uint32_t freq; + uint8_t qam; + uint32_t symbolrate; + uint8_t bandwidth; + uint8_t guard; + uint8_t code_rate; + uint8_t trans_mode; +} transponder; + +typedef struct write_data_t { + int fd_in; + int *fd_out; + char *name; + int chans; + transponder tp[32]; +} write_data; + +#define ADAPT_FIELD 0x20 +#define MAX_PCR (2576980377599ULL) // max pcr 2^33*300-1 +#define PCR_FAC (2048ULL) +#define MAXPCR (MAX_PCR*PCR_FAC) +#define PCR_FLAG 0x10 +#define OPCR_FLAG 0x08 + +//++++++++++++++++++++++++++++++++CRC+++++++++++++++++++++++++++++++++++++ +static uint32_t dvb_crc_table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + + +uint32_t dvb_crc32(uint8_t *data, int len) +{ + int i; + uint32_t crc=0xffffffff; + + for (i=0; i>24)^(data[i]))&0xff]; + return crc; +} + +void dvb_set_crc32(uint8_t *data, int len) +{ + uint32_t crc; + + crc=dvb_crc32(data, len); + data[len] = (uint8_t)(crc>>24); + data[len+1] = (uint8_t)(crc>>16); + data[len+2] = (uint8_t)(crc>>8); + data[len+3] = (uint8_t)(crc); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//+++++++++++++++++++++++++++++++++++PCR++++++++++++++++++++++++++++++++++ + +uint16_t get_pid(uint8_t *pid) +{ + uint16_t pp; + + pp = (pid[0] & 0x1f) << 8; + pp |= pid[1] &0xff; + return pp; +} + +void set_pid(uint16_t pid, uint8_t *p) +{ + p[0] = (p[0] & 0xE0) | ((uint8_t) (pid >> 8 ) & 0x1F); + p[1] = (uint8_t) (pid); +} + +int pcr_in_msecs(uint64_t pcr) +{ + uint64_t PCR; + + PCR = pcr/PCR_FAC; + + return PCR/27000; +} + + +int check_pcr(uint8_t *buf) +{ + + if (buf[0] != 0x47) { + fprintf(stderr,"Not a TS packet header in check_pcr\n"); + return -1; + } + + if (buf[1] & 0x80) { + fprintf(stderr,"Corrupt packet in check_pcr\n"); + return -1; + } + + if (!(buf[3] & ADAPT_FIELD)){ +// fprintf(stderr,"no adaptation field\n"); + return 0; //no adapt. field + } + if (!buf[4]){ +// fprintf(stderr,"no adaptation field length\n"); + return 0; //No adaptation field length + } + if (! (buf[5] & PCR_FLAG) ){ +// fprintf(stderr,"no PCR flag\n"); + return 0; // no PCR FLAG + } +// fprintf(stderr,"Found pcr\n"); + return 1; +} + +uint8_t *get_pcr(uint8_t *buf) +{ + return buf+6; +} + +uint64_t convert_pcr(uint8_t *b){ + uint64_t pcr; + + pcr = ((uint64_t) b[0] << 25) | ((uint64_t) b[1] << 17) | + ((uint64_t) b[2] << 9) | ((uint64_t) b[3] << 1) | + ((uint64_t) b[4] >> 7); + pcr *= 300; + pcr += ((b[4] & 1) << 8) | b[5]; + return pcr*PCR_FAC; +} + +int find_pcr(uint8_t *buf, int l, int last) +{ + int c = 0; + while (buf[c] != 0x47) c++; + + if (last){ + c+=((l-c)/TS_SIZE-1)*TS_SIZE; + while (buf[c] != 0x47) c--; + while (c >=0 && !check_pcr(buf+c)) c-=TS_SIZE; + if (check_pcr(buf+c)) return c; + else return -1; + } else { + while (c < l && !check_pcr(buf+c)) c+=TS_SIZE; + if (check_pcr(buf+c)) return c; + else return -1; + } +} +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//+++++++++++++++++++++++++++++++++++TS PACKETS+++++++++++++++++++++++++++ + +void write_filler(uint8_t *buf) +{ + int j; + uint8_t *p; + + p = buf; + *p++ = 0x47; + *p++ = 0x1F; + *p++ = 0xFF; + *p++ = 0x00; + for(j = 0; j < TS_SIZE-4; j+=1 ) *p++ = 0x00; +} + +void setbcd(uint8_t *p, int freq, int b, int e) +{ + int i; + int f = freq/e; + int r = b%2; + + if (r){ + p[b/2] = ( (f % 10) >> 4) & 0xF0; + f = f / 10; + } + for ( i= b/2; i > 0; i--){ + p[i-1] = (f % 10) & 0x0F; + f = f / 10; + p[i-1] |= ( (f % 10) << 4) & 0xF0; + f = f / 10; + } +} + +static int write_cable_delsys_descriptor (uint8_t *buf, int blength, + transponder *tp) +{ + int length = 0; + uint8_t *p; + + p = buf; + length = 11; + + if (length > (int)(0xFF) || length+2 >blength){ + fprintf(stderr,"Not enough space for cable delsys descriptor %d, %d\n", + length, blength); + return -1; + } + p[0]= 0x44; // cable delivery system descriptor + p[1]= 0x0B; // length always 11 + setbcd(p+2, tp->freq, 8, 100); + p[6] = 0xFF; // reserved + p[7]= 0x02; // FEC_outer + p[8]= tp->qam; // QAM + setbcd(p+9,tp->symbolrate, 7, 100); + p[12]|= 0x0F; + + return length+2; +} + +static int write_terrestrial_delsys_descriptor (uint8_t *buf, int blength, + transponder *tp) +{ + int length = 0; + uint8_t *p; + uint32_t freq = tp->freq/10; + p = buf; + length = 11; + + if (length > (int)(0xFF) || length+2 >blength){ + fprintf(stderr,"Not enough space for cable delsys descriptor %d, %d\n", + length, blength); + return -1; + } + p[0]= 0x5a; // terretrial delivery system descriptor + p[1]= 0x0B; // length always 11 + p[2]= (freq >> 24) & 0xFF; + p[3]= (freq >> 16) & 0xFF; + p[4]= (freq >> 8) & 0xFF; + p[5]= freq & 0xFF; + p[6]= ((tp->bandwidth&0x7)<<5) |0x1f; + //bandwidth 8MHz 000,no priority 1, + //no time slice 1, no mpe-fce 1 + p[7]= 0x00 |((tp->qam & 0x03) << 6) | (tp->code_rate &0x07); + //64-QAM 10, no hierarchy 000, 7/8 100 + p[8]= 0x00 | ((tp->guard &0x03) <<3 )|((tp->trans_mode &0x03) << 1); + // no LP 000, 1/32 guard 00, 8k mode 01, no other freq 0 + + p[9]=0xff; + p[10]=0xff; + p[11]=0xff; + p[12]=0xff; + + return length+2; +} + +int CreateNIT(uint8_t *NIT, transponder *tp, int start, int stop, + char *nname, uint16_t nid, uint8_t secnum, uint8_t lastsec) +{ + uint8_t *p,*lp; + int c = 0; + int cc; + int i; + uint16_t TableLen = 0; + int slen; + + p = NIT; + + p[0] = 0x40; // Table Id NIT = 0x40 + + p[1] = 0x00; // Table length determined at end + p[2] = 0x00; + + p[3] = (nid >> 8) & 0xFF; // network id + p[4] = nid & 0xFF; + + p[5] = 0xC3; // seq number + p[6] = secnum; // section number + p[7] = lastsec; // last section number + + +// Network descriptor + p[8] = 0xF0; // network descriptor length + p[9] = 0x00; // set later + TableLen = 7; + c = 10; + p[c] = 0x40; // Network name descriptor + + slen = 0; + + slen = strlen(nname); + p[c+1] = slen; + memcpy(p+c+2,nname,slen); + + p[8] = 0xF0 | (((2+slen) >> 8) &0x0F); + p[9] = ((2+slen) & 0xFF); + TableLen += 2+slen; + c += 2+slen; + + +// Transport stream loop + p[c] = 0xF0; // transport stream loop length + p[c+1] = 0x00; // set later + cc = c+1; + + TableLen += 2; + c += 2; + slen = 0; + for (i= start; i < stop; i++){ + p[c] = (uint8_t)( tp[i].tpid >> 8 ); //transport stream id + p[c+1]= (uint8_t)( tp[i].tpid ); + p[c+2]= (nid >> 8) &0xFF; // orig network id + p[c+3]= nid & 0xFF; // id + + lp = p+c+4; + p[c+4]= 0xF0; // descriptor loop length + p[c+5]= 0x0D; // 13 for cable delivery descriptor + c += 6; + switch (tp->delsys){ + case SYS_DVBC_ANNEX_A: + slen = write_cable_delsys_descriptor (p+c, MAXNIT-c, &tp[i]); + break; + case SYS_DVBT: + slen = write_terrestrial_delsys_descriptor (p+c, MAXNIT-c, &tp[i]); + break; + default: + slen = 0; + } + c+=slen; + + lp[0] = 0xF0 | (((slen) >> 8) &0x0F); + lp[1] = ((slen) & 0xFF); + + + TableLen += 6+slen; + } + + p[cc-1]= 0xF0 | (((c-cc-1) >> 8) &0x0F); + p[cc] = ((c-cc-1) & 0xFF); + + TableLen += 4; + + p[1] = 0xF0 | ((TableLen >> 8) & 0x0F); + p[2] = (uint8_t)(TableLen) & 0xFF; + + + dvb_set_crc32(NIT, TableLen + 3 -4 ); + return TableLen+3; + +} + +void init_sec_data(section_data *s, uint8_t *sec, uint16_t seclength) +{ + uint16_t seclen = 0; + + s->section = sec; + seclen |= ((sec[1] & 0x0F) << 8); + seclen |= (sec[2] & 0xFF); + seclen += 3; + if (seclen > 3){ + s->sec_length = seclen; + if(seclength && seclen != seclength) + fprintf(stderr,"Setting seclength (%d) %d\n",seclength, seclen); + } else s->sec_length = seclength; + + s->sec_pos = 0; + s->pack_num = 0; +} + +void write_sec_pack(section_data *s, uint8_t *ts_pack, uint16_t pid) +{ + uint8_t *p = ts_pack; + uint16_t rest = 0; + uint16_t len = s->sec_length - s->sec_pos; + uint16_t pload = 0; + + *p++ = 0x47; + set_pid(pid,p); + if (!s->sec_pos){ + *p |= 0x40; + } else { + *p &= ~0x40; + } + p += 2; + *p++ = 0x10 | (s->pack_num & 0x0f); + s->pack_num += 1; + if (!s->sec_pos) *p++=0x00; + pload = TS_SIZE - (p - ts_pack); + if (pload > len) pload = len; + memcpy( p, s->section + s->sec_pos, pload); + p += pload; + rest = TS_SIZE - (p - ts_pack); + if (rest > 0) + memset(p, 0xff, rest); + s->sec_pos += pload; + if (s->sec_pos == s->sec_length){ + s->sec_pos = 0; + } +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//++++++++++++++++++++++++++++++++MAIN ROUTINE++++++++++++++++++++++++++++ + +#define OBSIZE (672*TS_SIZE) +#define BSIZE (7*OBSIZE) + +void write_mods(write_data *wd) +{ + uint8_t NIT[MAXNIT]; + section_data sec; + off64_t inflength,c=0; + uint8_t buffer[BSIZE]; + uint8_t obuffer[OBSIZE]; + int ci=0,w=0; + int isdvr=0; + int first = 0; + int last = 0; + uint64_t fpcr = 0; + uint64_t lpcr = 0; + uint64_t delta_pcr = 0; + uint64_t in_prate, out_prate; + int slen = 0; + + if (dvbt){ + out_prate = DEFAULT_BIT_RATE_T / (8*TS_SIZE); + } else { + out_prate = DEFAULT_BIT_RATE_C / (8*TS_SIZE); + } + slen = CreateNIT(NIT, wd->tp, 0, wd->chans, "DD", 1, 0, 0); + + init_sec_data(&sec, NIT, slen); + in_prate = 0; + + inflength = lseek64(wd->fd_in, 0, SEEK_END); + inflength = TS_SIZE*(inflength/TS_SIZE); + if (inflength <= 0){ + if (inflength == 0 || errno == ESPIPE){ + isdvr = 1; + fprintf(stderr,"Non seekable file, handling as dvr\n"); + } else { + fprintf(stderr,"Error in lseek, aborting\n"); + return; + } + } + + if (!isdvr){ + fprintf(stderr,"Input file length: %.2f MiB\n",inflength/1024./1024.); + lseek64(wd->fd_in,0,SEEK_SET); + } + + fprintf(stderr,"Starting %s\n",wd->name); + while (1) { + int wc=0; + first = 0; + last = 0; + + if ((ci=read(wd->fd_in,buffer,BSIZE))<0) return; + + first = find_pcr(buffer, ci, 0); + last = find_pcr(buffer, ci, 1); + if (first == last){ + fprintf(stderr,"Input buffer too small\n" + "first %d last %d length %d pidf 0x%x\n", first/TS_SIZE, + last/TS_SIZE, + ci/TS_SIZE, get_pid(buffer+first+1)); + } + fpcr = convert_pcr(get_pcr(buffer+first)); + lpcr = convert_pcr(get_pcr(buffer+last)); + if (lpcr > fpcr) delta_pcr = lpcr - fpcr; + else delta_pcr = (MAXPCR-fpcr)+lpcr; + int packs = (last-first)/TS_SIZE; + in_prate = ((packs*10000/pcr_in_msecs(delta_pcr))+5)/10; + +#if 0 + fprintf(stderr,"delta_pcr %d ms npack %d packet_rate in: %d out: %d\n", + pcr_in_msecs(delta_pcr), + packs, in_prate, out_prate); + fprintf(stderr,"Input bitrate %.2f MBit output bitrate %.2f MBit\n", + (in_prate*TS_SIZE*8)/1000000.0, + (out_prate*TS_SIZE*8)/1000000.0); +#endif + + if (in_prate > out_prate){ + fprintf(stderr,"Input bitrate (%.2f MBit) larger than " + "possible output bitrate (%.2f MBit)\n", + (in_prate*TS_SIZE*8)/1000000.0, + (out_prate*TS_SIZE*8)/1000000.0); + exit(1); + } + + int filler = (out_prate*10/in_prate+5)/10-1; + int d=0; + int rest=0; + for (int s = 0; s < ci; s+=TS_SIZE){ + memcpy(obuffer+d, buffer+s, TS_SIZE*sizeof(uint8_t)); + d+=TS_SIZE; + int fill = (OBSIZE - d)/TS_SIZE; + if (fill < filler) rest = filler - fill; + else fill = filler; +// fprintf(stderr,"d %d fill %d filler %d %d %d\n", d, fill,filler,s,ci); + int nit = 0; + for(int i=0;i < fill; i++){ + if (writeNIT && nit < 4 ) { + write_sec_pack(&sec, obuffer+d, NIT_PID); + nit++; + } else write_filler(obuffer+d); + d+=TS_SIZE; + } + if (d >= OBSIZE){ + for (int m = 0; m < wd->chans; m++){ + int lc = 0; + while (lc < OBSIZE){ + if ((w=write(wd->fd_out[m],obuffer+lc,OBSIZE-lc))<0){ + fprintf(stderr,"Problem writing to modulator from %s (%d %d) %s\n", + wd->name, w, ci,strerror(errno)); + return; + } + wc += w; + lc+=w; + d = 0; + } + } + } + + for(int i=0;i < rest; i++){ + write_filler(obuffer+d); + d+=TS_SIZE; + } + rest = 0; + } + if (inflength){ + c+=ci; + fprintf(stderr,"written %d %d%%\n",(int)c,(int)((100*c)/inflength)); + if (c >=inflength ){ + fprintf(stderr,"Restarting stream %s\n",wd->name); + lseek64(wd->fd_in,0,SEEK_SET); + c = 0; + } + } + } +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//+++++++++++++++++++++++++++++++++DVB DEVICES++++++++++++++++++++++++++++ + +#define DVB_TUNE 0 +#define DVB_MOD 1 +#define DVB_CA 2 +#define MAX_ADAPT 32 + +typedef struct dvb_devices_t { + int adapters; + int dtype[MAX_ADAPT]; + int ndevs[MAX_ADAPT]; + uint64_t snr[MAX_ADAPT]; + uint64_t hwid[MAX_ADAPT]; + uint64_t devid0[MAX_ADAPT]; +} dvb_devices; + + +static int check_tuner(int adapt) +{ + char device[35]; + int front = 0; + int done = 0; + + while (!done) { + snprintf(device,34,"/dev/dvb/adapter%d/frontend%d",adapt,front); +// fprintf(stderr,"Checking for %s\n", device); + if(access(device, F_OK) < 0) + done=1; + else { + front++; + } + } + return front; +} + +static int check_ca(int adapt) +{ + char device[25]; + int ca = 0; + int done = 0; + + while (!done) { + snprintf(device,24,"/dev/dvb/adapter%d/ci%d",adapt,ca); + if(access(device, F_OK) < 0) + done=1; + else { + ca++; + } + } + return ca; +} + +static int check_modulator(int adapt) +{ + char device[25]; + int mod = 0; + int done = 0; + + while (!done) { + snprintf(device,24,"/dev/dvb/adapter%d/mod%d",adapt,mod); + if(access(device, F_OK) < 0) + done=1; + else { + mod++; + } + } + return mod; +} + + +static int check_dvb(dvb_devices *ddevices){ + int done = 0; + int nadapt = 0; + int maxmod = 0; + int maxfront = 0; + int maxca = 0; + int i; + int adapter =0; + + while ( nadapt < MAX_ADAPT && !done){ + maxca = check_ca(nadapt); + maxmod = check_modulator(nadapt); + maxfront = check_tuner(nadapt); + + if (maxmod){ + ddevices->dtype[nadapt] = DVB_MOD; + ddevices->ndevs[nadapt] = maxmod; + maxmod = 0; + nadapt++; + } else { + if (maxfront) { + ddevices->dtype[nadapt] = DVB_TUNE; + ddevices->ndevs[nadapt] = maxfront; + maxfront = 0; + nadapt++; + } else { + if (maxca) { + ddevices->dtype[nadapt] = DVB_CA; + ddevices->ndevs[nadapt] = maxca; + maxca = 0; + nadapt++; + } else { + done = 1; + } + } + } + } + ddevices->adapters = nadapt; + if (!nadapt) return -1; + + fprintf(stderr,"Found %d dvb adapters\n",nadapt); + for (i=0; idtype[i]){ + case DVB_TUNE: + fprintf(stderr," Adapter %d is a TUNER CARD with %d FRONTENDS\n", i, ddevices->ndevs[i]); + break; + case DVB_MOD: + fprintf(stderr," Adapter %d is a MODULATOR CARD with %d MODULATORS\n", i, ddevices->ndevs[i]); + adapter = i; + break; + case DVB_CA: + fprintf(stderr," Adapter %d is a CI CARD with %d CA \n",i,ddevices->ndevs[i]); + break; + } + } + return adapter; +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//++++++++++++++++++++++++++++++++DVBT MOD++++++++++++++++++++++++++++++++ + +static int mci_cmd(int dev, struct mci_command *cmd) +{ + int ret; + struct ddb_mci_msg msg; + uint8_t status; + + memset(&msg, 0, sizeof(msg)); + msg.link = 0; + memcpy(&msg.cmd, cmd, sizeof(msg.cmd)); + //dump((uint8_t *) &msg.cmd, sizeof(msg.cmd)); + ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); + if (ret < 0) { + dprintf(2, "mci_cmd error %s\n",strerror(errno)); + return ret; + } + status = msg.res.status; + if (status == MCI_STATUS_OK) + return ret; + if (status == MCI_STATUS_UNSUPPORTED) { + dprintf(2, "Unsupported MCI command\n"); + return ret; + } + if (status == MCI_STATUS_INVALID_PARAMETER) { + dprintf(2, "Invalid MCI parameters\n"); + return ret; + } + return ret; +} + +int mci_set_output(int fd, uint8_t connector, uint8_t nchannels, uint8_t unit, + int16_t power) +{ + char con[14]; + char un[6]; + struct mci_command msg_output = { + .mod_command = MOD_SETUP_OUTPUT, + .mod_channel = 0, + .mod_stream = 0, + .mod_setup_output = { + .connector = MOD_CONNECTOR_F, + .num_channels = 14, + .unit = MOD_UNIT_DBUV, + .channel_power = 9000, + }, + }; + + msg_output.mod_setup_output.connector = connector; + msg_output.mod_setup_output.num_channels = nchannels; + msg_output.mod_setup_output.unit = unit; + msg_output.mod_setup_output.channel_power = power; + + + switch (connector){ + case MOD_CONNECTOR_F: + snprintf(con, 14, "F-Connector"); + break; + + case MOD_CONNECTOR_SMA: + snprintf(con, 14, "SMA-Connector"); + break; + + case MOD_CONNECTOR_OFF: + snprintf(con, 14, "off"); + break; + + default: + fprintf(stderr,"unknown connector in modulator setup\n"); + return -1; + break; + } + switch (unit){ + case MOD_UNIT_DBUV: + snprintf(un, 6, " dBuV"); + break; + + case MOD_UNIT_DBM: + snprintf(un, 6, " dBm"); + break; + + default: + fprintf(stderr,"unknow power unit in modulator setup\n"); + return -1; + break; + } + + fprintf(stderr,"Setting DVBT Modulator output to %s, %d channels, power %f%s\n", + con, nchannels, (double)power/100, un ); + + return mci_cmd(fd,&msg_output); +} + +int mci_set_output_simple(int adapt, uint8_t nchannels) +{ + char fn[128]; + int re = 0; + + snprintf(fn, 127, "/dev/dvb/adapter%u/mod0", adapt); + int fd = open(fn, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Could not open %s\n", fn); + return -1; + } + + re = mci_set_output(fd, MOD_CONNECTOR_F, nchannels, MOD_UNIT_DBUV, 9000); + close(fd); + return re; +} + +int mci_set_channels(int fd, uint32_t freq, uint8_t nchan, uint8_t standard, + uint32_t offset, uint32_t bandw) +{ + char stand[25]; + struct mci_command msg_channels = { + .mod_command = MOD_SETUP_CHANNELS, + .mod_channel = 0, + .mod_stream = 0, + .mod_setup_channels[0] = { + .flags = MOD_SETUP_FLAG_FIRST|MOD_SETUP_FLAG_LAST|MOD_SETUP_FLAG_VALID, + .standard = MOD_STANDARD_DVBT_8, + .num_channels = 25, + .frequency = 474000000, + }, + }; + + msg_channels.mod_setup_channels[0].frequency = freq; + msg_channels.mod_setup_channels[0].num_channels = nchan; + msg_channels.mod_setup_channels[0].standard = standard; + if (standard == MOD_STANDARD_GENERIC){ + msg_channels.mod_setup_channels[0].offset = offset; + msg_channels.mod_setup_channels[0].bandwidth = bandw; + } + + switch(standard){ + case MOD_STANDARD_GENERIC: + snprintf(stand, 24, "MOD_STANDARD_GENERIC"); + break; + + case MOD_STANDARD_DVBT_8: + snprintf(stand, 24, "MOD_STANDARD_DVBT_8"); + break; + + case MOD_STANDARD_DVBT_7: + snprintf(stand, 24, "MOD_STANDARD_DVBT_7"); + break; + + case MOD_STANDARD_DVBT_6: + snprintf(stand, 24, "MOD_STANDARD_DVBT_6"); + break; + + case MOD_STANDARD_DVBT_5: + snprintf(stand, 24, "MOD_STANDARD_DVBT_5"); + break; + + default: + fprintf(stderr,"unknown standard in channels setup\n"); + return -1; + break; + + } + fprintf(stderr,"Setting DVBT Modulator channels to %d HZ, %d channels, %s\n", + freq, nchan, stand); + + return mci_cmd(fd,&msg_channels); +} + +int mci_set_channels_simple(int adapt, uint32_t freq, uint8_t nchan) +{ + + char fn[128]; + int re = 0; + + snprintf(fn, 127, "/dev/dvb/adapter%u/mod0", adapt); + int fd = open(fn, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Could not open %s\n", fn); + return -1; + } + + re = mci_set_channels(fd, freq, nchan, MOD_STANDARD_DVBT_8, 0, 0); + close(fd); + return re; +} + +int mci_set_stream( int fd, uint8_t stream, uint8_t channel, uint8_t standard, + uint8_t stream_format, uint32_t symbol_rate, + uint8_t modulation, uint8_t rolloff, + uint8_t fft_size, uint8_t guard_interval, + uint8_t puncture_rate, uint8_t constellation, + uint16_t cell_identifier) +{ + struct mci_command msg_stream = { + .mod_command = MOD_SETUP_STREAM, + .mod_channel = 0, + .mod_stream = 0, + .mod_setup_stream = { + .standard = MOD_STANDARD_DVBC_8, + }, + }; + + msg_stream.mod_channel = channel; + msg_stream.mod_stream = stream; + msg_stream.mod_setup_stream.standard = standard; + msg_stream.mod_setup_stream.stream_format = stream_format; + if (symbol_rate) + msg_stream.mod_setup_stream.symbol_rate = symbol_rate; + if (modulation) + msg_stream.mod_setup_stream.qam.modulation = modulation; + if (rolloff) + msg_stream.mod_setup_stream.qam.rolloff = rolloff; + msg_stream.mod_setup_stream.ofdm.fft_size = fft_size; + msg_stream.mod_setup_stream.ofdm.guard_interval = guard_interval; + msg_stream.mod_setup_stream.ofdm.puncture_rate = puncture_rate; + msg_stream.mod_setup_stream.ofdm.constellation = constellation; + if (cell_identifier) + msg_stream.mod_setup_stream.ofdm.cell_identifier = cell_identifier; + + fprintf(stderr,"Setting DVBT Stream %d to channel %d\n",stream, channel); + + return mci_cmd(fd,&msg_stream); + +} + +void set_dvbt_mods(int adapt, int chans, uint32_t start_freq, write_data *wd) +{ + if ((mci_set_output_simple(adapt, chans) < 0)|| + (mci_set_channels_simple(adapt, start_freq, chans)< 0)) + { + fprintf(stderr,"Error setting up DVBT Modulator\n"); + exit(1); + } + wd->chans = chans; + wd->fd_out = (int *)malloc(chans*sizeof(int)); + memset(wd->fd_out,0,chans*sizeof(int)); + + for (int i = 0; i < chans; i++){ + char *device; + int fd; + + wd->tp[i].tpid = 1; // all the same transport stream id + wd->tp[i].delsys = SYS_DVBT; + wd->tp[i].freq = start_freq+8000000*i; + wd->tp[i].qam = 2; + wd->tp[i].symbolrate = 0; + wd->tp[i].bandwidth = 0; + wd->tp[i].guard = 0; + wd->tp[i].code_rate = 4; + wd->tp[i].trans_mode = MOD_STANDARD_DVBT_8; + + device = malloc(sizeof(char)*25); + snprintf(device,24,"/dev/dvb/adapter%d/mod%d",adapt,i); + fd = open(device, O_RDWR); + if( fd < 0 ) + { + fprintf(stderr,"Error opening %s : %s\n",device,strerror(errno)); + free(device); + exit(1); + } + + mci_set_stream( fd, i, i, MOD_STANDARD_DVBT_8, 4, 0, 0, 0, 1, 0, 4, 2, 0); + close(fd); + free(device); + } +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//++++++++++++++++++++++++++++++++DVBC MOD++++++++++++++++++++++++++++++++ + +static int set_property(int fd, uint32_t cmd, uint32_t data) +{ + struct dtv_property p; + struct dtv_properties c; + int ret; + + p.cmd = cmd; + c.num = 1; + c.props = &p; + p.u.data = data; + ret = ioctl(fd, FE_SET_PROPERTY, &c); + if (ret < 0) { + fprintf(stderr, "FE_SET_PROPERTY returned %d\n", errno); + return -1; + } + return 0; +} + +static int set_input_bitrate(int fd, uint64_t data) +{ + struct dtv_property p; + struct dtv_properties c; + int ret; + + p.cmd = MODULATOR_INPUT_BITRATE; + c.num = 1; + c.props = &p; + p.u.data64 = data; + ret = ioctl(fd, FE_SET_PROPERTY, &c); + if (ret < 0) { + fprintf(stderr, "FE_SET_PROPERTY returned %d\n", errno); + return -1; + } + return 0; +} + +void set_dvbc_mods(int adapt, int chans, uint32_t start_freq, write_data *wd) +{ + uint32_t freq = start_freq; + uint8_t qam = QAM_256; + uint32_t sym = 6900000; + + wd->chans = chans; + wd->fd_out = (int *)malloc(chans*sizeof(int)); + memset(wd->fd_out,0,chans*sizeof(int)); + + for (int i = 0; i < chans; i++){ + char *device; + int fd; + + wd->tp[i].tpid = i; + wd->tp[i].delsys = SYS_DVBC_ANNEX_A; + wd->tp[i].freq = freq; + wd->tp[i].qam = qam; + wd->tp[i].symbolrate = sym; + wd->tp[i].bandwidth = 0; + wd->tp[i].guard = 0; + wd->tp[i].code_rate = 0; + wd->tp[i].trans_mode = 0; + + device = malloc(sizeof(char)*25); + snprintf(device,24,"/dev/dvb/adapter%d/mod%d",adapt,i); + fd = open(device, O_RDWR); + if( fd < 0 ) + { + fprintf(stderr,"Error opening %s : %s\n",device,strerror(errno)); + free(device); + exit(1); + } + if (set_property(fd, MODULATOR_FREQUENCY, freq) < 0){ + fprintf(stderr,"setting freq %d failed\n",freq); + exit(1); + } + if (set_property(fd, MODULATOR_MODULATION, qam) < 0){ + fprintf(stderr,"setting qam %d failed\n",qam); + exit(1); + } + if (set_property(fd, MODULATOR_SYMBOL_RATE, sym) < 0){ + fprintf(stderr,"setting sym %d failed\n",sym); + exit(1); + } + + if (set_input_bitrate(fd, (DEFAULT_BIT_RATE_C << 32)) < 0){ + fprintf(stderr,"setting bitrate %d failed\n", + (int)DEFAULT_BIT_RATE_C); + exit(1); + } + + + if (set_property(fd, MODULATOR_PCR_MODE, 0) < 0){ + fprintf(stderr,"setting pcr mode 0 failed\n"); + exit(1); + } + freq += 8000000; + close(fd); + free(device); + } +} + +//+++++++++++++++++++++++++++++CLI++++++++++++++++++++++++++++++++++++++++ + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +static void usage(char *progname) +{ + printf ("usage: %s [options] \n\n",progname); + printf ("options:\n"); + printf (" --adapter, -a : adapter number of modulator card\n"); + printf (" --file, -i : input filename(default test.ts)\n"); + printf (" --frequency, -f : start frequency in MHz( default DVB_C 114MHz, DVB-T 474MHz)\n"); + printf (" --dvbt, -t : modulator is DVB-T\n"); + printf (" --NIT, -n : write a minimal NIT for fatser scan\n"); + printf (" --help, -h : print help message\n"); + printf ("\n"); + printf ("\n"); + exit(1); +} + + +static int parse_cl(int argc, char * const argv[], char **filename) +{ + int c; + int fset = 0; + + *filename = strdup("test.ts"); + + writeNIT = 0; + dvbt = 0; + while (1){ + int option_index = 0; + static struct option long_options[] = { + {"help", no_argument , NULL, 'h'}, + {"dvbt", no_argument , NULL, 't'}, + {"NIT", no_argument , NULL, 'n'}, + {"adapter", required_argument , NULL, 'a'}, + {"file", required_argument , NULL, 'i'}, + {"frequency", required_argument , NULL, 'f'}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long (argc, argv, "ha:i:f:nt",long_options, + &option_index); + + if (c == -1) + break; + + switch (c){ + case 'a': + adapt = (int)strtol(optarg,(char **)NULL, 0); + break; + + case 'f': + fset = 1; + start_freq = strtoul(optarg, NULL, 0)*1000000; + break; + + case 'i': + if (*filename){ + free(*filename); + } + *filename = strdup(optarg); + break; + + case 'n': + writeNIT = 1; + break; + + case 't': + if (!fset) start_freq = START_FREQ_T; + dvbt = 1; + break; + + case 'h': + case '?': + default: + usage(argv[0]); + + } + } + + return adapt; + +} +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//++++++++++++++++++++++++++++++++++++MAIN++++++++++++++++++++++++++++++++ + +int main(int argc, char **argv) +{ + const char *progn = "modtest"; + + int maxout = 0; + int mods = 0; + char *filename; + char *device; + dvb_devices ddevices; + write_data wd; + int fd_out; + int fd_in; + + printf("%s \n\n", progn); + adapt = parse_cl(argc, argv, &filename); + if (check_dvb(&ddevices)<0){ + fprintf(stderr,"No DVB devices found\n"); + exit(1); + } + + for (int i=0; i