mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2025-03-01 10:35:23 +00:00
Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0b54436695 | ||
|
a986a98b96 | ||
|
345c3b8e0d | ||
|
b172e83a4b | ||
|
5fef324ea0 | ||
|
63f693946c | ||
|
17b741b01d | ||
|
8e4379ef3e | ||
|
1022b26d7f | ||
|
59cbab6383 | ||
|
0fcd9563f1 | ||
|
cf64ad4b0e | ||
|
1c88e05931 | ||
|
11b8c21cb5 | ||
|
3cc98a4995 | ||
|
0c328cd989 | ||
|
ffbef1488e | ||
|
8badef38a7 | ||
|
5d47dbec26 | ||
|
0368446256 | ||
|
07d5675b06 | ||
|
ea8e877dca | ||
|
9ec5f40324 | ||
|
50e230b48d | ||
|
4197d9a59e | ||
|
62b0b57c5d | ||
|
fe63f1d0b8 | ||
|
dc384c70af | ||
|
4e0bf8b182 | ||
|
e7390e1cd8 | ||
|
d54905cc14 | ||
|
7779445112 | ||
|
3ba2128c4e | ||
|
8f2bf94b43 | ||
|
a927449610 | ||
|
3295328aa9 | ||
|
2b53b34350 | ||
|
a6f022941f | ||
|
da1594d424 | ||
|
32afa3e920 | ||
f8726493b1 |
3
Makefile
3
Makefile
@@ -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
|
||||
|
||||
|
27
README.md
27
README.md
@@ -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/ !
|
||||
|
@@ -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)
|
||||
|
||||
|
44
apps/cit.c
44
apps/cit.c
@@ -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);
|
||||
|
@@ -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
255
apps/ddlicense.c
Normal 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;
|
||||
}
|
@@ -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);
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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, ®, 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;
|
||||
|
@@ -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),
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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:
|
||||
|
@@ -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:
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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];
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#include "tda18271c2dd.h"
|
||||
|
||||
struct SStandardParam {
|
||||
s32 m_IFFrequency;
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
||||
|
39
lib/ddzap.c
39
lib/ddzap.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
201
lib/dvb_filter.h
201
lib/dvb_filter.h
@@ -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;
|
||||
}
|
71
lib/src/ca.c
71
lib/src/ca.c
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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
121
lib/src/dvb_filter.h
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user