41 Commits

Author SHA1 Message Date
rjkm
0b54436695 correct version number 2025-01-21 21:46:39 +01:00
rjkm
a986a98b96 return PLS in transmission_mode 2024-11-16 14:34:24 +01:00
rjkm
345c3b8e0d fix compilation with newer kernels 2024-11-16 14:25:10 +01:00
rjkm
b172e83a4b show XO2 firmware version 2024-11-16 14:24:07 +01:00
rjkm
5fef324ea0 add support for license setting via MCI commands (only FSM cards for now) 2024-10-20 22:39:37 +02:00
rjkm
63f693946c make new compiler warning settings happy 2024-09-19 10:54:57 +02:00
rjkm
17b741b01d support 16 channel DVB-T card 2024-09-19 10:53:23 +02:00
rjkm
8e4379ef3e only allow values between 0-3 2024-09-19 10:52:37 +02:00
rjkm
1022b26d7f cleanup init for FSM and DVB-T cards 2024-09-19 10:51:57 +02:00
rjkm
59cbab6383 prevent lockup 2024-09-19 10:35:39 +02:00
rjkm
0fcd9563f1 only warn about zigzag if max_drift is set 2024-09-19 10:34:30 +02:00
rjkm
cf64ad4b0e show more information about card connected at GT link 2024-09-19 10:33:25 +02:00
rjkm
1c88e05931 factor out setting of input 2024-09-19 10:31:41 +02:00
rjkm
11b8c21cb5 revert ignoring of bad packets at startup 2024-09-19 10:29:48 +02:00
rjkm
3cc98a4995 adapt to newer kernel version 2024-09-19 10:28:59 +02:00
rjkm
0c328cd989 do not allow unaligned access 2024-09-19 10:23:58 +02:00
rjkm
ffbef1488e remove unused tasklet struct 2024-09-19 10:22:46 +02:00
rjkm
8badef38a7 use correct lib name 2024-09-19 10:19:51 +02:00
rjkm
5d47dbec26 add 16 channel version of DVB-T modulator 2024-09-19 10:18:51 +02:00
drmocm
0368446256 modulator info 2024-07-11 13:57:59 +02:00
drmocm
07d5675b06 some information for DVB-T modulators 2024-07-11 13:50:17 +02:00
rjkm
ea8e877dca use dvb_filter.h only locally 2024-04-26 16:33:45 +02:00
rjkm
9ec5f40324 also install dvb_filter.h 2024-04-26 16:17:43 +02:00
rjkm
50e230b48d add dvb filter 2024-03-29 14:05:49 +01:00
rjkm
4197d9a59e make copying to/from CA device more robust, add TDT callback 2024-03-29 14:04:33 +01:00
rjkm
62b0b57c5d Add some more comments to MCI API documentation. 2024-03-26 22:36:05 +01:00
rjkm
fe63f1d0b8 Change assignment of devices when using kernel dvb-core.
Modulators are now osdX.
2024-03-26 22:34:52 +01:00
rjkm
dc384c70af Add input select via configurable DiSeqC message. 2024-03-26 22:30:23 +01:00
rjkm
4e0bf8b182 Add reset function. 2024-03-26 22:28:31 +01:00
rjkm
e7390e1cd8 Ignore errors at start, they are from aold data in buffers/FIFOs. 2024-03-26 22:27:43 +01:00
rjkm
d54905cc14 Remove ISDB entries when using kernel dvb-core because array is too small.
ISDB modes are then not enumerated but still work.
2024-03-26 22:22:52 +01:00
rjkm
7779445112 Add example for 2 regions in DVB-C and move modulator.conf to modulator-t.conf 2024-03-26 22:21:09 +01:00
rjkm
3ba2128c4e Support several channel regions. They have to start with frequency now! 2024-03-26 22:17:41 +01:00
rjkm
8f2bf94b43 Add some comments about using kernel dvb-core. 2024-03-26 22:16:18 +01:00
rjkm
a927449610 Merge branch 'internal' of hippo:rjkm/dddvb into internal 2024-03-10 21:45:55 +01:00
rjkm
3295328aa9 Merge branch 'internal' of hippo:rjkm/dddvb into internal 2024-03-10 21:45:09 +01:00
drmocm
2b53b34350 even longer device filenames 2024-03-08 09:19:46 +01:00
rjkm
a6f022941f remove gt link tasklet code 2024-03-08 00:33:57 +01:00
rjkm
da1594d424 prevent warning if KERNEL_DVB_CORE=y is used 2024-03-08 00:19:22 +01:00
drmocm
32afa3e920 changed dvb file name length to 60 2024-03-07 19:42:49 +01:00
f8726493b1 adapt defines to make KERNEL_DVB_CORE (compile against kernel dvb-core) work again 2024-03-06 17:07:08 +01:00
41 changed files with 835 additions and 456 deletions

View File

@@ -3,13 +3,14 @@ MDIR ?=
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=y DDDVB=y
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 DDDVB=y
KBUILD_EXTMOD = $(PWD)
ifeq ($(KERNEL_DVB_CORE),y)
DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD) -DKERNEL_DVB_CORE=y"
else
MODDEFS += CONFIG_DVB_NET=y
DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux"
endif

View File

@@ -1,5 +1,7 @@
# DDBridge Driver
Device driver for all Digital Devices DVB demodulator and modulator cards.
### Patches
We can only accept patches which don't break compilation for older kernels (as far back as 2.6.37).
@@ -9,12 +11,23 @@ incompatiblities to this driver package.
For installation instructions see:
http://support.digital-devices.eu/index.php?article=152
### Prepare for Building
TBD
### Building
TBD
To compile against the dvb-core of a current kernel compile with KERNEL_DVB_CORE=y:
make KERNEL_DVB_CORE=y install
This will only work with current mainline kernels.
Some features will also not work correctly with the mainline kernel dvb-core:
- some devices will have fewer delivery systems enumerated
if one you need is missing you will have to fix it yourself
- the DTV_INPUT property will not work
- local bugfixes in dvb-core will be missing
- Some device names will be different because they do not exist in the kernel
Also, do not forget to delete old dvb-core modules from e.g. /lib/modules/x.y.z-amd64/updates/ !

View File

@@ -1,4 +1,4 @@
TARGETS = cit ddtest setmod1 setmod2 modconfig ddinfo getiq modtest
TARGETS = cit ddtest setmod1 setmod2 modconfig ddinfo getiq modtest ddlicense
all: $(TARGETS)

View File

@@ -10,8 +10,9 @@
#include <sys/ioctl.h>
#include <pthread.h>
#include <getopt.h>
#include <linux/dvb/ca.h>
uint32_t adapter = 0, device = 0, snum = 256, rnum = 256;
uint32_t adapter = 0, device = 0, snum = 256, rnum = 256, do_reset = 0;
uint8_t fill[188]={0x47, 0x1f, 0xff, 0x10,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
@@ -83,6 +84,8 @@ void proc_buf(uint8_t *buf, uint32_t *d)
c=(buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7];
if (c!=*d) {
printf("CONT ERROR: got %08x expected %08x\n", c, *d);
//if (!*d && (c+100) > 100)
// return;
*d=c;
} else {
if (memcmp(ts+8, buf+8, 180))
@@ -169,6 +172,34 @@ int send(void)
}
void reset()
{
char fname[80];
int fd, i;
sprintf(fname, "/dev/dvb/adapter%u/ca%u", adapter, device);
fd=open(fname, O_WRONLY);
if (fd < 0)
return;
ioctl(fd, CA_RESET);
for (i=0; i<24; i++) {
ca_slot_info_t info;
usleep(500000);
info.num = 0;
if (ioctl(fd, CA_GET_SLOT_INFO, &info))
return;
if (info.flags & CA_CI_MODULE_READY)
break;
}
if (i==24)
dprintf(2, "RESET failed\n");
}
int main(int argc, char **argv)
{
pthread_t th;
@@ -181,11 +212,12 @@ int main(int argc, char **argv)
{"device", required_argument, 0, 'd'},
{"snum", required_argument, 0, 's'},
{"rnum", required_argument, 0, 'r'},
{"reset", no_argument, 0, 'R'},
{"help", no_argument , 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"a:d:h",
"a:d:hs:R",
long_options, &option_index);
if (c==-1)
break;
@@ -203,6 +235,9 @@ int main(int argc, char **argv)
case 'r':
rnum = strtoul(optarg, NULL, 10);
break;
case 'R':
do_reset = 1;
break;
case 'h':
printf("cit -a<adapter> -d<device>\n");
exit(-1);
@@ -214,6 +249,11 @@ int main(int argc, char **argv)
if (optind < argc) {
printf("Warning: unused arguments\n");
}
if (do_reset) {
reset();
exit(0);
}
printf("adapter %d, device: %d\n", adapter, device);
memset(ts+8, 180, 0x5a);
pthread_create(&th, NULL, get_ts, NULL);

View File

@@ -30,7 +30,7 @@ char *Rolloff[8] = {
"rsvd",
};
void dump(const uint8_t *b, int l)
void dump(uint8_t *b, int l)
{
int i, j;
@@ -45,6 +45,15 @@ void dump(const uint8_t *b, int l)
}
}
void ldump(uint8_t *b, int l)
{
int i;
for (i = 0; i < l; i++)
printf("%02X", b[i]);
printf("\n");
}
void print_temp(struct mci_result *res)
{
printf("Die temperature = %u\n", res->sx8_bist.temperature);
@@ -344,17 +353,18 @@ int readreg(int dev, uint32_t reg, uint32_t link, uint32_t *val)
return 0;
}
void mci_firmware(int dev, uint32_t link)
void mci_firmware(int dev, uint32_t link, uint32_t base)
{
union {
uint32_t u[4];
char s[16];
} version;
readreg(dev, MIC_INTERFACE_VER , link, &version.u[0]);
readreg(dev, MIC_INTERFACE_VER + 4, link, &version.u[1]);
readreg(dev, MIC_INTERFACE_VER + 8, link, &version.u[2]);
readreg(dev, MIC_INTERFACE_VER + 12, link, &version.u[3]);
base += 0xf0;
readreg(dev, base , link, &version.u[0]);
readreg(dev, base + 4, link, &version.u[1]);
readreg(dev, base + 8, link, &version.u[2]);
readreg(dev, base + 12, link, &version.u[3]);
printf("MCI firmware: %s.%d\n", &version.s, version.s[15]);
}
@@ -368,7 +378,6 @@ int mci_info(int dev, uint32_t link, uint8_t demod)
.cmd.demod = demod
};
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
@@ -380,6 +389,35 @@ int mci_info(int dev, uint32_t link, uint8_t demod)
return ret;
}
void print_license(int dev, struct mci_result *res)
{
if (res->license.serial_number[0] == 0xff)
res->license.serial_number[0] = 0;
printf("SERNBR:%s\n", (char *) &res->license.serial_number);
printf("ID:");
ldump(res->license.ID, 8);
printf("LK:");
ldump(res->license.LK, 24);
}
int mci_license(int dev)
{
struct ddb_mci_msg msg = {
.link = 0,
.cmd.command = CMD_GET_SERIALNUMBER,
};
int ret;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
print_license(dev, &msg.res);
return ret;
}
static int get_id(int fd, int link, struct ddb_id *id)
{
struct ddb_reg ddbreg;
@@ -416,6 +454,8 @@ static int get_id(int fd, int link, struct ddb_id *id)
static char *id2name(uint16_t id)
{
switch (id) {
case 0x210:
return "FSM";
case 0x222:
return "MOD";
case 0x0009:
@@ -476,7 +516,7 @@ static int card_info(int ddbnum, int demod)
num = 4;
if (id.device == 0x0014)
num = 2;
mci_firmware(ddb, link);
mci_firmware(ddb, link, 0x600);
if (demod >= 0)
mci_info(ddb, link, demod);
else {
@@ -484,6 +524,14 @@ static int card_info(int ddbnum, int demod)
mci_info(ddb, link, i);
}
break;
case 0x0210:
if (!(id.hw & 0x01000000))
break;
mci_firmware(ddb, link, 0x300);
printf("VEN:DD01\n");
printf("DEV:0210\n");
mci_license(ddb);
break;
default:
break;
}

255
apps/ddlicense.c Normal file
View File

@@ -0,0 +1,255 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/types.h>
#include <getopt.h>
#include <ctype.h>
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"
static void dump(const uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
printf("%04x: ", j);
for (i = 0; i < 16; i++)
if (i + j < l)
printf("%02x ", b[i]);
else
printf(" ");
printf("\n");
}
}
static void ldump(FILE *f, uint8_t *b, int l)
{
int i;
for (i = 0; i < l; i++)
fprintf(f, "%02X", b[i]);
fprintf(f, "\n");
}
static int mci_get_license(int dev, uint8_t *ID, uint8_t *LK, uint8_t *SN)
{
struct ddb_mci_msg msg = {
.link = 0,
.cmd.command = CMD_GET_SERIALNUMBER,
};
int ret;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
dprintf(2, "Error: %d\n", ret, errno);
return ret;
}
if (msg.res.status != 0x00) {
dprintf(2, "MCI error: %02x, check firmware and license file.\n", msg.res.status);
return -1;
}
memcpy(ID, msg.res.license.ID, 8);
memcpy(LK, msg.res.license.LK, 24);
memcpy(SN, msg.res.license.serial_number, 24);
return 0;
}
static int mci_set_license(int dev, uint8_t *ID, uint8_t *LK)
{
struct ddb_mci_msg msg = {
.link = 0,
.cmd.command = CMD_IMPORT_LICENSE,
};
int ret;
memcpy(msg.cmd.license.ID, ID, 8);
memcpy(msg.cmd.license.LK, LK, 24);
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
if (msg.res.status != 0x00) {
dprintf(2, "MCI error: %02x, check firmware and license file.\n", msg.res.status);
return -1;
}
return ret;
}
static int GetHex(char* s, uint32_t nBytes, uint8_t *Buffer)
{
int i;
if( strlen(s) < (nBytes * 2) )
return -1;
for (i = 0; i < nBytes; i += 1) {
char d0, d1;
d0 = s[i*2];
if( !isxdigit(d0) ) return -1;
d1 = s[i*2+1];
if( !isxdigit(d1) ) return -1;
d0 = toupper(d0);
d1 = toupper(d1);
Buffer[i] =(uint8_t) ((d0 > '9' ? d0 - 'A' + 10 : d0 - '0') << 4) | ((d1 > '9' ? d1 - 'A' + 10 : d1 - '0'));
}
return (nBytes * 2);
}
static int get_id_lk(char *fn, uint8_t *ID, uint8_t *LK)
{
FILE *fin = fopen(fn, "r");
if (!fin) {
printf("License file not found\n");
return -1;
}
memset(ID, 0, 8);
memset(LK, 0xff, 24);
while (1) {
char s[128];
if (fgets(s, sizeof(s), fin) == NULL)
break;
if (strncmp(s,"ID:",3) == 0) {
if (GetHex(&s[3], 8, ID) < 0 )
return -1;
}
if (strncmp(s,"LK:",3) == 0) {
if (GetHex(&s[3],24, LK) < 0 )
return -1;
}
}
//dump(ID, 8);
//dump(LK, 24);
fclose(fin);
return 0;
}
static int get_license(int ddb, struct ddb_id *id, char *ename)
{
uint8_t ID[8], LK[24], SN[17];
int stat;
FILE *f = fopen(ename, "w+");
if (!f) {
dprintf(2, "Could not write to output file.\n");
return -1;
}
stat = mci_get_license(ddb, ID, LK, SN);
if (stat < 0) {
dprintf(2, "Could not read license.\n");
return stat;
}
if (SN[0] == 0xff)
SN[0] = 0;
fprintf(f, "VEN:%04X\n", id->vendor);
fprintf(f, "DEV:%04X\n", id->device);
fprintf(f, "SERNBR:%s\n", (char *) SN);
fprintf(f, "ID:");
ldump(f, ID, 8);
fprintf(f, "LK:");
ldump(f, LK, 24);
fclose(f);
return 0;
}
static int set_license(int ddb, char *iname)
{
uint8_t ID[8], LK[24];
int stat=0;
stat = get_id_lk(iname, ID, LK);
if (stat < 0)
return stat;
return mci_set_license(ddb, ID, LK);
}
static int get_set_license(int ddbnum, char *ename, char *iname)
{
int ddb, stat = 0;
char ddbname[80];
struct ddb_id id;
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
ddb = open(ddbname, O_RDWR);
if (ddb < 0) {
dprintf(2, "Error opening device %s\n", ddbname);
return -3;
}
if (ioctl(ddb, IOCTL_DDB_ID, &id) < 0) {
dprintf(2, "Unsupported device %s.\n", ddbname);
return -1;
}
if (id.device != 0x210) {
dprintf(2, "Unsupported device %s with ID %04x.\n", ddbname, id.device);
return -1;
}
if (ename)
stat = get_license(ddb, &id, ename);
if (iname)
stat = set_license(ddb, iname);
close(ddb);
return stat;
}
int main(int argc, char*argv[])
{
int fd = -1, all = 1, i, ret = 0;
char fn[128];
int32_t device = 0;
char *iname = 0, *ename = 0;
while (1) {
int cur_optind = optind ? optind : 1;
int option_index = 0;
int c;
static struct option long_options[] = {
{"device", required_argument, 0, 'd'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "ad:i:e:",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'd':
device = strtoul(optarg, NULL, 0);
break;
case 'a':
all = 1;
break;
case 'i':
iname = optarg;
break;
case 'e':
ename = optarg;
break;
default:
break;
}
}
if (optind < argc) {
printf("too many arguments\n");
exit(1);
}
if (!ename && !iname) {
dprintf(2, "Neither export nor import file name provided.\n");
return -1;
}
get_set_license(device, ename, iname);
return 0;
}

View File

@@ -24,12 +24,31 @@ struct mconf {
int set_output;
int set_channels;
int fd;
int chanset;
struct mci_command channels;
struct mci_command stream;
struct mci_command output;
};
void dump(uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
printf("%02x ", b[i]);
else
printf(" ");
printf(" | ");
for (i = 0; i < 16; i++)
if (i + j < l)
putchar((b[i] > 31 && b[i] < 127) ? b[i] : '.');
printf("\n");
}
}
void strim(char *s)
{
int l = strlen(s);
@@ -39,13 +58,15 @@ void strim(char *s)
s[l] = 0;
}
void parse(char *fname, char *sec, void *priv, void (*cb)(void *, char *, char *))
int parse(char *fname, char *sec, void *priv, void (*cb)(void *, char *, char *))
{
char line[256], csec[80], par[80], val[80], *p;
FILE *f;
if ((f = fopen(fname, "r")) == NULL)
return;
if ((f = fopen(fname, "r")) == NULL) {
dprintf(2, "Could not open %s\n", fname);
return -1;
}
while ((p = fgets(line, sizeof(line), f))) {
if (*p == '\r' || *p == '\n' || *p == '#')
continue;
@@ -75,6 +96,7 @@ void parse(char *fname, char *sec, void *priv, void (*cb)(void *, char *, char *
if (!strcmp(sec, csec) && cb)
cb(priv, NULL, NULL);
fclose(f);
return 0;
}
struct param_table_entry {
@@ -249,24 +271,6 @@ int parse_param(char *val, struct param_table_entry *table, int *value) {
return -1;
}
void dump(const uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
printf("%02x ", b[i]);
else
printf(" ");
printf(" | ");
for (i = 0; i < 16; i++)
if (i + j < l)
putchar((b[i] > 31 && b[i] < 127) ? b[i] : '.');
printf("\n");
}
}
int mci_cmd(int dev, struct mci_command *cmd)
{
int ret;
@@ -276,7 +280,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((const uint8_t *) &msg.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 %d (%s)\n", errno, strerror(errno));
@@ -301,7 +305,7 @@ struct mci_command msg_channels = {
.mod_channel = 0,
.mod_stream = 0,
.mod_setup_channels[0] = {
.flags = MOD_SETUP_FLAG_FIRST|MOD_SETUP_FLAG_LAST|MOD_SETUP_FLAG_VALID,
.flags = 0,
.standard = MOD_STANDARD_DVBT_8,
.num_channels = 25,
.frequency = 474000000,
@@ -371,23 +375,29 @@ void channels_cb(void *priv, char *par, char *val)
return;
}
if (!strcasecmp(par, "frequency")) {
mc->channels.mod_setup_channels[0].frequency = (uint32_t) (strtod(val, NULL) * 1000000.0);
printf("frequency = %u\n", mc->channels.mod_setup_channels[0].frequency);
} else if (!strcasecmp(par, "channels")) {
mc->channels.mod_setup_channels[0].num_channels = strtol(val, NULL, 10);
printf("channels = %u\n", mc->channels.mod_setup_channels[0].num_channels);
mc->chanset++;
if (mc->chanset > 3)
return;
mc->channels.mod_setup_channels[mc->chanset].frequency = (uint32_t) (strtod(val, NULL) * 1000000.0);
printf("frequency %u = %u\n", mc->chanset + 1, mc->channels.mod_setup_channels[mc->chanset].frequency);
} else
if (mc->chanset>=0 && mc->chanset < 4) {
if (!strcasecmp(par, "channels")) {
mc->channels.mod_setup_channels[mc->chanset].num_channels = strtol(val, NULL, 10);
printf("channels = %u\n", mc->channels.mod_setup_channels[mc->chanset].num_channels);
} else if (!strcasecmp(par, "standard")) {
if (!parse_param(val,mod_standard_table, &value))
mc->channels.mod_setup_channels[0].standard = value;
mc->channels.mod_setup_channels[mc->chanset].standard = value;
printf("standard = %u\n", value);
} else if (!strcasecmp(par, "offset")) {
mc->channels.mod_setup_channels[0].offset = (uint32_t) (strtod(val, NULL) * 1000000.0);
mc->channels.mod_setup_channels[mc->chanset].offset = (uint32_t) (strtod(val, NULL) * 1000000.0);
} else if (!strcasecmp(par, "bandwidth")) {
mc->channels.mod_setup_channels[0].bandwidth = (uint32_t) (strtod(val, NULL) * 1000000.0);
mc->channels.mod_setup_channels[0].offset =
mc->channels.mod_setup_channels[0].bandwidth / 2;
mc->channels.mod_setup_channels[mc->chanset].bandwidth = (uint32_t) (strtod(val, NULL) * 1000000.0);
mc->channels.mod_setup_channels[mc->chanset].offset =
mc->channels.mod_setup_channels[mc->chanset].bandwidth / 2;
} else
printf("invalid channels parameter: %s\n", par);
}
}
void streams_cb(void *priv, char *par, char *val)
@@ -462,7 +472,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((const uint8_t *)&res->license, sizeof(res->license));
//dump((const uint8_t *)&res->license, sizeof(res->license));
return ret;
}
@@ -471,7 +481,6 @@ int main(int argc, char*argv[])
int fd = -1;
char fn[128];
uint32_t device = 0;
uint32_t frequency = 0;
char *configname = "modulator.conf";
struct mconf mc;
@@ -479,7 +488,8 @@ int main(int argc, char*argv[])
mc.channels = msg_channels;
mc.stream = msg_stream;
mc.output = msg_output;
mc.chanset = -1;
while (1) {
int cur_optind = optind ? optind : 1;
int option_index = 0;
@@ -521,9 +531,14 @@ int main(int argc, char*argv[])
}
//mci_lic(fd);
mc.fd = fd;
parse(configname, "channels", (void *) &mc, channels_cb);
if (parse(configname, "channels", (void *) &mc, channels_cb))
exit(-1);
if (mc.set_channels) {
printf("setting channels.\n");
for (int i = 0; i <= mc.chanset; i++)
mc.channels.mod_setup_channels[i].flags = MOD_SETUP_FLAG_VALID;
mc.channels.mod_setup_channels[0].flags |= MOD_SETUP_FLAG_FIRST;
mc.channels.mod_setup_channels[mc.chanset].flags |= MOD_SETUP_FLAG_LAST;
printf("setting channels, %u groups.\n", mc.chanset + 1);
mci_cmd(fd, &mc.channels);
}
parse(configname, "streams", (void *) &mc, streams_cb);

View File

@@ -660,14 +660,15 @@ typedef struct dvb_devices_t {
} dvb_devices;
#define MAXNAME 128
static int check_tuner(int adapt)
{
char device[35];
char device[MAXNAME];
int front = 0;
int done = 0;
while (!done) {
snprintf(device,34,"/dev/dvb/adapter%d/frontend%d",adapt,front);
snprintf(device,MAXNAME-1,"/dev/dvb/adapter%d/frontend%d",adapt,front);
// fprintf(stderr,"Checking for %s\n", device);
if(access(device, F_OK) < 0)
done=1;
@@ -680,12 +681,12 @@ static int check_tuner(int adapt)
static int check_ca(int adapt)
{
char device[25];
char device[MAXNAME];
int ca = 0;
int done = 0;
while (!done) {
snprintf(device,24,"/dev/dvb/adapter%d/ci%d",adapt,ca);
snprintf(device,MAXNAME-1,"/dev/dvb/adapter%d/ci%d",adapt,ca);
if(access(device, F_OK) < 0)
done=1;
else {
@@ -697,12 +698,12 @@ static int check_ca(int adapt)
static int check_modulator(int adapt)
{
char device[25];
char device[MAXNAME];
int mod = 0;
int done = 0;
while (!done) {
snprintf(device,24,"/dev/dvb/adapter%d/mod%d",adapt,mod);
snprintf(device,MAXNAME-1,"/dev/dvb/adapter%d/mod%d",adapt,mod);
if(access(device, F_OK) < 0)
done=1;
else {

View File

@@ -13,6 +13,7 @@ power = 70.0
# channels are frequency slots to which a stream (mod0, mod1 ...) can be assigned
[channels]
# frequency of channel 0, following channels are spaced according to set standard
# frequency parameter has to come first!
frequency = 474.0
# numbers of channels to allocate, starting from frequency below
# this defines 16 channels at 474, 474+8, 474+16, etc. Mhz
@@ -20,6 +21,11 @@ channels = 16
# standard: 0 = generic, 1 = DVB-T 8MHz, 2 = DVB-T 7 MHz, 3 = DVB-T 6 MHz
standard = DVBC_8
frequency = 640.0
channels = 8
standard = DVBC_8
[streams]
# number of streams depends on the card hardware
# streams correspond to devices mod0, mod1, ...
@@ -29,7 +35,6 @@ standard = DVBC_8
stream_format = TS
symbol_rate = 6.9
modulation = qam_dvbc_256
rolloff = 13
channel = 0
stream = 0
@@ -52,7 +57,7 @@ stream = 5
channel = 6
stream = 6
symbol_rate = 6.5
modulation = qam_dvbc_64
#symbol_rate = 6.5
#modulation = qam_dvbc_64
channel = 7
stream = 7

View File

@@ -7,24 +7,24 @@ channels = 16
# unit of power in DBUV or DBM
unit = DBUV
# power output in units of above unit
power = 50.0
power = 90.0
# define channels:
# channels are frequency slots to which a stream (mod0, mod1 ...) can be assigned
[channels]
frequency = 474.0
# standard: 0 = generic, 1 = DVB-T 8MHz, 2 = DVB-T 7 MHz, 3 = DVB-T 6 MHz
standard = 1
standard = DVBT_8
# numbers of channels to allocate, starting from frequency below
# this defines 25 channels at 474, 474+8, 474+16, etc. Mhz
channels = 25
# frequency of channel 0, following channels are spaced according to set standard
frequency = 474.0
[streams]
stream_format = TS
standard = DVBT_8
# number of streams depends on the card hardware
# streams correspond to devices mod0, mod1, ...
# channels are defined above in channels section
@@ -33,6 +33,9 @@ frequency = 474.0
guard_interval = 0
# 0 = 2K, 1 = 8K (2K not yet supported)
fft_size = 1
puncture_rate = 7/8
constellation = qam64
cell_identifier = 0
# all following streams will be set according to the last set other parameters

View File

@@ -1,4 +1,4 @@
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX -DCONFIG_DVB_CXD2099 -DCONFIG_DVB_NET
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX -DCONFIG_DVB_CXD2099 -DCONFIG_DVB_NET -DCONFIG_DVB_TDA18271C2DD
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

View File

@@ -2034,6 +2034,7 @@ static int init_xo2_ci(struct ddb_port *port)
if (res < 0)
return res;
dev_info(dev->dev, "Port %d: version %u.%u\n", data[0], data[1]);
if (data[0] > 1) {
dev_info(dev->dev, "Port %d: invalid XO2 CI %02x\n",
port->nr, data[0]);
@@ -3334,6 +3335,8 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EFAULT;
if ((reg.reg & 0xfffffff) >= dev->regs_len)
return -EINVAL;
if (reg.reg & 3)
return -EINVAL;
reg.val = ddbreadl(dev, reg.reg);
if (copy_to_user(parg, &reg, sizeof(reg)))
return -EFAULT;
@@ -3347,6 +3350,8 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EFAULT;
if ((reg.reg & 0xfffffff) >= dev->regs_len)
return -EINVAL;
if (reg.reg & 3)
return -EINVAL;
ddbwritel(dev, reg.val, reg.reg);
break;
}
@@ -4070,7 +4075,7 @@ static struct class ddb_class = {
.devnode = ddb_devnode,
};
int ddb_class_create(void)
static int ddb_class_create(void)
{
ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops);
if (ddb_major < 0)
@@ -4080,7 +4085,7 @@ int ddb_class_create(void)
return 0;
}
void ddb_class_destroy(void)
static void ddb_class_destroy(void)
{
class_unregister(&ddb_class);
unregister_chrdev(ddb_major, DDB_NAME);
@@ -4213,32 +4218,9 @@ static void gtl_link_handler(void *priv)
(1 & ddbreadl(dev, regs)));
}
static void link_tasklet(unsigned long data)
{
struct ddb_link *link = (struct ddb_link *)data;
struct ddb *dev = link->dev;
u32 s, tag = DDB_LINK_TAG(link->nr);
u32 l = link->nr;
s = ddbreadl(dev, tag | INTERRUPT_STATUS);
dev_info(dev->dev, "gtl_irq %08x = %08x\n", tag | INTERRUPT_STATUS, s);
if (!s)
return;
ddbwritel(dev, s, tag | INTERRUPT_ACK);
LINK_IRQ_HANDLE(l, 0);
LINK_IRQ_HANDLE(l, 1);
LINK_IRQ_HANDLE(l, 2);
LINK_IRQ_HANDLE(l, 3);
LINK_IRQ_HANDLE(l, 24);
}
static void gtl_irq_handler(void *priv)
{
struct ddb_link *link = (struct ddb_link *)priv;
#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);
@@ -4250,7 +4232,6 @@ static void gtl_irq_handler(void *priv)
LINK_IRQ_HANDLE(l, 3);
LINK_IRQ_HANDLE(l, 24);
}
#endif
}
static int ddb_gtl_init_link(struct ddb *dev, u32 l)
@@ -4312,13 +4293,14 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l)
dev_info(dev->dev, "GTL %s\n", dev->link[l].info->name);
dev_info(dev->dev, "GTL HW %08x REGMAP %08x\n",
dev_info(dev->dev, "GTL HW %08x REGMAP %08x FW %u.%u\n",
dev->link[l].ids.hwid,
dev->link[l].ids.regmapid);
dev->link[l].ids.regmapid,
(dev->link[l].ids.hwid & 0xff0000) >> 16,
dev->link[l].ids.hwid & 0xffff);
dev_info(dev->dev, "GTL ID %08x\n",
ddbreadl(dev, DDB_LINK_TAG(l) | 8));
tasklet_init(&link->tasklet, link_tasklet, (unsigned long)link);
ddbwritel(dev, 0xffffffff, DDB_LINK_TAG(l) | INTERRUPT_ACK);
ddbwritel(dev, 0x0100000f, DDB_LINK_TAG(l) | INTERRUPT_ENABLE);
@@ -4469,9 +4451,20 @@ static int ddb_init_boards(struct ddb *dev)
((link->info->type == DDB_MOD) &&
(link->ids.revision == 1)))
mci_init(link);
}
else if (link->info->version == 17)
mci_init(link);
}
if (l)
continue;
if (dev->link[0].info->type == DDB_MOD &&
dev->link[0].info->version == 18) {
u32 lic = ddbreadl(dev, 0x260) >> 24;
if (lic == 16)
dev->link[0].info =
get_ddb_info(0xdd01, 0x0222, 0xdd01, 0x0002);
}
if (dev->link[0].info->type == DDB_MOD &&
dev->link[0].info->version == 2) {
u32 lic = ddbreadl(dev, 0x1c) & 7;

View File

@@ -624,6 +624,16 @@ static const struct ddb_info ddb_sdr_dvbt = {
.tempmon_irq = 8,
};
static const struct ddb_info ddb_sdr_dvbt_16 = {
.type = DDB_MOD,
.name = "Digital Devices DVBT",
.version = 18,
.regmap = &octopus_sdr_map,
.port_num = 16,
.temp_num = 1,
.tempmon_irq = 8,
};
static const struct ddb_info ddb_s2_48 = {
.type = DDB_OCTOPUS_MAX,
.name = "Digital Devices MAX S8 4/8",
@@ -923,6 +933,7 @@ static const struct ddb_device_id ddb_device_ids[] = {
DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv),
DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq),
DDB_DEVID(0x0222, 0x0001, ddb_sdr_dvbt),
DDB_DEVID(0x0222, 0x0002, ddb_sdr_dvbt_16), /* dummy entry ! */
DDB_DEVID(0x0223, 0x0001, ddb_sdr_iq2),
DDB_DEVID(0xffff, 0xffff, ddb_none),

View File

@@ -477,9 +477,11 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
static struct dvb_frontend_ops m4_ops = {
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C,
SYS_ISDBC, SYS_DVBC2,
SYS_DVBT, SYS_DVBT2, SYS_ISDBT,
SYS_DVBS, SYS_DVBS2, SYS_ISDBS, },
SYS_DVBC2, SYS_DVBT, SYS_DVBT2, SYS_DVBS, SYS_DVBS2,
#ifndef KERNEL_DVB_CORE
SYS_ISDBC, SYS_ISDBS, SYS_ISDBT,
#endif
},
.info = {
.name = "M4",
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
@@ -531,9 +533,11 @@ static struct mci_cfg ddb_max_m4_cfg = {
static struct dvb_frontend_ops m_ops = {
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C,
SYS_ISDBC,
SYS_DVBT, SYS_DVBT2, SYS_ISDBT,
SYS_DVBS, SYS_DVBS2, SYS_ISDBS, },
SYS_DVBT, SYS_DVBT2, SYS_DVBS, SYS_DVBS2,
#ifndef KERNEL_DVB_CORE
SYS_ISDBC, SYS_ISDBS, SYS_ISDBT,
#endif
},
.info = {
.name = "M_AS",
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
@@ -655,7 +659,7 @@ static struct mci_cfg *ddb_max_cfgs [] = {
struct dvb_frontend *ddb_mx_attach(struct ddb_input *input, int nr, int tuner, int type)
{
return ddb_mci_attach(input, ddb_max_cfgs[type], nr, tuner);
return ddb_mci_attach(input, ddb_max_cfgs[type & 3], nr, tuner);
}
EXPORT_SYMBOL(ddb_mx_attach);

View File

@@ -48,6 +48,11 @@ static int no_voltage;
module_param(no_voltage, int, 0444);
MODULE_PARM_DESC(no_voltage, "Do not enable voltage on LNBH (will also disable 22KHz tone).");
static u8 input_diseqc_sequence[6] = { 0x00 };
static int input_diseqc_sequence_length = 1;
module_param_array(input_diseqc_sequence, byte, &input_diseqc_sequence_length, 0444);
MODULE_PARM_DESC(input_diseqc_sequence, "DiSEqC sequence to select input. Last byte & 15 selects input.");
/* MAX LNB interface related functions */
static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
@@ -72,8 +77,7 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
static int max_set_input(struct dvb_frontend *fe, int in);
static int max_emulate_switch(struct dvb_frontend *fe,
u8 *cmd, u32 len)
static int max_emulate_switch(struct dvb_frontend *fe, u8 *cmd, u32 len)
{
int input;
@@ -107,6 +111,11 @@ static int max_send_master_cmd(struct dvb_frontend *fe,
if (!max_emulate_switch(fe, cmd->msg, cmd->msg_len))
return 0;
if (cmd->msg_len &&
cmd->msg_len == input_diseqc_sequence_length &&
!memcmp(cmd->msg, input_diseqc_sequence, cmd->msg_len - 1))
return max_set_input(fe, cmd->msg[cmd->msg_len - 1] & 0x0f);
if (dvb->diseqc_send_master_cmd)
dvb->diseqc_send_master_cmd(fe, cmd);
@@ -473,8 +482,9 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
cfg = mxl5xx;
cfg.fw_priv = link;
if (dev->link[0].info->type == DDB_OCTONET)
if (dev->link[0].info->type == DDB_OCTONET) {
;/*cfg.ts_clk = 69;*/
}
demod = input->nr;
tuner = demod & 3;

View File

@@ -210,9 +210,9 @@ int ddb_mci_cmd(struct mci *state,
}
int ddb_mci_cmd_raw(struct mci *state,
struct mci_command *command, u32 command_len,
struct mci_result *result, u32 result_len)
static int ddb_mci_cmd_raw(struct mci *state,
struct mci_command *command, u32 command_len,
struct mci_result *result, u32 result_len)
{
struct ddb_link *link = state->base->link;
int stat;

View File

@@ -452,18 +452,20 @@ int ddbridge_mod_output_start(struct ddb_output *output)
static int mod_write_max2871(struct ddb *dev, u32 val)
{
u32 retry = 100;
ddbwritel(dev, val, MAX2871_OUTDATA);
ddbwritel(dev, MAX2871_CONTROL_CE | MAX2871_CONTROL_WRITE,
MAX2871_CONTROL);
while (1) {
while (--retry) {
u32 ControlReg = ddbreadl(dev, MAX2871_CONTROL);
if (ControlReg == 0xFFFFFFFF)
return -EIO;
if ((ControlReg & MAX2871_CONTROL_WRITE) == 0)
break;
if ((ControlReg & MAX2871_CONTROL_WRITE) == 0)
return 0;
udelay(10);
}
return 0;
return -EIO;
}
static u32 max2871_fsm[6] = {
@@ -2155,7 +2157,6 @@ static int mod_init_3(struct ddb *dev, u32 Frequency)
return ret;
}
static int mod_init_sdr_iq(struct ddb *dev)
{
int streams = dev->link[0].info->port_num;
@@ -2172,7 +2173,6 @@ static int mod_init_sdr_iq(struct ddb *dev)
ddbwritel(dev, 0x01, 0x240);
//mod3_set_base_frequency(dev, 602000000);
dev->mod_base.frequency = 570000000;
for (i = 0; i < streams; i++) {
@@ -2191,39 +2191,35 @@ static int mod_init_sdr_iq(struct ddb *dev)
return ret;
}
static int mod_init_dvbt(struct ddb *dev)
{
int i;
dev->mod_base.frequency = 570000000;
for (i = 0; i < dev->link[0].info->port_num; i++)
dev->mod[i].port = &dev->port[i];
return 0;
}
int ddbridge_mod_init(struct ddb *dev)
{
dev_info(dev->dev, "Revision: %u\n", dev->link[0].ids.revision);
if (dev->link[0].ids.revision == 1) {
switch (dev->link[0].info->version) {
case 0:
case 1:
return mod_init_1(dev, 722000000);
case 2: /* FSM */
if ((dev->link[0].ids.hwid & 0xffffff) >= 9065)
return mod_init_2_1(dev, 114000000);
return mod_init_2(dev, 114000000);
case 16: /* PAL */
return mod_init_3(dev, 503250000);
case 17: /* raw IQ */
case 18: /* IQ+FFT */
return mod_init_sdr_iq(dev);
default:
return -1;
}
}
switch (dev->link[0].info->version) {
case 0:
case 1:
return mod_init_1(dev, 722000000);
case 2: /* FSM */
if (dev->link[0].ids.revision == 1) {
if ((dev->link[0].ids.hwid & 0xffffff) >= 9065)
return mod_init_2_1(dev, 114000000);
}
return mod_init_2(dev, 114000000);
case 16: /* PAL */
return mod_init_3(dev, 503250000);
case 17: /* raw IQ */
return mod_init_sdr_iq(dev);
case 18: /* IQ+FFT */
return mod_init_sdr_iq(dev);
case 18: /* IQ+FFT (DVB-T) */
return mod_init_dvbt(dev);
default:
return -1;
}

View File

@@ -559,7 +559,9 @@ static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
static int set_input(struct dvb_frontend *fe, int input)
{
struct sx8 *state = fe->demodulator_priv;
#ifndef KERNEL_DVB_CORE
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
#endif
if (input >= SX8_TUNER_NUM)
return -EINVAL;

View File

@@ -424,7 +424,6 @@ struct ddb_link {
spinlock_t lock; /* lock link access */
struct mutex flash_mutex; /* lock flash access */
struct ddb_lnb lnb;
struct tasklet_struct tasklet;
struct ddb_ids ids;
spinlock_t temp_lock; /* lock temp chip access */
@@ -537,7 +536,7 @@ struct DDMOD_FLASH {
int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len);
#define DDBRIDGE_VERSION "0.9.39"
#define DDBRIDGE_VERSION "0.9.40"
/* linked function prototypes */
@@ -581,5 +580,10 @@ struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr,
void (*handler)(void *), void *data);
struct dvb_frontend *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, int tuner);
struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner,
int (**fn_set_input)(struct dvb_frontend *fe, int input));
struct dvb_frontend *ddb_mx_attach(struct ddb_input *input, int nr, int tuner, int type);
int ddb_dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
int (*func)(struct file *file, unsigned int cmd, void *arg));
#endif

View File

@@ -24,7 +24,11 @@
#include "ddbridge.h"
#include "ddbridge-io.h"
#if (KERNEL_VERSION(6, 11, 0) > LINUX_VERSION_CODE)
static int __exit octonet_remove(struct platform_device *pdev)
#else
static void __exit octonet_remove(struct platform_device *pdev)
#endif
{
struct ddb *dev;
@@ -43,7 +47,9 @@ static int __exit octonet_remove(struct platform_device *pdev)
ddb_ports_release(dev);
ddb_unmap(dev);
platform_set_drvdata(pdev, 0);
#if (KERNEL_VERSION(6, 11, 0) > LINUX_VERSION_CODE)
return 0;
#endif
}
static int __init octonet_probe(struct platform_device *pdev)

View File

@@ -83,6 +83,7 @@ limit depends on # of channels active.
MODULATOR_INPUT_BITRATE:
THIS FEATURE ONLY WORKS FOR DVB-C MODULATORS
The modulator will ALWAY insert null packets if it
does not get enough data.
@@ -94,6 +95,21 @@ So, this property should be set last.
unit - 2^-32 Hz
FOR DVB-T MODULATORS THIS FEATURE DOES NOT WORK
You should write a steady stream of transport packets with the
rate given by the modulation. The easiest way to keep a steady rate
is to write as much as the device will receive until it blocks. In that
way you ensure that the device will not get an underrun of data and
you can use the acceptance rate as a guide for you input rate.
All you should do is to correct the PCR of your transport stream according
to the calculated packet rate and use a buffer that assures that you are
always ready to write as sson as the modulator device allows it.
E.g you have a circular output buffer that you fill to say 50% and than start
writing into the device in a seperate thread. You feed the output buffer
with you input TS and see that it does not underrun, you may need to insert
empty packets to do that. The output thread should always have enough data
to write to the device as soon as it no longer blocks.
Debugging features:

View File

@@ -1,6 +1,10 @@
MCI API for modulators:
Note:
Notes:
The API is not meant to be used directly but via the app/modconfig command.
Example config files for DVB-T and DVB-C are in apps/modulator.conf and
apps/modulator-c.conf, respectively.
stream - refers to one modulator slot which take a TS and modulates it
e.g. the FSM16 has 16 streams
@@ -9,6 +13,7 @@ channel - an actual frequency the stream is sent on
the FSM cards in default config have 96 channels at 114 MHz + X * 8 MHz (X=0-95)
MCI commands can be sent to modulators with the IOCTL_DDB_MCI_CMD:
#define IOCTL_DDB_MCI_CMD _IOWR(DDB_MAGIC, 0x0c, struct ddb_mci_msg)
@@ -124,6 +129,10 @@ frequency offset between channels depends on standard (e.g. 8MHz for DVBC_8)
offset/bandwidth: set offsets between channels and bandwidth by hand (not for FSM cards)
NOTE: After changing the channel setup you have to set the streams you want to use at least once
before you use them. Otherwise, they will not have the new channel frequency.
MOD_SETUP_OUTPUT:

View File

@@ -503,6 +503,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
if (fepriv->max_drift)
dev_warn_once(fe->dvb->device,
"Frontend requested software zigzag, but didn't set the frequency step size\n");
#endif

View File

@@ -167,17 +167,14 @@ int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int nonblocking)
memset(ctx, 0, sizeof(struct dvb_vb2_ctx));
q->type = DVB_BUF_TYPE_CAPTURE;
/**capture type*/
q->is_output = 0;
/**only mmap is supported currently*/
q->io_modes = VB2_MMAP;
q->drv_priv = ctx;
q->buf_struct_size = sizeof(struct dvb_buffer);
q->min_buffers_needed = 1;
q->min_queued_buffers = 1;
q->ops = &dvb_vb2_qops;
q->mem_ops = &vb2_vmalloc_memops;
q->buf_ops = &dvb_vb2_buf_ops;
q->num_buffers = 0;
ret = vb2_core_queue_init(q);
if (ret) {
ctx->state = DVB_VB2_STATE_NONE;
@@ -355,12 +352,13 @@ int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{
struct vb2_queue *q = &ctx->vb_q;
struct vb2_buffer *vb2 = vb2_get_buffer(q, b->index);
if (b->index >= q->num_buffers) {
dprintk(1, "[%s] buffer index out of range\n", ctx->name);
if (!vb2) {
dprintk(1, "[%s] invalid buffer index\n", ctx->name);
return -EINVAL;
}
vb2_core_querybuf(&ctx->vb_q, b->index, b);
vb2_core_querybuf(&ctx->vb_q, vb2, b);
dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
return 0;
}
@@ -370,7 +368,7 @@ int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp)
struct vb2_queue *q = &ctx->vb_q;
int ret;
ret = vb2_core_expbuf(&ctx->vb_q, &exp->fd, q->type, exp->index,
ret = vb2_core_expbuf(&ctx->vb_q, &exp->fd, q->type, q->bufs[exp->index],
0, exp->flags);
if (ret) {
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
@@ -385,13 +383,14 @@ int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp)
int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{
struct vb2_queue *q = &ctx->vb_q;
struct vb2_buffer *vb2 = vb2_get_buffer(q, b->index);
int ret;
if (b->index >= q->num_buffers) {
dprintk(1, "[%s] buffer index out of range\n", ctx->name);
if (!vb2) {
dprintk(1, "[%s] invalid buffer index\n", ctx->name);
return -EINVAL;
}
ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL);
ret = vb2_core_qbuf(&ctx->vb_q, vb2, b, NULL);
if (ret) {
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
b->index, ret);

View File

@@ -9,6 +9,7 @@ EXTRA_CFLAGS += -DCONFIG_DVB_STV6110x
EXTRA_CFLAGS += -DCONFIG_DVB_STV0367DD
#EXTRA_CFLAGS += -DCONFIG_DVB_TDA18212
EXTRA_CFLAGS += -DCONFIG_DVB_TDA18212DD
EXTRA_CFLAGS += -DCONFIG_DVB_TDA18271C2DD
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843
EXTRA_CFLAGS += -DCONFIG_DVB_STV6111
EXTRA_CFLAGS += -DCONFIG_DVB_STV0910

View File

@@ -62,16 +62,6 @@ static bool IsQAM(struct drxk_state *state)
state->m_OperationMode == OM_QAM_ITU_C;
}
bool IsA1WithPatchCode(struct drxk_state *state)
{
return state->m_DRXK_A1_PATCH_CODE;
}
bool IsA1WithRomCode(struct drxk_state *state)
{
return state->m_DRXK_A1_ROM_CODE;
}
#define NOA1ROM 0
#ifndef CHK_ERROR
@@ -492,7 +482,7 @@ static int WriteBlock(struct drxk_state *state, u32 Address,
#define DRXK_MAX_RETRIES_POWERUP 20
#endif
int PowerUpDevice(struct drxk_state *state)
static int PowerUpDevice(struct drxk_state *state)
{
int status;
u8 data = 0;

View File

@@ -39,7 +39,9 @@
#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include <asm/div64.h>
#if (KERNEL_VERSION(6, 12, 0) > LINUX_VERSION_CODE)
#include <asm/unaligned.h>
#endif
#include <media/dvb_frontend.h>
#include "mxl5xx.h"
@@ -823,7 +825,9 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
static int set_input(struct dvb_frontend *fe, int input)
{
struct mxl *state = fe->demodulator_priv;
#ifndef KERNEL_DVB_CORE
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
#endif
state->tuner = input;
#ifndef KERNEL_DVB_CORE

View File

@@ -1570,7 +1570,6 @@ static int ofdm_lock(struct stv_state *state)
if (!(OFDM_Status & 0x40))
return -1;
//printk("lock 1\n");
readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT);
FFTMode = (SYR_STAT & 0x0C) >> 2;
@@ -1609,9 +1608,9 @@ static int ofdm_lock(struct stv_state *state)
writereg(state, R367_TSGENERAL,tmp2 & ~0x01);
}
msleep(FECTimeOut);
if( (OFDM_Status & 0x98) != 0x98 )
if( (OFDM_Status & 0x98) != 0x98 ) {
;//return -1;
//printk("lock 2\n");
}
{
u8 Guard = (SYR_STAT & 0x03);

View File

@@ -118,6 +118,7 @@ struct stv {
enum fe_code_rate puncture_rate;
enum fe_stv0910_modcod modcod;
u8 pls;
enum dvbs2_fec_type fec_type;
u32 pilots;
enum fe_stv0910_roll_off fe_roll_off;
@@ -508,6 +509,7 @@ static int get_signal_parameters(struct stv *state)
if (state->receive_mode == RCVMODE_DVBS2) {
read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp);
state->pls = tmp & 0x7f;
state->modcod = (enum fe_stv0910_modcod)((tmp & 0x7c) >> 2);
state->pilots = (tmp & 0x01) != 0;
state->fec_type = (enum dvbs2_fec_type)((tmp & 0x02) >> 1);
@@ -1333,6 +1335,7 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
};
read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp);
mc = ((tmp & 0x7c) >> 2);
p->transmission_mode = tmp & 0x7f;
p->pilot = (tmp & 0x01) ? PILOT_ON : PILOT_OFF;
p->modulation = modcod2mod[mc];
p->fec_inner = modcod2fec[mc];

View File

@@ -32,6 +32,7 @@
#include <asm/div64.h>
#include <media/dvb_frontend.h>
#include "stv6111.h"
static inline u32 MulDiv32(u32 a, u32 b, u32 c)
{

View File

@@ -33,6 +33,7 @@
#include <asm/div64.h>
#include <media/dvb_frontend.h>
#include "tda18212dd.h"
#ifndef CHK_ERROR
#define CHK_ERROR(s) if ((status = s) < 0) break

View File

@@ -33,6 +33,7 @@
#include <asm/div64.h>
#include <media/dvb_frontend.h>
#include "tda18271c2dd.h"
struct SStandardParam {
s32 m_IFFrequency;

View File

@@ -1,6 +1,10 @@
#ifndef _TDA18271C2DD_H_
#define _TDA18271C2DD_H_
#if defined(CONFIG_DVB_TDA18271C2DD) || \
#include <linux/types.h>
#include <linux/i2c.h>
#if defined(CONFIG_DVB_TDA18271C2DD) || \
(defined(CONFIG_DVB_TDA18271C2DD_MODULE) \
&& defined(MODULE))
struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,

View File

@@ -21,19 +21,11 @@
#ifdef KERNEL_DVB_CORE
#define DVB_DEVICE_CI 0
#define DVB_DEVICE_MOD 6
#define DVB_DEVICE_NS 7
#define DVB_DEVICE_NSD 8
#define DVB_DEVICE_NS 6
#define DVB_DEVICE_NSD 7
#define DVB_DEVICE_MOD 8
#define SYS_DVBC2 19
#define ROLLOFF_15 4
#define ROLLOFF_10 5
#define ROLLOFF_5 6
#define FEC_1_4 13
#define FEC_1_3 14
#define APSK_64 14
#define APSK_128 15
#define APSK_256 16
#define APSK_128 21
#define APSK_256 22
#define APSK_256_L 23
#endif

View File

@@ -3,8 +3,11 @@ The libdddvb provides a userspace library to simplify tuning and
CI use. It detects DVB cards and their capabilities and selects
free frontends depending on a given delivery system.
Please note that the libdddvb library and the ddzap tool are
provided as examples and for testing purposes.
In order to install the libdddvb library you need the dvben50221.
In order to install the libdddvb library you need the libdvben50221.
On an Ubuntu and other Debian based system you can install it like this:

View File

@@ -1,6 +1,7 @@
#define _LARGEFILE64_SOURCE
#include "../include/linux/dvb/frontend.h"
#include "src/libdddvb.h"
#include "src/dvb_filter.h"
#include <stdio.h>
#include <string.h>
#include <getopt.h>
@@ -14,8 +15,7 @@
#include <math.h>
#include <time.h>
#include <inttypes.h>
#include "dvb_filter.h"
#include <errno.h>
char line_start[16] = "";
char line_end[16] = "\r";
@@ -304,7 +304,7 @@ static uint32_t root2gold(uint32_t root)
return 0xffffffff;
}
ssize_t rread(int fd, void *buf, size_t count)
ssize_t rread(int fd, uint8_t *buf, size_t count)
{
size_t len, todo=count;
@@ -328,35 +328,48 @@ static void decode(struct dddvb *dd, int fd)
uint8_t ts[188];
struct dvbf_pid pidf[16];
int pmt;
ssize_t len;
ssize_t len, len2;
uint32_t count = 0;
for (pmt = 0; pmt < numpmt; pmt++) {
dvbf_init_pid(&pidf[pmt], pmt_pid[pmt]);
do {
len=rread(fd,ts,188);
if (len < 0) {
if (len != 188) {
dprintf(2, "Error reading stream\n");
exit(-1);
}
write(fileno(stdout),ts,188);
if (ts[0] != 0x47)
dprintf(2, "Alignment error ts\n");
//write(fileno(stdout),ts,188);
}
while (proc_pidf(&pidf[pmt], ts)<=0);
dprintf(2, "PMT %u of %u\n", pmt, numpmt);
dump(stderr, pidf[pmt].buf, pidf[pmt].len);
//dump(stderr, pidf[pmt].buf, pidf[pmt].len);
pmts[pmt]=pidf[pmt].buf;
}
//sleep(10);
while (dddvb_ca_set_pmts(dd, ci, pmts) < 0)
sleep(1);
while (1) {
rread(fd, buf, sizeof(buf));
len = rread(fd, buf, sizeof(buf));
if (len < 0) {
dprintf(2, "Error reading stream\n");
dprintf(2, "Error reading stream %d\n", errno);
exit(-1);
}
dddvb_ca_write(dd, ci, buf, sizeof(buf));
dddvb_ca_read(dd, ci, buf, sizeof(buf));
write(fileno(stdout),buf, sizeof(buf));
if (buf[0] != 0x47) {
rread(fd, buf, 1);
continue;
}
len2 = dddvb_ca_write(dd, ci, buf, len);
if (len2 != len)
dprintf(2, "Written less to CI %d\n", len);
len = dddvb_ca_read(dd, ci, buf, len2);
if (len < 0)
continue;
len2 = write(fileno(stdout), buf, len);
if (len2 != len)
dprintf(2, "Written less to output %d\n", len);
}
}

View File

@@ -1,201 +0,0 @@
static inline uint16_t seclen(const uint8_t *buf)
{
return 3+((buf[1]&0x0f)<<8)+buf[2];
}
static inline uint16_t tspid(const uint8_t *buf)
{
return ((buf[1]&0x1f)<<8)+buf[2];
}
static inline int tspayload(const uint8_t *tsp)
{
if (!(tsp[3] & 0x10))
return 0;
if (tsp[3] & 0x20)
return (tsp[4] > 183) ? 0 : (183 - tsp[4]);
return 184;
}
static inline int tspaystart(const uint8_t *tsp)
{
if (!(tsp[3]&0x10))
return 188;
if (tsp[3]&0x20)
return (tsp[4] >= 184) ? 188 : tsp[4]+5;
return 4;
}
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 < len; i++)
crc = (crc << 8) ^ dvb_crc_table[((crc >> 24) ^ *data++) & 0xff];
return crc;
}
struct dvbf_pid {
uint16_t pid;
uint8_t cc;
uint16_t bufp;
uint16_t len;
uint8_t buf[4096];
};
static inline void pidf_reset(struct dvbf_pid *pidf)
{
pidf->bufp = pidf->len = 0;
}
void dvbf_init_pid(struct dvbf_pid *pidf, uint16_t pid)
{
pidf->pid = pid;
pidf->cc = 0xff;
pidf_reset(pidf);
}
static inline void write_secbuf(struct dvbf_pid *p, uint8_t *tsp, int n)
{
memcpy(p->buf+p->bufp, tsp, n);
p->bufp += n;
}
static inline int validcc(struct dvbf_pid *p, uint8_t *tsp)
{
uint8_t newcc;
int valid;
newcc = tsp[3] & 0x0f;
if (p->cc == 0xff)
valid=1;
else
valid = (((p->cc + 1) & 0x0f) == newcc) ? 1 : 0;
p->cc = newcc;
if (!valid)
pidf_reset(p);
return valid;
}
void dump(FILE *fp, uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%02x ", b[i]);
else
fprintf(fp, " ");
fprintf(fp, " | ");
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%c", (b[i] > 31 && b[i] < 127) ? b[i] : '.');
fprintf(fp, "\n");
}
}
static void pidf_section(struct dvbf_pid *p)
{
dump(stderr, p->buf, p->len);
}
static int proc_pidf(struct dvbf_pid *p, uint8_t *tsp)
{
int pusoff, todo, off;
if (tspid(tsp) != p->pid)
return 0;
if (!(tsp[3] & 0x10)) //no payload
return 0;
todo = (tsp[3] & 0x20) ? // AF?
((tsp[4] > 183) ? 0 : (183 - tsp[4])) :
184;
if (!todo)
return 0;
off = 188 - todo;
pusoff = (tsp[1] & 0x40) ? tsp[off++] : todo;
if (pusoff + off > 188)
goto error;
if (validcc(p, tsp) && pusoff && p->bufp) {
int rlen = pusoff;
if (p->len) {
if (p->bufp + rlen > p->len)
rlen = p->len - p->bufp;
} else
if (p->bufp + rlen > 4096)
rlen = 4096 - p->bufp;
write_secbuf(p, tsp + off, rlen);
if (!p->len && p->bufp >= 3 && (p->len = seclen(p->buf)) > 4096)
pidf_reset(p);
else
return 1;//pidf_section(p);
}
off += pusoff;
while ((todo = 188 - off) > 0 && tsp[off] != 0xff) {
pidf_reset(p);
if (todo < 3 || (p->len = seclen(tsp+off)) > todo) {
if (p->len > 4096)
goto error;
write_secbuf(p, tsp+off, todo);
off+=todo;
} else {
write_secbuf(p, tsp+off, p->len);
off+=p->len;
return 2;//pidf_section(p);
}
}
return 0;
error:
pidf_reset(p);
return -1;
}

View File

@@ -2,6 +2,7 @@
#include "dddvb.h"
#include "tools.h"
#include "debug.h"
#include "dvb_filter.h"
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
@@ -31,6 +32,23 @@
#define MMI_STATE_ENQ 2
#define MMI_STATE_MENU 3
void dump(FILE *fp, uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%02x ", b[i]);
else
fprintf(fp, " ");
fprintf(fp, " | ");
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%c", (b[i] > 31 && b[i] < 127) ? b[i] : '.');
fprintf(fp, "\n");
}
}
int set_nonblock(int fd)
{
@@ -166,24 +184,23 @@ static int handle_pmt(struct dvbca *ca, uint8_t *buf, int size)
#endif
#if 0
static void handle_tdt(struct dddvb_ca *ca)
{
struct section *section;
struct dvb_tdt_section *tdt;
uint8_t sec[4096];
uint8_t *sec=ca->dvbf_tdt.buf;
time_t dvb_time;
int len;
int len=ca->dvbf_tdt.len;
if (sec[0] != 0x70)
return;
dbgprintf(DEBUG_CA, "got tdt\n");
//dump(stderr, sec,len);
if (ca->stdcam == NULL)
return;
if (ca->stdcam->dvbtime == NULL)
return;
len = getsec(ca->input, 0x14, 0, 0x70, sec);
if (len < 0)
return;
dbgprintf(DEBUG_CA, "got tdt\n");
section = section_codec(sec, len);
if (section == NULL)
return;
@@ -196,7 +213,7 @@ static void handle_tdt(struct dddvb_ca *ca)
if (ca->stdcam->dvbtime)
ca->stdcam->dvbtime(ca->stdcam, dvb_time);
}
#endif
static int handle_pmts(struct dddvb_ca *ca)
{
@@ -253,24 +270,6 @@ static int handle_pmts(struct dddvb_ca *ca)
return 0;
}
void dump(FILE *fp, uint8_t *b, int l)
{
int i, j;
for (j = 0; j < l; j += 16, b += 16) {
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%02x ", b[i]);
else
fprintf(fp, " ");
fprintf(fp, " | ");
for (i = 0; i < 16; i++)
if (i + j < l)
fprintf(fp, "%c", (b[i] > 31 && b[i] < 127) ? b[i] : '.');
fprintf(fp, "\n");
}
}
static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
{
int listmgmt = CA_LIST_MANAGEMENT_ONLY;
@@ -303,6 +302,8 @@ static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
dbgprintf(DEBUG_CA, "section_ext_decode failed\n");;
continue;
}
//dump(stderr, (uint8_t *) section, len);
//dump(stderr, (uint8_t *) section_ext, len);
pmt = mpeg_pmt_section_codec(section_ext);
//pmt = (struct mpeg_pmt_section *) section_ext;
if (!pmt) {
@@ -310,7 +311,7 @@ static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
continue;
}
dbgprintf(DEBUG_CA, "PMT = %p section=%p\n", pmt, section);
//dbgprintf(DEBUG_CA, "PMT = %p section=%p\n", pmt, section);
ca->ca_pmt_version[i] = section_ext->version_number;
if (ca->sentpmt) {
@@ -334,7 +335,7 @@ static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
dbgprintf(DEBUG_CA, "Failed to format PMT\n");
return -1;
}
//dump(capmt, size);
//dump(stderr, capmt, size);
dbgprintf(DEBUG_CA, "set ca_pmt\n");
if (en50221_app_ca_pmt(ca->stdcam->ca_resource, ca->stdcam->ca_session_number, capmt, size)) {
dbgprintf(DEBUG_CA, "Failed to send PMT\n");
@@ -697,6 +698,7 @@ static int init_ca(struct dddvb *dd, int a, int f, int fd)
pthread_create(&ca->poll_pt, NULL, (void *) ci_poll, ca);
pthread_create(&ca->pt, NULL, (void *) handle_ci, ca);
dvbf_init_pid(&ca->dvbf_tdt, 0x14);
sprintf(fname, "/dev/dvb/adapter%d/ci%d", a, f);
ca->ci_wfd = open(fname, O_WRONLY);
@@ -708,7 +710,16 @@ static int init_ca(struct dddvb *dd, int a, int f, int fd)
int dddvb_ca_write(struct dddvb *dd, uint32_t nr, uint8_t *buf, uint32_t len)
{
struct dddvb_ca *ca = &dd->dvbca[nr];
uint32_t i;
if (len%188)
return -EINVAL;
for (i = 0; i < len; i+=188) {
if (proc_pidf(&ca->dvbf_tdt, buf+i)>0)
handle_tdt(ca);
}
return write(ca->ci_wfd, buf, len);
}

View File

@@ -13,6 +13,10 @@
#include <linux/dvb/net.h>
#include <libucsi/dvb/section.h>
#include <libucsi/mpeg/section.h>
#include <libucsi/section.h>
#include <libucsi/section_buf.h>
#include <libdvben50221/en50221_stdcam.h>
#define DDDVB_MAX_DVB_FE 256
@@ -92,6 +96,17 @@ struct dddvb_fe {
struct dddvb_status status;
};
struct dvbf_pid {
uint16_t pid;
uint8_t cc;
uint16_t bufp;
uint16_t len;
uint8_t buf[4096];
int (*cb) (struct dvbf_pid *);
void *cbd;
};
struct dddvb_ca {
struct dddvb *dd;
struct osstrm *stream;
@@ -128,6 +143,8 @@ struct dddvb_ca {
uint8_t mmi_buf[16];
int mmi_bufp;
int sock;
struct dvbf_pid dvbf_tdt;
};
struct dddvb {

View File

@@ -99,7 +99,15 @@ static int get_stat_num(int fd, uint32_t cmd, struct dtv_fe_stats *stats, int nu
return 0;
}
static int set_property_input(int fd, uint32_t input)
{
struct dvb_diseqc_master_cmd cmd = {.msg = {input}, .msg_len = 1};
if (ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &cmd) == -1)
perror("FE_DISEQC_SEND_MASTER_CMD for setting input failed");
return 0;
//return set_property(fd, DTV_INPUT, input);
}
static int set_fe_input(struct dddvb_fe *fe, uint32_t fr,
uint32_t sr, fe_delivery_system_t ds,
@@ -129,7 +137,7 @@ static int set_fe_input(struct dddvb_fe *fe, uint32_t fr,
return -1;
}
if (input != DDDVB_UNDEF)
set_property(fd, DTV_INPUT, input);
set_property_input(fd, 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]);
@@ -214,7 +222,7 @@ static int set_en50494(struct dddvb_fe *fe, uint32_t freq_khz, uint32_t sr,
(slot << 5) | ((sat & 0x3f) ? 0x10 : 0) | (band ? 4 : 0) | (hor ? 8 : 0);
cmd.msg[4] = t & 0xff;
set_property(fd, DTV_INPUT, input);
set_property_input(fd, input);
if (ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) == -1)
perror("FE_SET_TONE failed");
if (ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18) == -1)
@@ -253,7 +261,7 @@ static int set_en50607(struct dddvb_fe *fe, uint32_t freq_khz, uint32_t sr,
cmd.msg[2] = (t & 0xff);
cmd.msg[3] = ((sat & 0x3f) << 2) | (hor ? 2 : 0) | (band ? 1 : 0);
set_property(fd, DTV_INPUT, input);
set_property_input(fd, input);
if (ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) == -1)
perror("FE_SET_TONE failed");
if (ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18) == -1)
@@ -345,7 +353,7 @@ static int tune_sat(struct dddvb_fe *fe)
if (input != DDDVB_UNDEF) {
input = 3 & (input >> 6);
dbgprintf(DEBUG_DVB, "input = %u\n", input);
set_property(fe->fd, DTV_INPUT, input);
set_property_input(fe->fd, input);
}
if (fe->scif_type == 3)
set_vol_tone(fe->fd, fe->param.param[PARAM_POL], hi);
@@ -831,27 +839,6 @@ static int dddvb_fe_init(struct dddvb *dd, int a, int f, int fd)
fe->fnum = f;
fe->nr = dd->dvbfe_num;
dps.num = 1;
dps.props = dp;
dp[0].cmd = DTV_INPUT;
r = ioctl(fd, FE_GET_PROPERTY, &dps);
if (r < 0)
return -1;
#if 0
for (i = 0; i < dp[0].u.buffer.len; i++) {
fe->input[i] = dp[0].u.buffer.data[i];
//dbgprintf(DEBUG_DVB, "input prop %u = %u\n", i, fe->input[i]);
}
if (fe->input[3]) {
dd->has_feswitch = 1;
if (!dd->scif_type && !msmode) {
if (fe->input[2] >= fe->input[1]) {
fe->type = 0;
return -1;
}
}
}
#endif
if (fe->type & (1UL << SYS_DVBS2))
dd->dvbs2num++;
if (fe->type & (1UL << SYS_DVBT2))

121
lib/src/dvb_filter.h Normal file
View File

@@ -0,0 +1,121 @@
static inline uint16_t seclen(const uint8_t *buf)
{
return 3+((buf[1]&0x0f)<<8)+buf[2];
}
static inline uint16_t tspid(const uint8_t *buf)
{
return ((buf[1]&0x1f)<<8)+buf[2];
}
static inline int tspayload(const uint8_t *tsp)
{
if (!(tsp[3] & 0x10))
return 0;
if (tsp[3] & 0x20)
return (tsp[4] > 183) ? 0 : (183 - tsp[4]);
return 184;
}
static inline int tspaystart(const uint8_t *tsp)
{
if (!(tsp[3]&0x10))
return 188;
if (tsp[3]&0x20)
return (tsp[4] >= 184) ? 188 : tsp[4]+5;
return 4;
}
static inline void pidf_reset(struct dvbf_pid *pidf)
{
pidf->bufp = pidf->len = 0;
}
static inline void dvbf_init_pid(struct dvbf_pid *pidf, uint16_t pid)
{
pidf->pid = pid;
pidf->cc = 0xff;
pidf_reset(pidf);
}
static inline void write_secbuf(struct dvbf_pid *p, uint8_t *tsp, int n)
{
memcpy(p->buf+p->bufp, tsp, n);
p->bufp += n;
}
static inline int validcc(struct dvbf_pid *p, uint8_t *tsp)
{
uint8_t newcc;
int valid;
newcc = tsp[3] & 0x0f;
if (p->cc == 0xff)
valid=1;
else
valid = (((p->cc + 1) & 0x0f) == newcc) ? 1 : 0;
p->cc = newcc;
if (!valid)
pidf_reset(p);
return valid;
}
static int proc_pidf(struct dvbf_pid *p, uint8_t *tsp)
{
int pusoff, todo, off;
if (tspid(tsp) != p->pid)
return 0;
if (!(tsp[3] & 0x10)) //no payload
return 0;
todo = (tsp[3] & 0x20) ? // AF?
((tsp[4] > 183) ? 0 : (183 - tsp[4])) :
184;
if (!todo)
return 0;
off = 188 - todo;
pusoff = (tsp[1] & 0x40) ? tsp[off++] : todo;
if (pusoff + off > 188)
goto error;
if (validcc(p, tsp) && pusoff && p->bufp) {
int rlen = pusoff;
if (p->len) {
if (p->bufp + rlen > p->len)
rlen = p->len - p->bufp;
} else
if (p->bufp + rlen > 4096)
rlen = 4096 - p->bufp;
write_secbuf(p, tsp + off, rlen);
if (!p->len && p->bufp >= 3 && (p->len = seclen(p->buf)) > 4096)
pidf_reset(p);
else {
if (p->cb)
p->cb(p);
else
return 1;
}
}
off += pusoff;
while ((todo = 188 - off) > 0 && tsp[off] != 0xff) {
pidf_reset(p);
if (todo < 3 || (p->len = seclen(tsp+off)) > todo) {
if (p->len > 4096)
goto error;
write_secbuf(p, tsp+off, todo);
off+=todo;
} else {
write_secbuf(p, tsp+off, p->len);
off+=p->len;
if (p->cb)
p->cb(p);
else
return 2;
}
}
return 0;
error:
pidf_reset(p);
return -1;
}