mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2025-03-01 10:35:23 +00:00
Compare commits
128 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 | |||
525472b9f1 | |||
7423903c67 | |||
690289c338 | |||
09021aec73 | |||
a1c604f212 | |||
1124f00b34 | |||
70a119c0db | |||
123291b26e | |||
85f8f5d2bd | |||
4d0c806262 | |||
9e6e34b857 | |||
327cc09d34 | |||
adaeb94a54 | |||
570864a576 | |||
c681e4f24a | |||
0628769620 | |||
934c619bcb | |||
847b8611bd | |||
be74b9630f | |||
3d17ab8de5 | |||
b76aa3c0c2 | |||
ca9613d911 | |||
0daf0f79ae | |||
|
3884037c93 | ||
f23789e90c | |||
0c603bc421 | |||
f23648f938 | |||
d8f3d40352 | |||
de5051a85a | |||
d63916cba1 | |||
3ef783c393 | |||
cf7f19b8bc | |||
0ad8eff8af | |||
a0d4605ad8 | |||
948234d787 | |||
05718a5965 | |||
aedb0a1b64 | |||
76697f420f | |||
6c7a754004 | |||
bf85718376 | |||
5f8c0cb75a | |||
accad41c2c | |||
72181bd0ad | |||
100aa25176 | |||
73317671a3 | |||
f77d50e526 | |||
|
25c730789d | ||
|
775ddf72ef | ||
|
7b23c917d3 | ||
|
d91b2b7813 | ||
|
58c608ab30 | ||
|
8dc2fd062f | ||
|
33ed0ec27c | ||
|
1ca4a8cea5 | ||
|
bb1408a98a | ||
|
9af63d41f7 | ||
95d23821b7 | |||
059bfbb76e | |||
454bb63993 | |||
5b83e68887 | |||
fc043cc914 | |||
4d583fd5f4 | |||
2c75179530 | |||
|
a443c3e8de | ||
|
979cb7a237 | ||
|
c86cb59638 | ||
|
31589952a8 | ||
|
f125fd503c | ||
|
00b0036b33 | ||
|
83a6dc3a1d | ||
|
ab4b0c8306 | ||
|
e0539d5074 | ||
|
d0793274d2 | ||
|
fb4f263aa3 | ||
|
e9ccab3578 | ||
|
a5f3b75d0a | ||
|
f02b135bdb | ||
|
ec655e1438 | ||
|
81793729e6 | ||
|
8986494cd3 | ||
|
fbc39f71f4 | ||
|
ccc13aed48 | ||
|
0fe2c2feb3 | ||
|
4a93d1056a | ||
|
bfddf62f64 | ||
|
1d96274993 | ||
|
23bdd90595 |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -1,7 +1,3 @@
|
||||
#
|
||||
# Normal rules
|
||||
#
|
||||
|
||||
.*
|
||||
*.o
|
||||
*.o.*
|
||||
@@ -11,5 +7,9 @@
|
||||
*.so
|
||||
*.so.dbg
|
||||
*.orig
|
||||
*.mod.c
|
||||
*.ko
|
||||
*~
|
||||
\#*#
|
||||
\#*#
|
||||
Module.symvers
|
||||
modules.order
|
||||
|
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);
|
||||
@@ -285,7 +294,6 @@ void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res)
|
||||
else
|
||||
printf("Demod Locked: DVB-S2\n");
|
||||
printf("PLS-Code: %u\n", res->dvbs2_signal_info.pls_code);
|
||||
mci_bb(dev, link, demod);
|
||||
if (pls >= 250) {
|
||||
pilots = 1;
|
||||
modcod = S2Xrsvd[pls - 250];
|
||||
@@ -298,6 +306,8 @@ void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res)
|
||||
short_frame = pls & 2;
|
||||
modcod = S2ModCods[pls / 4];
|
||||
}
|
||||
printf("ModCod: %s\n", modcod);
|
||||
mci_bb(dev, link, demod);
|
||||
printf("Roll-Off: %s\n", Rolloff[res->dvbs2_signal_info.roll_off & 7]);
|
||||
printf("Pilots: %s\n", pilots ? "On" : "Off");
|
||||
printf("Frame: %s\n", short_frame ? "Short" : "Normal");
|
||||
@@ -343,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]);
|
||||
}
|
||||
@@ -367,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) {
|
||||
@@ -379,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;
|
||||
@@ -415,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:
|
||||
@@ -423,6 +464,8 @@ static char *id2name(uint16_t id)
|
||||
return "MAX SX8 Basic";
|
||||
case 0x000a:
|
||||
return "MAX M4";
|
||||
case 0x0014:
|
||||
return "MAX CI M2";
|
||||
default:
|
||||
return " ";
|
||||
}
|
||||
@@ -432,7 +475,7 @@ static int card_info(int ddbnum, int demod)
|
||||
{
|
||||
char ddbname[80];
|
||||
struct ddb_id ddbid;
|
||||
int ddb, ret, link, links = 1, i;
|
||||
int ddb, ret, link, links = 1, i, num=8;
|
||||
struct ddb_id id;
|
||||
|
||||
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
|
||||
@@ -465,24 +508,30 @@ static int card_info(int ddbnum, int demod)
|
||||
id.hw, id.regmap, (id.hw & 0xff0000) >> 16, (id.hw & 0xffff));
|
||||
switch (id.device) {
|
||||
case 0x0009:
|
||||
mci_firmware(ddb, link);
|
||||
if (demod >= 0)
|
||||
mci_info(ddb, link, demod);
|
||||
else {
|
||||
for (i = 0; i < 8; i++)
|
||||
mci_info(ddb, link, i);
|
||||
}
|
||||
case 0x000b:
|
||||
temp_info(ddb, link);
|
||||
break;
|
||||
case 0x000a:
|
||||
mci_firmware(ddb, link);
|
||||
case 0x0014:
|
||||
if (id.device == 0x000a)
|
||||
num = 4;
|
||||
if (id.device == 0x0014)
|
||||
num = 2;
|
||||
mci_firmware(ddb, link, 0x600);
|
||||
if (demod >= 0)
|
||||
mci_info(ddb, link, demod);
|
||||
else {
|
||||
for (i = 0; i < 4; i++)
|
||||
for (i = 0; i < num; i++)
|
||||
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);
|
||||
|
233
apps/modtest.c
233
apps/modtest.c
@@ -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 {
|
||||
@@ -866,7 +867,7 @@ int mci_set_output(int fd, uint8_t connector, uint8_t nchannels, uint8_t unit,
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr,"Setting DVBT Modulator output to %s, %d channels, power %f%s\n",
|
||||
fprintf(stderr,"Setting DVB Modulator output to %s, %d channels, power %f%s\n",
|
||||
con, nchannels, (double)power/100, un );
|
||||
|
||||
return mci_cmd(fd,&msg_output);
|
||||
@@ -934,19 +935,32 @@ int mci_set_channels(int fd, uint32_t freq, uint8_t nchan, uint8_t standard,
|
||||
snprintf(stand, 24, "MOD_STANDARD_DVBT_5");
|
||||
break;
|
||||
|
||||
case MOD_STANDARD_DVBC_8:
|
||||
snprintf(stand, 24, "MOD_STANDARD_DVBC_8");
|
||||
break;
|
||||
|
||||
case MOD_STANDARD_DVBC_7:
|
||||
snprintf(stand, 24, "MOD_STANDARD_DVBC_7");
|
||||
break;
|
||||
|
||||
case MOD_STANDARD_DVBC_6:
|
||||
snprintf(stand, 24, "MOD_STANDARD_DVBC_6");
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"unknown standard in channels setup\n");
|
||||
return -1;
|
||||
break;
|
||||
|
||||
}
|
||||
fprintf(stderr,"Setting DVBT Modulator channels to %d HZ, %d channels, %s\n",
|
||||
fprintf(stderr,"Setting DVB Modulator channels to %d HZ, %d channels, %s\n",
|
||||
freq, nchan, stand);
|
||||
|
||||
return mci_cmd(fd,&msg_channels);
|
||||
}
|
||||
|
||||
int mci_set_channels_simple(int adapt, uint32_t freq, uint8_t nchan)
|
||||
int mci_set_channels_simple(int adapt, enum fe_delivery_system delsys,
|
||||
uint32_t freq, uint8_t nchan)
|
||||
{
|
||||
|
||||
char fn[128];
|
||||
@@ -958,8 +972,18 @@ int mci_set_channels_simple(int adapt, uint32_t freq, uint8_t nchan)
|
||||
fprintf(stderr, "Could not open %s\n", fn);
|
||||
return -1;
|
||||
}
|
||||
switch(delsys){
|
||||
case SYS_DVBC_ANNEX_A:
|
||||
re = mci_set_channels(fd, freq, nchan, MOD_STANDARD_DVBC_8, 0, 0);
|
||||
break;
|
||||
|
||||
case SYS_DVBT:
|
||||
re = mci_set_channels(fd, freq, nchan, MOD_STANDARD_DVBT_8, 0, 0);
|
||||
break;
|
||||
|
||||
re = mci_set_channels(fd, freq, nchan, MOD_STANDARD_DVBT_8, 0, 0);
|
||||
default:
|
||||
re = -1;
|
||||
}
|
||||
close(fd);
|
||||
return re;
|
||||
}
|
||||
@@ -971,15 +995,11 @@ int mci_set_stream( int fd, uint8_t stream, uint8_t channel, uint8_t standard,
|
||||
uint8_t puncture_rate, uint8_t constellation,
|
||||
uint16_t cell_identifier)
|
||||
{
|
||||
struct mci_command msg_stream = {
|
||||
.mod_command = MOD_SETUP_STREAM,
|
||||
.mod_channel = 0,
|
||||
.mod_stream = 0,
|
||||
.mod_setup_stream = {
|
||||
.standard = MOD_STANDARD_DVBC_8,
|
||||
},
|
||||
};
|
||||
|
||||
struct mci_command msg_stream;
|
||||
|
||||
memset(&msg_stream,0,sizeof(msg_stream));
|
||||
|
||||
msg_stream.mod_command = MOD_SETUP_STREAM;
|
||||
msg_stream.mod_channel = channel;
|
||||
msg_stream.mod_stream = stream;
|
||||
msg_stream.mod_setup_stream.standard = standard;
|
||||
@@ -990,25 +1010,30 @@ int mci_set_stream( int fd, uint8_t stream, uint8_t channel, uint8_t standard,
|
||||
msg_stream.mod_setup_stream.qam.modulation = modulation;
|
||||
if (rolloff)
|
||||
msg_stream.mod_setup_stream.qam.rolloff = rolloff;
|
||||
msg_stream.mod_setup_stream.ofdm.fft_size = fft_size;
|
||||
msg_stream.mod_setup_stream.ofdm.guard_interval = guard_interval;
|
||||
msg_stream.mod_setup_stream.ofdm.puncture_rate = puncture_rate;
|
||||
msg_stream.mod_setup_stream.ofdm.constellation = constellation;
|
||||
if (fft_size)
|
||||
msg_stream.mod_setup_stream.ofdm.fft_size = fft_size;
|
||||
if (guard_interval)
|
||||
msg_stream.mod_setup_stream.ofdm.guard_interval = guard_interval;
|
||||
if (puncture_rate)
|
||||
msg_stream.mod_setup_stream.ofdm.puncture_rate = puncture_rate;
|
||||
if (constellation)
|
||||
msg_stream.mod_setup_stream.ofdm.constellation = constellation;
|
||||
if (cell_identifier)
|
||||
msg_stream.mod_setup_stream.ofdm.cell_identifier = cell_identifier;
|
||||
|
||||
fprintf(stderr,"Setting DVBT Stream %d to channel %d\n",stream, channel);
|
||||
|
||||
fprintf(stderr,"Setting DVB Stream %d to channel %d\n",stream, channel);
|
||||
|
||||
return mci_cmd(fd,&msg_stream);
|
||||
|
||||
}
|
||||
|
||||
void set_dvbt_mods(int adapt, int chans, uint32_t start_freq, write_data *wd)
|
||||
void set_dvb_mods(int adapt, int chans, uint32_t start_freq,
|
||||
enum fe_delivery_system delsys, write_data *wd)
|
||||
{
|
||||
if ((mci_set_output_simple(adapt, chans) < 0)||
|
||||
(mci_set_channels_simple(adapt, start_freq, chans)< 0))
|
||||
(mci_set_channels_simple(adapt, delsys, start_freq, chans)< 0))
|
||||
{
|
||||
fprintf(stderr,"Error setting up DVBT Modulator\n");
|
||||
fprintf(stderr,"Error setting up DVB Modulator\n");
|
||||
exit(1);
|
||||
}
|
||||
wd->chans = chans;
|
||||
@@ -1019,16 +1044,29 @@ void set_dvbt_mods(int adapt, int chans, uint32_t start_freq, write_data *wd)
|
||||
char *device;
|
||||
int fd;
|
||||
|
||||
wd->tp[i].tpid = 1; // all the same transport stream id
|
||||
wd->tp[i].delsys = SYS_DVBT;
|
||||
wd->tp[i].tpid = i;
|
||||
wd->tp[i].delsys = delsys;
|
||||
wd->tp[i].freq = start_freq+8000000*i;
|
||||
wd->tp[i].qam = 2;
|
||||
wd->tp[i].symbolrate = 0;
|
||||
wd->tp[i].bandwidth = 0;
|
||||
wd->tp[i].guard = 0;
|
||||
wd->tp[i].code_rate = 4;
|
||||
wd->tp[i].trans_mode = MOD_STANDARD_DVBT_8;
|
||||
|
||||
switch(delsys){
|
||||
case SYS_DVBT:
|
||||
wd->tp[i].qam = 2;
|
||||
wd->tp[i].symbolrate = 0;
|
||||
wd->tp[i].bandwidth = 0;
|
||||
wd->tp[i].guard = 0;
|
||||
wd->tp[i].code_rate = 4;
|
||||
wd->tp[i].trans_mode = MOD_STANDARD_DVBT_8;
|
||||
break;
|
||||
|
||||
case SYS_DVBC_ANNEX_A:
|
||||
wd->tp[i].qam = MOD_QAM_DVBC_256;
|
||||
wd->tp[i].symbolrate = 6900000;
|
||||
wd->tp[i].bandwidth = 0;
|
||||
wd->tp[i].guard = 0;
|
||||
wd->tp[i].code_rate = 0;
|
||||
wd->tp[i].trans_mode = 0;
|
||||
break;
|
||||
}
|
||||
device = malloc(sizeof(char)*40);
|
||||
snprintf(device,35,"/dev/dvb/adapter%d/mod%d",adapt,i);
|
||||
fd = open(device, O_RDWR);
|
||||
@@ -1038,106 +1076,29 @@ void set_dvbt_mods(int adapt, int chans, uint32_t start_freq, write_data *wd)
|
||||
free(device);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int re= 0;
|
||||
uint8_t stream_format = 4; //format is ransport stream
|
||||
uint8_t fft_size = wd->tp[i].trans_mode;
|
||||
|
||||
mci_set_stream( fd, i, i, MOD_STANDARD_DVBT_8, 4, 0, 0, 0, 1, 0, 4, 2, 0);
|
||||
close(fd);
|
||||
free(device);
|
||||
}
|
||||
}
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
//++++++++++++++++++++++++++++++++DVBC MOD++++++++++++++++++++++++++++++++
|
||||
|
||||
static int set_property(int fd, uint32_t cmd, uint32_t data)
|
||||
{
|
||||
struct dtv_property p;
|
||||
struct dtv_properties c;
|
||||
int ret;
|
||||
|
||||
p.cmd = cmd;
|
||||
c.num = 1;
|
||||
c.props = &p;
|
||||
p.u.data = data;
|
||||
ret = ioctl(fd, FE_SET_PROPERTY, &c);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "FE_SET_PROPERTY returned %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_input_bitrate(int fd, uint64_t data)
|
||||
{
|
||||
struct dtv_property p;
|
||||
struct dtv_properties c;
|
||||
int ret;
|
||||
|
||||
p.cmd = MODULATOR_INPUT_BITRATE;
|
||||
c.num = 1;
|
||||
c.props = &p;
|
||||
p.u.data64 = data;
|
||||
ret = ioctl(fd, FE_SET_PROPERTY, &c);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "FE_SET_PROPERTY returned %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_dvbc_mods(int adapt, int chans, uint32_t start_freq, write_data *wd)
|
||||
{
|
||||
uint32_t freq = start_freq;
|
||||
uint8_t qam = QAM_256;
|
||||
uint32_t sym = 6900000;
|
||||
|
||||
wd->chans = chans;
|
||||
wd->fd_out = (int *)malloc(chans*sizeof(int));
|
||||
memset(wd->fd_out,0,chans*sizeof(int));
|
||||
|
||||
for (int i = 0; i < chans; i++){
|
||||
char *device;
|
||||
int fd;
|
||||
|
||||
wd->tp[i].tpid = i;
|
||||
wd->tp[i].delsys = SYS_DVBC_ANNEX_A;
|
||||
wd->tp[i].freq = freq;
|
||||
wd->tp[i].qam = qam;
|
||||
wd->tp[i].symbolrate = sym;
|
||||
wd->tp[i].bandwidth = 0;
|
||||
wd->tp[i].guard = 0;
|
||||
wd->tp[i].code_rate = 0;
|
||||
wd->tp[i].trans_mode = 0;
|
||||
|
||||
device = malloc(sizeof(char)*40);
|
||||
snprintf(device,35,"/dev/dvb/adapter%d/mod%d",adapt,i);
|
||||
fd = open(device, O_RDWR);
|
||||
if( fd < 0 )
|
||||
{
|
||||
fprintf(stderr,"Error opening %s : %s\n",device,strerror(errno));
|
||||
free(device);
|
||||
exit(1);
|
||||
switch(delsys){
|
||||
case SYS_DVBC_ANNEX_A:
|
||||
re = mci_set_stream( fd, i, i, MOD_STANDARD_DVBC_8,
|
||||
stream_format, wd->tp[i].symbolrate,
|
||||
wd->tp[i].qam, 0, 0, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case SYS_DVBT:
|
||||
re = mci_set_stream( fd, i, i, MOD_STANDARD_DVBT_8,
|
||||
stream_format, 0, 0,
|
||||
0, fft_size, wd->tp[i].guard,
|
||||
wd->tp[i].code_rate, wd->tp[i].qam,
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
re = -1;
|
||||
}
|
||||
if (set_property(fd, MODULATOR_FREQUENCY, freq) < 0){
|
||||
fprintf(stderr,"setting freq %d failed\n",freq);
|
||||
exit(1);
|
||||
}
|
||||
if (set_property(fd, MODULATOR_MODULATION, qam) < 0){
|
||||
fprintf(stderr,"setting qam %d failed\n",qam);
|
||||
exit(1);
|
||||
}
|
||||
if (set_property(fd, MODULATOR_SYMBOL_RATE, sym) < 0){
|
||||
fprintf(stderr,"setting sym %d failed\n",sym);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (set_input_bitrate(fd, (DEFAULT_BIT_RATE_C << 32)) < 0){
|
||||
fprintf(stderr,"setting bitrate %d failed\n",
|
||||
(int)DEFAULT_BIT_RATE_C);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
freq += 8000000;
|
||||
if (re < 0) fprintf(stderr,"ERROR setting stream\n");
|
||||
close(fd);
|
||||
free(device);
|
||||
}
|
||||
@@ -1296,9 +1257,9 @@ int main(int argc, char **argv)
|
||||
chans = ddevices.ndevs[adapt];
|
||||
|
||||
if (dvbt){
|
||||
set_dvbt_mods(adapt, chans, start_freq, &wd);
|
||||
set_dvb_mods(adapt, chans, start_freq, SYS_DVBT, &wd);
|
||||
} else {
|
||||
set_dvbc_mods(adapt, chans, start_freq, &wd);
|
||||
set_dvb_mods(adapt, chans, start_freq, SYS_DVBC_ANNEX_A, &wd);
|
||||
}
|
||||
|
||||
fprintf(stderr,"Reading from %s\n", filename);
|
||||
|
63
apps/modulator-c.conf
Normal file
63
apps/modulator-c.conf
Normal file
@@ -0,0 +1,63 @@
|
||||
[output]
|
||||
# connector = OFF, SMA or F
|
||||
connector = F
|
||||
# number of total channels to be used at the same time
|
||||
# use lower number to have fewer channels but stronger signal per channel
|
||||
channels = 16
|
||||
# unit of power in DBUV or DBM
|
||||
unit = DBUV
|
||||
# power output in units of above unit
|
||||
power = 70.0
|
||||
|
||||
# define channels:
|
||||
# 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
|
||||
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, ...
|
||||
# channels are defined above in channels section
|
||||
|
||||
standard = DVBC_8
|
||||
stream_format = TS
|
||||
symbol_rate = 6.9
|
||||
modulation = qam_dvbc_256
|
||||
|
||||
channel = 0
|
||||
stream = 0
|
||||
|
||||
channel = 1
|
||||
stream = 1
|
||||
|
||||
channel = 2
|
||||
stream = 2
|
||||
|
||||
channel = 3
|
||||
stream = 3
|
||||
|
||||
channel = 4
|
||||
stream = 4
|
||||
|
||||
channel = 5
|
||||
stream = 5
|
||||
|
||||
channel = 6
|
||||
stream = 6
|
||||
|
||||
#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
|
||||
|
||||
|
@@ -45,14 +45,15 @@ static int read_attribute_mem(struct dvb_ca_en50221 *ca,
|
||||
int slot, int address)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1);
|
||||
u32 off = (address >> 1) & (CI_BUFFER_SIZE - 1);
|
||||
u8 val;
|
||||
|
||||
if (address > CI_BUFFER_SIZE)
|
||||
return -1;
|
||||
ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address,
|
||||
CI_DO_READ_ATTRIBUTES(ci));
|
||||
wait_ci_ready(ci);
|
||||
val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off);
|
||||
ddbcpyfrom(ci->port->dev, &val, CI_BUFFER(ci->nr) + off, 1);
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -110,7 +111,7 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
|
||||
CI_CONTROL(ci));
|
||||
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
|
||||
CI_CONTROL(ci));
|
||||
usleep_range(20, 25);
|
||||
msleep(20);
|
||||
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
|
||||
CI_CONTROL(ci));
|
||||
return 0;
|
||||
@@ -237,6 +238,8 @@ static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
struct ddb_ci *ci = ca->data;
|
||||
|
||||
write_creg(ci, 0x00, 0x01);
|
||||
msleep(300);
|
||||
write_creg(ci, 0x01, 0x01);
|
||||
write_creg(ci, 0x04, 0x04);
|
||||
msleep(300);
|
||||
|
@@ -61,7 +61,7 @@ static int raw_stream;
|
||||
module_param(raw_stream, int, 0444);
|
||||
MODULE_PARM_DESC(raw_stream, "send data as raw stream to DVB layer");
|
||||
|
||||
#ifdef __arm__
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
static int alt_dma = 1;
|
||||
#else
|
||||
static int alt_dma;
|
||||
@@ -69,6 +69,14 @@ static int alt_dma;
|
||||
module_param(alt_dma, int, 0444);
|
||||
MODULE_PARM_DESC(alt_dma, "use alternative DMA buffer handling");
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
static int use_workqueue = 1;
|
||||
#else
|
||||
static int use_workqueue;
|
||||
#endif
|
||||
module_param(use_workqueue, int, 0444);
|
||||
MODULE_PARM_DESC(use_workqueue, "use workqueue instead of tasklet");
|
||||
|
||||
static int no_init;
|
||||
module_param(no_init, int, 0444);
|
||||
MODULE_PARM_DESC(no_init, "do not initialize most devices");
|
||||
@@ -325,7 +333,7 @@ static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
|
||||
dma_unmap_single(&pdev->dev, dma->pbuf[i],
|
||||
dma->size,
|
||||
dir ? DMA_TO_DEVICE :
|
||||
DMA_FROM_DEVICE);
|
||||
DMA_BIDIRECTIONAL);
|
||||
kfree(dma->vbuf[i]);
|
||||
} else {
|
||||
dma_free_coherent(&pdev->dev, dma->size,
|
||||
@@ -356,7 +364,7 @@ static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
|
||||
dma->vbuf[i],
|
||||
dma->size,
|
||||
dir ? DMA_TO_DEVICE :
|
||||
DMA_FROM_DEVICE);
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (dma_mapping_error(&pdev->dev, dma->pbuf[i])) {
|
||||
kfree(dma->vbuf[i]);
|
||||
dma->vbuf[i] = 0;
|
||||
@@ -672,14 +680,10 @@ static void ddb_input_start_unlocked(struct ddb_input *input)
|
||||
ddbwritel(dev, 1, DMA_BASE_WRITE);
|
||||
ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma));
|
||||
}
|
||||
if (dev->link[0].info->type == DDB_OCTONET)
|
||||
ddbwritel(dev, 0x01, TS_CONTROL(input));
|
||||
else {
|
||||
if (raw_stream)
|
||||
ddbwritel(dev, 0x01 | ((raw_stream & 3) << 8), TS_CONTROL(input));
|
||||
else
|
||||
ddbwritel(dev, 0x01 | input->con, TS_CONTROL(input));
|
||||
}
|
||||
if (raw_stream)
|
||||
ddbwritel(dev, 0x01 | (raw_stream & 0x300), TS_CONTROL(input));
|
||||
else
|
||||
ddbwritel(dev, 0x01 | input->con, TS_CONTROL(input));
|
||||
if (input->port->type == DDB_TUNER_DUMMY)
|
||||
ddbwritel(dev, 0x000fff01, TS_CONTROL2(input));
|
||||
if (input->dma)
|
||||
@@ -799,6 +803,12 @@ static ssize_t ddb_output_write(struct ddb_output *output,
|
||||
}
|
||||
if (len > left)
|
||||
len = left;
|
||||
if (alt_dma)
|
||||
dma_sync_single_for_cpu(dev->dev,
|
||||
output->dma->pbuf[
|
||||
output->dma->cbuf],
|
||||
output->dma->size,
|
||||
DMA_TO_DEVICE);
|
||||
if (copy_from_user(output->dma->vbuf[output->dma->cbuf] +
|
||||
output->dma->coff,
|
||||
buf, len))
|
||||
@@ -869,6 +879,12 @@ static size_t ddb_input_read(struct ddb_input *input,
|
||||
DMA_FROM_DEVICE);
|
||||
ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] +
|
||||
input->dma->coff, free);
|
||||
if (alt_dma)
|
||||
dma_sync_single_for_device(dev->dev,
|
||||
input->dma->pbuf[
|
||||
input->dma->cbuf],
|
||||
input->dma->size,
|
||||
DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
input->dma->coff += free;
|
||||
@@ -958,12 +974,16 @@ static unsigned int ts_poll(struct file *file, poll_table *wait)
|
||||
|
||||
unsigned int mask = 0;
|
||||
|
||||
poll_wait(file, &input->dma->wq, wait);
|
||||
poll_wait(file, &output->dma->wq, wait);
|
||||
if (ddb_input_avail(input) >= 188)
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
if (ddb_output_free(output) >= 188)
|
||||
mask |= POLLOUT | POLLWRNORM;
|
||||
if (input && input->dma) {
|
||||
poll_wait(file, &input->dma->wq, wait);
|
||||
if (ddb_input_avail(input) >= 188)
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
}
|
||||
if (output && output->dma) {
|
||||
poll_wait(file, &output->dma->wq, wait);
|
||||
if (ddb_output_free(output) >= 188)
|
||||
mask |= POLLOUT | POLLWRNORM;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
@@ -990,8 +1010,11 @@ static int ts_open(struct inode *inode, struct file *file)
|
||||
int err;
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct ddb_output *output = dvbdev->priv;
|
||||
struct ddb_input *input = output->port->input[0];
|
||||
struct ddb_input *input;
|
||||
|
||||
if (!output)
|
||||
return -EINVAL;
|
||||
input = output->port->input[0];
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
||||
if (!input)
|
||||
return -EINVAL;
|
||||
@@ -1159,11 +1182,8 @@ static struct dvb_frontend_ops dummy_ops = {
|
||||
|
||||
static struct dvb_frontend *dummy_attach(void)
|
||||
{
|
||||
#if (KERNEL_VERSION(4, 13, 0) > LINUX_VERSION_CODE)
|
||||
struct dvb_frontend *fe = kmalloc(sizeof(*fe), __GFP_REPEAT);
|
||||
#else
|
||||
struct dvb_frontend *fe = kmalloc(sizeof(*fe), __GFP_RETRY_MAYFAIL);
|
||||
#endif
|
||||
struct dvb_frontend *fe = kzalloc(sizeof(*fe), GFP_KERNEL);
|
||||
|
||||
if (fe)
|
||||
fe->ops = dummy_ops;
|
||||
return fe;
|
||||
@@ -2014,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]);
|
||||
@@ -2419,7 +2440,9 @@ static void input_write_dvb(struct ddb_input *input,
|
||||
dma2->vbuf[dma->cbuf],
|
||||
dma2->size / 188);
|
||||
}
|
||||
|
||||
//if (alt_dma)
|
||||
// dma_sync_single_for_device(dev->dev, dma2->pbuf[dma->cbuf],
|
||||
// dma2->size, DMA_FROM_DEVICE);
|
||||
dma->cbuf = (dma->cbuf + 1) % dma2->num;
|
||||
if (ack)
|
||||
ddbwritel(dev, (dma->cbuf << 11),
|
||||
@@ -2429,18 +2452,13 @@ static void input_write_dvb(struct ddb_input *input,
|
||||
}
|
||||
}
|
||||
|
||||
static void input_tasklet(unsigned long data)
|
||||
static void input_proc(struct ddb_dma *dma)
|
||||
{
|
||||
struct ddb_dma *dma = (struct ddb_dma *)data;
|
||||
struct ddb_input *input = (struct ddb_input *)dma->io;
|
||||
struct ddb *dev = input->port->dev;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dma->lock, flags);
|
||||
if (!dma->running) {
|
||||
spin_unlock_irqrestore(&dma->lock, flags);
|
||||
if (!dma->running)
|
||||
return;
|
||||
}
|
||||
dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma));
|
||||
dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma));
|
||||
update_loss(dma);
|
||||
@@ -2451,83 +2469,64 @@ static void input_tasklet(unsigned long data)
|
||||
if (input->redo)
|
||||
input_write_output(input, input->redo);
|
||||
wake_up(&dma->wq);
|
||||
}
|
||||
|
||||
static void input_work(struct work_struct *work)
|
||||
{
|
||||
struct ddb_dma *dma = container_of(work, struct ddb_dma, work);
|
||||
|
||||
spin_lock_irq(&dma->lock);
|
||||
input_proc(dma);
|
||||
spin_unlock_irq(&dma->lock);
|
||||
}
|
||||
|
||||
static void input_tasklet(unsigned long data)
|
||||
{
|
||||
struct ddb_dma *dma = (struct ddb_dma *)data;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dma->lock, flags);
|
||||
input_proc(dma);
|
||||
spin_unlock_irqrestore(&dma->lock, flags);
|
||||
}
|
||||
|
||||
#ifdef OPTIMIZE_TASKLETS
|
||||
static void input_handler(unsigned long data)
|
||||
static void input_handler(void *data)
|
||||
{
|
||||
struct ddb_input *input = (struct ddb_input *)data;
|
||||
struct ddb_input *input = (struct ddb_input *) data;
|
||||
struct ddb_dma *dma = input->dma;
|
||||
|
||||
/* If there is no input connected, input_tasklet() will
|
||||
* just copy pointers and ACK. So, there is no need to go
|
||||
* through the tasklet scheduler.
|
||||
*/
|
||||
if (input->redi)
|
||||
tasklet_schedule(&dma->tasklet);
|
||||
else
|
||||
input_tasklet(data);
|
||||
if (!input->redi) {
|
||||
input_tasklet((unsigned long) dma);
|
||||
} else {
|
||||
if (use_workqueue)
|
||||
queue_work(ddb_wq, &dma->work);
|
||||
else
|
||||
tasklet_schedule(&dma->tasklet);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static void input_handler(void *data)
|
||||
static void output_handler(void *data)
|
||||
{
|
||||
struct ddb_input *input = (struct ddb_input *)data;
|
||||
struct ddb_dma *dma = input->dma;
|
||||
|
||||
input_tasklet((unsigned long)dma);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void output_tasklet(unsigned long data)
|
||||
{
|
||||
struct ddb_dma *dma = (struct ddb_dma *)data;
|
||||
struct ddb_output *output = (struct ddb_output *)dma->io;
|
||||
struct ddb_output *output = (struct ddb_output *)data;
|
||||
struct ddb_dma *dma = output->dma;
|
||||
struct ddb *dev = output->port->dev;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dma->lock, flags);
|
||||
if (!dma->running)
|
||||
goto unlock_exit;
|
||||
dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma));
|
||||
dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma));
|
||||
if (output->redi)
|
||||
output_ack_input(output, output->redi);
|
||||
wake_up(&dma->wq);
|
||||
unlock_exit:
|
||||
if (dma->running) {
|
||||
dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma));
|
||||
dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma));
|
||||
if (output->redi)
|
||||
output_ack_input(output, output->redi);
|
||||
wake_up(&dma->wq);
|
||||
}
|
||||
spin_unlock_irqrestore(&dma->lock, flags);
|
||||
}
|
||||
|
||||
#ifdef OPTIMIZE_TASKLETS
|
||||
static void output_handler(void *data)
|
||||
{
|
||||
struct ddb_output *output = (struct ddb_output *)data;
|
||||
struct ddb_dma *dma = output->dma;
|
||||
struct ddb *dev = output->port->dev;
|
||||
|
||||
spin_lock(&dma->lock);
|
||||
if (!dma->running) {
|
||||
spin_unlock(&dma->lock);
|
||||
return;
|
||||
}
|
||||
dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma));
|
||||
dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma));
|
||||
if (output->redi)
|
||||
output_ack_input(output, output->redi);
|
||||
wake_up(&dma->wq);
|
||||
spin_unlock(&dma->lock);
|
||||
}
|
||||
#else
|
||||
static void output_handler(void *data)
|
||||
{
|
||||
struct ddb_output *output = (struct ddb_output *)data;
|
||||
struct ddb_dma *dma = output->dma;
|
||||
|
||||
tasklet_schedule(&dma->tasklet);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -2555,7 +2554,6 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out, int irq_nr)
|
||||
spin_lock_init(&dma->lock);
|
||||
init_waitqueue_head(&dma->wq);
|
||||
if (out) {
|
||||
tasklet_init(&dma->tasklet, output_tasklet, (unsigned long)dma);
|
||||
dma->regs = rm->odma->base + rm->odma->size * nr;
|
||||
dma->bufregs = rm->odma_buf->base + rm->odma_buf->size * nr;
|
||||
if (io->port->dev->link[0].info->type == DDB_MOD &&
|
||||
@@ -2569,7 +2567,10 @@ static void ddb_dma_init(struct ddb_io *io, int nr, int out, int irq_nr)
|
||||
dma->div = 1;
|
||||
}
|
||||
} else {
|
||||
tasklet_init(&dma->tasklet, input_tasklet, (unsigned long)dma);
|
||||
if (use_workqueue)
|
||||
INIT_WORK(&dma->work, input_work);
|
||||
else
|
||||
tasklet_init(&dma->tasklet, input_tasklet, (unsigned long)dma);
|
||||
dma->regs = rm->idma->base + rm->idma->size * nr;
|
||||
dma->bufregs = rm->idma_buf->base + rm->idma_buf->size * nr;
|
||||
dma->num = dma_buf_num;
|
||||
@@ -2767,12 +2768,21 @@ void ddb_ports_release(struct ddb *dev)
|
||||
|
||||
for (i = 0; i < dev->port_num; i++) {
|
||||
port = &dev->port[i];
|
||||
if (port->input[0] && port->input[0]->dma)
|
||||
tasklet_kill(&port->input[0]->dma->tasklet);
|
||||
if (port->input[1] && port->input[1]->dma)
|
||||
tasklet_kill(&port->input[1]->dma->tasklet);
|
||||
if (port->output && port->output->dma)
|
||||
tasklet_kill(&port->output->dma->tasklet);
|
||||
if (use_workqueue) {
|
||||
if (port->input[0] && port->input[0]->dma)
|
||||
cancel_work_sync(&port->input[0]->dma->work);
|
||||
if (port->input[1] && port->input[1]->dma)
|
||||
cancel_work_sync(&port->input[1]->dma->work);
|
||||
//if (port->output && port->output->dma)
|
||||
// cancel_work_sync(&port->output->dma->work);
|
||||
} else {
|
||||
if (port->input[0] && port->input[0]->dma)
|
||||
tasklet_kill(&port->input[0]->dma->tasklet);
|
||||
if (port->input[1] && port->input[1]->dma)
|
||||
tasklet_kill(&port->input[1]->dma->tasklet);
|
||||
//if (port->output && port->output->dma)
|
||||
// tasklet_kill(&port->output->dma->tasklet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2874,9 +2884,8 @@ irqreturn_t ddb_irq_handler(int irq, void *dev_id)
|
||||
|
||||
if (s & 0x0000000f)
|
||||
irq_handle_msg(dev, s);
|
||||
if (s & 0x0fffff00) {
|
||||
if (s & 0x0fffff00)
|
||||
irq_handle_io(dev, s);
|
||||
}
|
||||
} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
|
||||
|
||||
return ret;
|
||||
@@ -3326,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;
|
||||
@@ -3339,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;
|
||||
}
|
||||
@@ -4062,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)
|
||||
@@ -4072,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);
|
||||
@@ -4205,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);
|
||||
|
||||
@@ -4242,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)
|
||||
@@ -4304,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);
|
||||
|
||||
@@ -4461,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;
|
||||
@@ -4613,7 +4614,7 @@ int ddb_init_ddbridge(void)
|
||||
|
||||
if (ddb_class_create() < 0)
|
||||
return -1;
|
||||
ddb_wq = alloc_workqueue("ddbridge", 0, 0);
|
||||
ddb_wq = alloc_workqueue("ddbridge", WQ_UNBOUND, 0);
|
||||
if (!ddb_wq)
|
||||
return ddb_exit_ddbridge(1, -1);
|
||||
return 0;
|
||||
|
@@ -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);
|
||||
|
@@ -388,7 +388,7 @@ fail:
|
||||
ddb_unmap(dev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
pci_disable_device(pdev);
|
||||
return -1;
|
||||
return stat;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
@@ -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)
|
||||
@@ -65,15 +70,14 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
|
||||
}
|
||||
if (c == 10)
|
||||
dev_info(dev->dev,
|
||||
"%s lnb = %08x cmd = %08x\n",
|
||||
__func__, lnb, cmd);
|
||||
"%s lnb = %08x cmd = %08x timed out\n",
|
||||
__func__, lnb, cmd | v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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,15 +482,20 @@ 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;
|
||||
if (fmode >= 3)
|
||||
tuner = 0;
|
||||
#ifdef CONFIG_MEDIA_ATTACH
|
||||
dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg,
|
||||
demod, tuner, &dvb->set_input);
|
||||
#else
|
||||
dvb->fe = mxl5xx_attach(i2c, &cfg, demod, tuner, &dvb->set_input);
|
||||
#endif
|
||||
if (!dvb->fe) {
|
||||
dev_err(dev->dev, "No MXL5XX found!\n");
|
||||
return -ENODEV;
|
||||
@@ -537,12 +551,15 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
|
||||
break;
|
||||
case DDB_TUNER_MCI_M8:
|
||||
fm = 3;
|
||||
dvb->fe = ddb_mx_attach(input, demod, tuner, 1);
|
||||
if (!demod)
|
||||
ddb_mci_cmd_link_simple(link, MCI_CMD_SET_INPUT_CONFIG,
|
||||
0xff, (delmode & 0x10) | 3);
|
||||
dvb->fe = ddb_mx_attach(input, demod, tuner, 3);
|
||||
dvb->input = 0;
|
||||
break;
|
||||
case DDB_TUNER_MCI_M8A:
|
||||
fm = 3;
|
||||
dvb->fe = ddb_mx_attach(input, demod, tuner, 2);
|
||||
dvb->fe = ddb_mx_attach(input, demod, tuner, 3);
|
||||
dvb->input = 0;
|
||||
break;
|
||||
case DDB_TUNER_MCI_M2:
|
||||
@@ -553,11 +570,11 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
|
||||
switch (delmode & 1) {
|
||||
case 0:
|
||||
mode = 2;
|
||||
mmode = 2;
|
||||
mmode = 2; /* M_S */
|
||||
break;
|
||||
case 1:
|
||||
mode = 1;
|
||||
mmode = demod ? 3 : 1;
|
||||
mmode = demod ? 3 : 1; /* demod 1=M/0=M_A */
|
||||
break;
|
||||
}
|
||||
if (!demod)
|
||||
|
@@ -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;
|
||||
@@ -310,7 +310,6 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
|
||||
p->symbol_rate =
|
||||
mci->signal_info.dvbs2_signal_info.symbol_rate;
|
||||
switch (p->delivery_system) {
|
||||
default:
|
||||
case SYS_DVBS:
|
||||
case SYS_DVBS2:
|
||||
{
|
||||
@@ -364,6 +363,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
|
||||
break;
|
||||
case SYS_ISDBT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* post is correct, we cannot provide both pre and post at the same time */
|
||||
/* set pre and post the same for now */
|
||||
|
@@ -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] = {
|
||||
@@ -574,10 +576,37 @@ static int mod_fsm_setup(struct ddb *dev, u32 MaxUsedChannels)
|
||||
return status;
|
||||
}
|
||||
|
||||
static int mod_set_power(struct ddb *dev)
|
||||
{
|
||||
struct ddb_link *link = &dev->link[0];
|
||||
struct mod_base *base = &dev->mod_base;
|
||||
struct mci_result res;
|
||||
struct mci_command cmd = {
|
||||
.mod_command = MOD_SETUP_OUTPUT,
|
||||
.mod_channel = 0,
|
||||
.mod_stream = 0,
|
||||
.mod_setup_output = {
|
||||
.connector = MOD_CONNECTOR_F,
|
||||
.num_channels = dev->link[0].info->port_num,
|
||||
.unit = MOD_UNIT_DBUV,
|
||||
.channel_power = 9000,
|
||||
},
|
||||
};
|
||||
if (!link->mci_ok)
|
||||
return -EFAULT;
|
||||
cmd.mod_setup_output.channel_power =
|
||||
8232 - base->attenuation * 1000 + base->gain * 12;
|
||||
return ddb_mci_cmd_link(link, &cmd, &res);
|
||||
}
|
||||
|
||||
static int mod_set_vga(struct ddb *dev, u32 gain)
|
||||
{
|
||||
if (gain > 255)
|
||||
return -EINVAL;
|
||||
if (dev->link[0].ids.revision == 1) {
|
||||
dev->mod_base.gain = gain;
|
||||
return mod_set_power(dev);
|
||||
}
|
||||
ddbwritel(dev, gain, RF_VGA);
|
||||
return 0;
|
||||
}
|
||||
@@ -686,23 +715,8 @@ static int mod_set_attenuator(struct ddb *dev, u32 Value)
|
||||
if (Value > 31)
|
||||
return -EINVAL;
|
||||
if (dev->link[0].ids.revision == 1) {
|
||||
struct ddb_link *link = &dev->link[0];
|
||||
struct mci_result res;
|
||||
struct mci_command cmd = {
|
||||
.mod_command = MOD_SETUP_OUTPUT,
|
||||
.mod_channel = 0,
|
||||
.mod_stream = 0,
|
||||
.mod_setup_output = {
|
||||
.connector = MOD_CONNECTOR_F,
|
||||
.num_channels = dev->link[0].info->port_num,
|
||||
.unit = MOD_UNIT_DBUV,
|
||||
.channel_power = 9000 - Value * 100,
|
||||
},
|
||||
};
|
||||
if (!link->mci_ok) {
|
||||
return -EFAULT;
|
||||
}
|
||||
return ddb_mci_cmd_link(link, &cmd, &res);
|
||||
dev->mod_base.attenuation = Value;
|
||||
return mod_set_power(dev);
|
||||
} else
|
||||
ddbwritel(dev, Value, RF_ATTENUATOR);
|
||||
return 0;
|
||||
@@ -1745,7 +1759,7 @@ static int mod_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
|
||||
if (mod->port->dev->link[0].info->version == 2)
|
||||
return mod_set_vga(mod->port->dev, tvp->u.data);
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
case MODULATOR_RESET:
|
||||
if (mod->port->dev->link[0].info->version == 2)
|
||||
return mod_fsm_setup(mod->port->dev,0 );
|
||||
@@ -1795,11 +1809,17 @@ static int mod_prop_get(struct ddb_mod *mod, struct dtv_property *tvp)
|
||||
return 0;
|
||||
|
||||
case MODULATOR_GAIN:
|
||||
tvp->u.data = 0xff & ddbreadl(dev, RF_VGA);
|
||||
if (dev->link[0].ids.revision == 1)
|
||||
tvp->u.data = dev->mod_base.gain;
|
||||
else
|
||||
tvp->u.data = 0xff & ddbreadl(dev, RF_VGA);
|
||||
return 0;
|
||||
|
||||
case MODULATOR_ATTENUATOR:
|
||||
tvp->u.data = 0x1f & ddbreadl(dev, RF_ATTENUATOR);
|
||||
if (dev->link[0].ids.revision == 1)
|
||||
tvp->u.data = dev->mod_base.attenuation;
|
||||
else
|
||||
tvp->u.data = 0x1f & ddbreadl(dev, RF_ATTENUATOR);
|
||||
return 0;
|
||||
|
||||
case MODULATOR_STATUS:
|
||||
@@ -1937,10 +1957,11 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
|
||||
(struct ddb_mci_msg __user *) parg;
|
||||
struct ddb_link *link;
|
||||
|
||||
if (dev->link[0].ids.revision != 1)
|
||||
if (dev->link[0].ids.revision != 1) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
||||
if (msg->link > 3) {
|
||||
}
|
||||
if (msg->link > 3) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
@@ -1965,6 +1986,10 @@ static int mod_init_2_1(struct ddb *dev, u32 Frequency)
|
||||
int i, streams = dev->link[0].info->port_num;
|
||||
|
||||
dev->mod_base.frequency = Frequency;
|
||||
dev->mod_base.gain = 64;
|
||||
dev->mod_base.attenuation = 0;
|
||||
mod_set_power(dev);
|
||||
|
||||
for (i = 0; i < streams; i++) {
|
||||
struct ddb_mod *mod = &dev->mod[i];
|
||||
mod->port = &dev->port[i];
|
||||
@@ -2132,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;
|
||||
@@ -2149,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++) {
|
||||
@@ -2164,42 +2187,39 @@ static int mod_init_sdr_iq(struct ddb *dev)
|
||||
mod_set_sdr_attenuator(dev, 0);
|
||||
udelay(10);
|
||||
mod_set_sdr_gain(dev, 120);
|
||||
ddb_mci_cmd_link_simple(&dev->link[0], 0xc0, 0x00, 90);
|
||||
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;
|
||||
}
|
||||
|
@@ -294,6 +294,7 @@
|
||||
|
||||
#define CI_CAM_READY (0x00010000)
|
||||
#define CI_CAM_DETECT (0x00020000)
|
||||
#define CI_POWER_ERROR (0x00100000)
|
||||
#define CI_READY (0x80000000)
|
||||
#define CI_BLOCKIO_ACTIVE (0x40000000)
|
||||
#define CI_BLOCKIO_RCVDATA (0x20000000)
|
||||
|
@@ -152,6 +152,7 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
if (stat)
|
||||
goto unlock;
|
||||
if (res.status == MCI_DEMOD_LOCKED || res.status == SX8_DEMOD_IQ_MODE) {
|
||||
//if (res.status == MCI_DEMOD_LOCKED || sx8_base->iq_mode) {
|
||||
*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI |
|
||||
FE_HAS_CARRIER | FE_HAS_SIGNAL;
|
||||
if (res.status == MCI_DEMOD_LOCKED) {
|
||||
@@ -171,8 +172,12 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
}
|
||||
} else if (res.status == MCI_DEMOD_TIMEOUT)
|
||||
*status = FE_TIMEDOUT;
|
||||
else if (res.status >= SX8_DEMOD_WAIT_MATYPE)
|
||||
else if (res.status >= SX8_DEMOD_WAIT_MATYPE) {
|
||||
*status = FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
|
||||
if (sx8_base->iq_mode)
|
||||
*status |= FE_HAS_LOCK;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&state->lock);
|
||||
return stat;
|
||||
@@ -385,6 +390,8 @@ unlock:
|
||||
cmd.dvbs2_search.s2_modulation_mask = modmask;
|
||||
cmd.dvbs2_search.rsvd1 = ro_lut[p->rolloff & 7];
|
||||
cmd.dvbs2_search.retry = 2;
|
||||
if (sx8_base->iq_mode)
|
||||
cmd.dvbs2_search.retry = 255;
|
||||
cmd.dvbs2_search.frequency = p->frequency * 1000;
|
||||
cmd.dvbs2_search.symbol_rate = p->symbol_rate;
|
||||
cmd.dvbs2_search.scrambling_sequence_index =
|
||||
@@ -552,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;
|
||||
|
@@ -202,6 +202,7 @@ struct ddb_dma {
|
||||
u32 div;
|
||||
u32 bufval;
|
||||
|
||||
struct work_struct work;
|
||||
struct tasklet_struct tasklet;
|
||||
spinlock_t lock; /* DMA lock */
|
||||
wait_queue_head_t wq;
|
||||
@@ -338,6 +339,8 @@ struct mod_base {
|
||||
u32 frequency;
|
||||
u32 flat_start;
|
||||
u32 flat_end;
|
||||
u32 attenuation;
|
||||
u32 gain;
|
||||
};
|
||||
|
||||
struct ddb_mod {
|
||||
@@ -421,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 */
|
||||
@@ -534,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.38"
|
||||
#define DDBRIDGE_VERSION "0.9.40"
|
||||
|
||||
/* linked function prototypes */
|
||||
|
||||
@@ -578,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:
|
||||
|
181
docs/modulator_mci_api
Normal file
181
docs/modulator_mci_api
Normal file
@@ -0,0 +1,181 @@
|
||||
MCI API for modulators:
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
with
|
||||
|
||||
struct ddb_mci_msg {
|
||||
__u32 link;
|
||||
struct mci_command cmd;
|
||||
struct mci_result res;
|
||||
};
|
||||
|
||||
link is always 0 for modulators.
|
||||
|
||||
mci_command with the entries relevant to modulators looks like this:
|
||||
|
||||
struct mci_command {
|
||||
union {
|
||||
u32 command_word;
|
||||
struct {
|
||||
u8 command;
|
||||
u8 tuner;
|
||||
u8 demod;
|
||||
u8 output;
|
||||
};
|
||||
struct {
|
||||
u8 mod_command;
|
||||
u8 mod_channel;
|
||||
u8 mod_stream;
|
||||
u8 mod_rsvd1;
|
||||
};
|
||||
};
|
||||
union {
|
||||
...
|
||||
struct mod_setup_channels mod_setup_channels[4];
|
||||
struct mod_setup_stream mod_setup_stream;
|
||||
struct mod_setup_output mod_setup_output;
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
mci_result like this:
|
||||
|
||||
struct mci_result {
|
||||
union {
|
||||
u32 status_word;
|
||||
struct {
|
||||
u8 status;
|
||||
u8 mode;
|
||||
u16 time;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
mci_command.command can be one of:
|
||||
|
||||
#define MOD_SETUP_CHANNELS (0x60)
|
||||
#define MOD_SETUP_OUTPUT (0x61)
|
||||
#define MOD_SETUP_STREAM (0x62)
|
||||
|
||||
which use the following corresponding structs in mci_command:
|
||||
|
||||
|
||||
|
||||
MOD_SETUP_CHANNELS:
|
||||
|
||||
mod_command = MOD_SETUP_CHANNELS
|
||||
mod_channel and mod_stream are not used
|
||||
|
||||
|
||||
struct mod_setup_channels {
|
||||
u8 flags;
|
||||
u8 standard;
|
||||
u8 num_channels;
|
||||
u8 rsvd;
|
||||
u32 frequency;
|
||||
u32 offset; /* used only when Standard == 0 */
|
||||
u32 bandwidth; /* used only when Standard == 0 */
|
||||
};
|
||||
|
||||
You can set up to 4 regions of channels.
|
||||
|
||||
flags:
|
||||
#define MOD_SETUP_FLAG_FIRST (0x01)
|
||||
#define MOD_SETUP_FLAG_LAST (0x02)
|
||||
#define MOD_SETUP_FLAG_VALID (0x80)
|
||||
|
||||
Set first/last if this is the first and/or last region you define.
|
||||
Set valid if you actually want to set it.
|
||||
|
||||
|
||||
standard:
|
||||
|
||||
see MOD_STANDARD_* defines in ddbridge-mci.h
|
||||
for FSM cards only MOD_STANDARD_DVBC_6/7/8 are relevant
|
||||
|
||||
|
||||
num_channels:
|
||||
|
||||
number of channels in this channel region
|
||||
|
||||
|
||||
frequency:
|
||||
|
||||
start frquency of this region
|
||||
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:
|
||||
|
||||
set mod_command to MOD_SETUP_OUTPUT
|
||||
mod_channel and mod_stream are not used
|
||||
|
||||
|
||||
struct mod_setup_output {
|
||||
u8 connector; /* 0 = OFF, 1 = F, 2 = SMA */
|
||||
u8 num_channels; /* max active channels, determines max power for each channel. */
|
||||
u8 unit; /* 0 = dBµV, 1 = dBm, */
|
||||
u8 rsvd;
|
||||
s16 channel_power;
|
||||
};
|
||||
|
||||
connector: use the F- or SMA-connector (the FSM cards only has F)
|
||||
|
||||
num_channels: how many channels will have actually have a stream using it (has to be less or equal to card stream capability)
|
||||
This influences internal multipliers. Setting it lower improves signal quality.
|
||||
|
||||
|
||||
unit: determines unit of channel_power (0 = dBµV, 1 = dBm)
|
||||
|
||||
channel_power: set channel power of output to X dBµV or dBm.
|
||||
|
||||
|
||||
|
||||
MOD_SETUP_STREAM:
|
||||
|
||||
|
||||
mod_command = MOD_SETUP_STREAM
|
||||
mod_stream = stream you want to configure
|
||||
mod_channel = channel the stream is to be sent on
|
||||
|
||||
|
||||
struct mod_setup_stream {
|
||||
u8 standard;
|
||||
u8 stream_format;
|
||||
u8 rsvd1[2];
|
||||
u32 symbol_rate; /* only used when Standard doesn't define a fixed symbol rate */
|
||||
union {
|
||||
struct mod_ofdm_parameter ofdm;
|
||||
struct mod_qam_parameter qam;
|
||||
};
|
||||
};
|
||||
|
@@ -6,7 +6,7 @@
|
||||
config DVB_MMAP
|
||||
bool "Enable DVB memory-mapped API (EXPERIMENTAL)"
|
||||
depends on DVB_CORE
|
||||
depends on VIDEO_V4L2=y || VIDEO_V4L2=DVB_CORE
|
||||
depends on VIDEO_DEV=y || VIDEO_DEV=DVB_CORE
|
||||
select VIDEOBUF2_VMALLOC
|
||||
help
|
||||
This option enables DVB experimental memory-mapped API, which
|
||||
|
@@ -6,8 +6,8 @@
|
||||
dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
|
||||
dvb-vb2-$(CONFIG_DVB_MMAP) := dvb_vb2.o
|
||||
|
||||
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
|
||||
dvb_ca_en50221.o dvb_frontend.o \
|
||||
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
|
||||
dvb_ca_en50221.o dvb_frontend.o \
|
||||
$(dvb-net-y) dvb_ringbuffer.o $(dvb-vb2-y) dvb_math.o
|
||||
|
||||
obj-$(CONFIG_DVB_CORE) += dvb-core.o
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
|
||||
|
||||
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
|
||||
dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
|
||||
dvb_ca_en50221.o dvb_frontend.o \
|
||||
$(dvb-net-y) dvb_ringbuffer.o dvb_math.o
|
||||
|
||||
|
@@ -158,6 +158,12 @@ struct dvb_ca_private {
|
||||
|
||||
/* mutex serializing ioctls */
|
||||
struct mutex ioctl_mutex;
|
||||
|
||||
/* A mutex used when a device is disconnected */
|
||||
struct mutex remove_mutex;
|
||||
|
||||
/* Whether the device is disconnected */
|
||||
int exit;
|
||||
};
|
||||
|
||||
static void dvb_ca_private_free(struct dvb_ca_private *ca)
|
||||
@@ -194,7 +200,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca);
|
||||
static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
|
||||
u8 *ebuf, int ecount);
|
||||
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
|
||||
u8 *ebuf, int ecount, u8 flags);
|
||||
u8 *ebuf, int ecount, int size_write_flag);
|
||||
|
||||
/**
|
||||
* findstr - Safely find needle in haystack.
|
||||
@@ -785,18 +791,19 @@ exit:
|
||||
* @buf: The data in this buffer is treated as a complete link-level packet to
|
||||
* be written.
|
||||
* @bytes_write: Size of ebuf.
|
||||
* @size_write_flag: A flag on Command Register which says whether the link size
|
||||
* information will be writen or not.
|
||||
*
|
||||
* return: Number of bytes written, or < 0 on error.
|
||||
*/
|
||||
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
|
||||
u8 *buf, int bytes_write, u8 flags)
|
||||
u8 *buf, int bytes_write, int size_write_flag)
|
||||
{
|
||||
struct dvb_ca_slot *sl = &ca->slot_info[slot];
|
||||
int status;
|
||||
int i;
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
flags=0;
|
||||
/* sanity check */
|
||||
if (bytes_write > sl->link_buf_size)
|
||||
return -EINVAL;
|
||||
@@ -824,7 +831,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
|
||||
|
||||
/* OK, set HC bit */
|
||||
status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
|
||||
IRQEN | CMDREG_HC | flags);
|
||||
IRQEN | CMDREG_HC | size_write_flag);
|
||||
if (status)
|
||||
goto exit;
|
||||
|
||||
@@ -894,7 +901,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
|
||||
buf[0], (buf[1] & 0x80) == 0, bytes_write);
|
||||
|
||||
exit:
|
||||
ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | flags);
|
||||
ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
|
||||
|
||||
exitnowrite:
|
||||
return status;
|
||||
@@ -1412,6 +1419,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file,
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
|
||||
slot = array_index_nospec(slot, ca->slot_count);
|
||||
#endif
|
||||
|
||||
info->type = CA_CI_LINK;
|
||||
info->flags = 0;
|
||||
sl = &ca->slot_info[slot];
|
||||
@@ -1490,6 +1498,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
|
||||
return -EFAULT;
|
||||
buf += 2;
|
||||
count -= 2;
|
||||
|
||||
if (slot >= ca->slot_count)
|
||||
return -EINVAL;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
|
||||
@@ -1734,12 +1743,22 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
if (!try_module_get(ca->pub->owner))
|
||||
mutex_lock(&ca->remove_mutex);
|
||||
|
||||
if (ca->exit) {
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!try_module_get(ca->pub->owner)) {
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = dvb_generic_open(inode, file);
|
||||
if (err < 0) {
|
||||
module_put(ca->pub->owner);
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1764,6 +1783,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
|
||||
|
||||
dvb_ca_private_get(ca);
|
||||
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1783,6 +1803,8 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
mutex_lock(&ca->remove_mutex);
|
||||
|
||||
/* mark the CA device as closed */
|
||||
ca->open = 0;
|
||||
dvb_ca_en50221_thread_update_delay(ca);
|
||||
@@ -1793,6 +1815,13 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
|
||||
|
||||
dvb_ca_private_put(ca);
|
||||
|
||||
if (dvbdev->users == 1 && ca->exit == 1) {
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
} else {
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1920,6 +1949,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
|
||||
}
|
||||
|
||||
mutex_init(&ca->ioctl_mutex);
|
||||
mutex_init(&ca->remove_mutex);
|
||||
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR;
|
||||
@@ -1962,6 +1992,14 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
mutex_lock(&ca->remove_mutex);
|
||||
ca->exit = 1;
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
|
||||
if (ca->dvbdev->users < 1)
|
||||
wait_event(ca->dvbdev->wait_queue,
|
||||
ca->dvbdev->users == 1);
|
||||
|
||||
/* shutdown the thread if there was one */
|
||||
kthread_stop(ca->thread);
|
||||
|
||||
|
@@ -128,12 +128,12 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
|
||||
|
||||
cc = buf[3] & 0x0f;
|
||||
ccok = ((feed->cc + 1) & 0x0f) == cc;
|
||||
feed->cc = cc;
|
||||
if (!ccok) {
|
||||
set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
|
||||
dprintk_sect_loss("missed packet: %d instead of %d!\n",
|
||||
cc, (feed->cc + 1) & 0x0f);
|
||||
}
|
||||
feed->cc = cc;
|
||||
|
||||
if (buf[1] & 0x40) // PUSI ?
|
||||
feed->peslen = 0xfffa;
|
||||
@@ -313,7 +313,6 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
|
||||
|
||||
cc = buf[3] & 0x0f;
|
||||
ccok = ((feed->cc + 1) & 0x0f) == cc;
|
||||
feed->cc = cc;
|
||||
|
||||
if (buf[3] & 0x20) {
|
||||
/* adaption field present, check for discontinuity_indicator */
|
||||
@@ -349,6 +348,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
|
||||
feed->pusi_seen = false;
|
||||
dvb_dmx_swfilter_section_new(feed);
|
||||
}
|
||||
feed->cc = cc;
|
||||
|
||||
if (buf[1] & 0x40) {
|
||||
/* PUSI=1 (is set), section boundary is here */
|
||||
|
@@ -1,603 +0,0 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include "dvb_filter.h"
|
||||
|
||||
#if 0
|
||||
static unsigned int bitrates[3][16] =
|
||||
{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
|
||||
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
|
||||
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
|
||||
#endif
|
||||
|
||||
static u32 freq[4] = {480, 441, 320, 0};
|
||||
|
||||
static unsigned int ac3_bitrates[32] =
|
||||
{32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
static u32 ac3_frames[3][32] =
|
||||
{{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
|
||||
1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
|
||||
1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
|
||||
1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
|
||||
void (*pes_write)(u8 *buf, int count, void *data),
|
||||
void *priv)
|
||||
{
|
||||
dvb_filter_ipack_init(pa, IPACKS, pes_write);
|
||||
dvb_filter_ipack_init(pv, IPACKS, pes_write);
|
||||
pa->pid = pida;
|
||||
pv->pid = pidv;
|
||||
pa->data = priv;
|
||||
pv->data = priv;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
|
||||
{
|
||||
u8 off = 0;
|
||||
|
||||
if (!buf || !p ){
|
||||
printk("NULL POINTER IDIOT\n");
|
||||
return;
|
||||
}
|
||||
if (buf[1]&PAY_START) {
|
||||
if (p->plength == MMAX_PLENGTH-6 && p->found>6){
|
||||
p->plength = p->found-6;
|
||||
p->found = 0;
|
||||
send_ipack(p);
|
||||
dvb_filter_ipack_reset(p);
|
||||
}
|
||||
}
|
||||
if (buf[3] & ADAPT_FIELD) { // adaptation field?
|
||||
off = buf[4] + 1;
|
||||
if (off+4 > 187) return;
|
||||
}
|
||||
dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* needs 5 byte input, returns picture coding type*/
|
||||
static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr)
|
||||
{
|
||||
u8 pct;
|
||||
|
||||
if (pr) printk( "Pic header: ");
|
||||
pic->temporal_reference[field] = (( headr[0] << 2 ) |
|
||||
(headr[1] & 0x03) )& 0x03ff;
|
||||
if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
|
||||
|
||||
pct = ( headr[1] >> 2 ) & 0x07;
|
||||
pic->picture_coding_type[field] = pct;
|
||||
if (pr) {
|
||||
switch(pct){
|
||||
case I_FRAME:
|
||||
printk( " I-FRAME");
|
||||
break;
|
||||
case B_FRAME:
|
||||
printk( " B-FRAME");
|
||||
break;
|
||||
case P_FRAME:
|
||||
printk( " P-FRAME");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) |
|
||||
( (headr[3] & 0x1F) << 11) ) & 0xffff;
|
||||
|
||||
if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
|
||||
|
||||
pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
|
||||
((headr[4] & 0x80) >> 3);
|
||||
|
||||
if ( pct == B_FRAME ){
|
||||
pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
|
||||
}
|
||||
if (pr) printk( " pic head param: 0x%x",
|
||||
pic->picture_header_parameter);
|
||||
|
||||
return pct;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* needs 4 byte input */
|
||||
static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
|
||||
{
|
||||
if (pr) printk("GOP header: ");
|
||||
|
||||
pic->time_code = (( headr[0] << 17 ) | ( headr[1] << 9) |
|
||||
( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff;
|
||||
|
||||
if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F,
|
||||
((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F),
|
||||
((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F));
|
||||
|
||||
if ( ( headr[3] & 0x40 ) != 0 ){
|
||||
pic->closed_gop = 1;
|
||||
} else {
|
||||
pic->closed_gop = 0;
|
||||
}
|
||||
if (pr) printk("closed: %d", pic->closed_gop);
|
||||
|
||||
if ( ( headr[3] & 0x20 ) != 0 ){
|
||||
pic->broken_link = 1;
|
||||
} else {
|
||||
pic->broken_link = 0;
|
||||
}
|
||||
if (pr) printk(" broken: %d\n", pic->broken_link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* needs 8 byte input */
|
||||
static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
|
||||
{
|
||||
int sw;
|
||||
int form = -1;
|
||||
|
||||
if (pr) printk("Reading sequence header\n");
|
||||
|
||||
vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
|
||||
vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]);
|
||||
|
||||
sw = (int)((headr[3]&0xF0) >> 4) ;
|
||||
|
||||
switch( sw ){
|
||||
case 1:
|
||||
if (pr)
|
||||
printk("Videostream: ASPECT: 1:1");
|
||||
vi->aspect_ratio = 100;
|
||||
break;
|
||||
case 2:
|
||||
if (pr)
|
||||
printk("Videostream: ASPECT: 4:3");
|
||||
vi->aspect_ratio = 133;
|
||||
break;
|
||||
case 3:
|
||||
if (pr)
|
||||
printk("Videostream: ASPECT: 16:9");
|
||||
vi->aspect_ratio = 177;
|
||||
break;
|
||||
case 4:
|
||||
if (pr)
|
||||
printk("Videostream: ASPECT: 2.21:1");
|
||||
vi->aspect_ratio = 221;
|
||||
break;
|
||||
|
||||
case 5 ... 15:
|
||||
if (pr)
|
||||
printk("Videostream: ASPECT: reserved");
|
||||
vi->aspect_ratio = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
vi->aspect_ratio = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pr)
|
||||
printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size);
|
||||
|
||||
sw = (int)(headr[3]&0x0F);
|
||||
|
||||
switch ( sw ) {
|
||||
case 1:
|
||||
if (pr)
|
||||
printk(" FRate: 23.976 fps");
|
||||
vi->framerate = 23976;
|
||||
form = -1;
|
||||
break;
|
||||
case 2:
|
||||
if (pr)
|
||||
printk(" FRate: 24 fps");
|
||||
vi->framerate = 24000;
|
||||
form = -1;
|
||||
break;
|
||||
case 3:
|
||||
if (pr)
|
||||
printk(" FRate: 25 fps");
|
||||
vi->framerate = 25000;
|
||||
form = VIDEO_MODE_PAL;
|
||||
break;
|
||||
case 4:
|
||||
if (pr)
|
||||
printk(" FRate: 29.97 fps");
|
||||
vi->framerate = 29970;
|
||||
form = VIDEO_MODE_NTSC;
|
||||
break;
|
||||
case 5:
|
||||
if (pr)
|
||||
printk(" FRate: 30 fps");
|
||||
vi->framerate = 30000;
|
||||
form = VIDEO_MODE_NTSC;
|
||||
break;
|
||||
case 6:
|
||||
if (pr)
|
||||
printk(" FRate: 50 fps");
|
||||
vi->framerate = 50000;
|
||||
form = VIDEO_MODE_PAL;
|
||||
break;
|
||||
case 7:
|
||||
if (pr)
|
||||
printk(" FRate: 60 fps");
|
||||
vi->framerate = 60000;
|
||||
form = VIDEO_MODE_NTSC;
|
||||
break;
|
||||
}
|
||||
|
||||
vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
|
||||
|
||||
vi->vbv_buffer_size
|
||||
= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
|
||||
|
||||
if (pr){
|
||||
printk(" BRate: %d Mbit/s",4*(vi->bit_rate)/10000);
|
||||
printk(" vbvbuffer %d",16*1024*(vi->vbv_buffer_size));
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
vi->video_format = form;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr)
|
||||
{
|
||||
u8 *headr;
|
||||
int found = 0;
|
||||
int c = 0;
|
||||
|
||||
while (found < 4 && c+4 < count){
|
||||
u8 *b;
|
||||
|
||||
b = mbuf+c;
|
||||
if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
|
||||
&& b[3] == 0xb3) found = 4;
|
||||
else {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
if (! found) return -1;
|
||||
c += 4;
|
||||
if (c+12 >= count) return -1;
|
||||
headr = mbuf+c;
|
||||
if (read_sequence_header(headr, vi, pr) < 0) return -1;
|
||||
vi->off = c-4;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
|
||||
{
|
||||
u8 *headr;
|
||||
int found = 0;
|
||||
int c = 0;
|
||||
int fr = 0;
|
||||
|
||||
while (found < 2 && c < count){
|
||||
u8 b[2];
|
||||
memcpy( b, mbuf+c, 2);
|
||||
|
||||
if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
|
||||
found = 2;
|
||||
else {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) return -1;
|
||||
|
||||
if (c+3 >= count) return -1;
|
||||
headr = mbuf+c;
|
||||
|
||||
ai->layer = (headr[1] & 0x06) >> 1;
|
||||
|
||||
if (pr)
|
||||
printk("Audiostream: Layer: %d", 4-ai->layer);
|
||||
|
||||
|
||||
ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
|
||||
|
||||
if (pr){
|
||||
if (ai->bit_rate == 0)
|
||||
printk(" Bit rate: free");
|
||||
else if (ai->bit_rate == 0xf)
|
||||
printk(" BRate: reserved");
|
||||
else
|
||||
printk(" BRate: %d kb/s", ai->bit_rate/1000);
|
||||
}
|
||||
|
||||
fr = (headr[2] & 0x0c ) >> 2;
|
||||
ai->frequency = freq[fr]*100;
|
||||
if (pr){
|
||||
if (ai->frequency == 3)
|
||||
printk(" Freq: reserved\n");
|
||||
else
|
||||
printk(" Freq: %d kHz\n",ai->frequency);
|
||||
|
||||
}
|
||||
ai->off = c;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
|
||||
{
|
||||
u8 *headr;
|
||||
int found = 0;
|
||||
int c = 0;
|
||||
u8 frame = 0;
|
||||
int fr = 0;
|
||||
|
||||
while ( !found && c < count){
|
||||
u8 *b = mbuf+c;
|
||||
|
||||
if ( b[0] == 0x0b && b[1] == 0x77 )
|
||||
found = 1;
|
||||
else {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) return -1;
|
||||
if (pr)
|
||||
printk("Audiostream: AC3");
|
||||
|
||||
ai->off = c;
|
||||
if (c+5 >= count) return -1;
|
||||
|
||||
ai->layer = 0; // 0 for AC3
|
||||
headr = mbuf+c+2;
|
||||
|
||||
frame = (headr[2]&0x3f);
|
||||
ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
|
||||
|
||||
if (pr)
|
||||
printk(" BRate: %d kb/s", (int) ai->bit_rate/1000);
|
||||
|
||||
ai->frequency = (headr[2] & 0xc0 ) >> 6;
|
||||
fr = (headr[2] & 0xc0 ) >> 6;
|
||||
ai->frequency = freq[fr]*100;
|
||||
if (pr) printk (" Freq: %d Hz\n", (int) ai->frequency);
|
||||
|
||||
|
||||
ai->framesize = ac3_frames[fr][frame >> 1];
|
||||
if ((frame & 1) && (fr == 1)) ai->framesize++;
|
||||
ai->framesize = ai->framesize << 1;
|
||||
if (pr) printk (" Framesize %d\n",(int) ai->framesize);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_filter_get_ac3info);
|
||||
|
||||
|
||||
#if 0
|
||||
static u8 *skip_pes_header(u8 **bufp)
|
||||
{
|
||||
u8 *inbuf = *bufp;
|
||||
u8 *buf = inbuf;
|
||||
u8 *pts = NULL;
|
||||
int skip = 0;
|
||||
|
||||
static const int mpeg1_skip_table[16] = {
|
||||
1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
|
||||
};
|
||||
|
||||
|
||||
if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
|
||||
if (buf[7] & PTS_ONLY)
|
||||
pts = buf+9;
|
||||
else pts = NULL;
|
||||
buf = inbuf + 9 + inbuf[8];
|
||||
} else { /* mpeg1 */
|
||||
for (buf = inbuf + 6; *buf == 0xff; buf++)
|
||||
if (buf == inbuf + 6 + 16) {
|
||||
break;
|
||||
}
|
||||
if ((*buf & 0xc0) == 0x40)
|
||||
buf += 2;
|
||||
skip = mpeg1_skip_table [*buf >> 4];
|
||||
if (skip == 5 || skip == 10) pts = buf;
|
||||
else pts = NULL;
|
||||
|
||||
buf += mpeg1_skip_table [*buf >> 4];
|
||||
}
|
||||
|
||||
*bufp = buf;
|
||||
return pts;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void initialize_quant_matrix( u32 *matrix )
|
||||
{
|
||||
int i;
|
||||
|
||||
matrix[0] = 0x08101013;
|
||||
matrix[1] = 0x10131616;
|
||||
matrix[2] = 0x16161616;
|
||||
matrix[3] = 0x1a181a1b;
|
||||
matrix[4] = 0x1b1b1a1a;
|
||||
matrix[5] = 0x1a1a1b1b;
|
||||
matrix[6] = 0x1b1d1d1d;
|
||||
matrix[7] = 0x2222221d;
|
||||
matrix[8] = 0x1d1d1b1b;
|
||||
matrix[9] = 0x1d1d2020;
|
||||
matrix[10] = 0x22222526;
|
||||
matrix[11] = 0x25232322;
|
||||
matrix[12] = 0x23262628;
|
||||
matrix[13] = 0x28283030;
|
||||
matrix[14] = 0x2e2e3838;
|
||||
matrix[15] = 0x3a454553;
|
||||
|
||||
for ( i = 16 ; i < 32 ; i++ )
|
||||
matrix[i] = 0x10101010;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void initialize_mpg_picture(struct mpg_picture *pic)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* set MPEG1 */
|
||||
pic->mpeg1_flag = 1;
|
||||
pic->profile_and_level = 0x4A ; /* MP@LL */
|
||||
pic->progressive_sequence = 1;
|
||||
pic->low_delay = 0;
|
||||
|
||||
pic->sequence_display_extension_flag = 0;
|
||||
for ( i = 0 ; i < 4 ; i++ ){
|
||||
pic->frame_centre_horizontal_offset[i] = 0;
|
||||
pic->frame_centre_vertical_offset[i] = 0;
|
||||
}
|
||||
pic->last_frame_centre_horizontal_offset = 0;
|
||||
pic->last_frame_centre_vertical_offset = 0;
|
||||
|
||||
pic->picture_display_extension_flag[0] = 0;
|
||||
pic->picture_display_extension_flag[1] = 0;
|
||||
pic->sequence_header_flag = 0;
|
||||
pic->gop_flag = 0;
|
||||
pic->sequence_end_flag = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic )
|
||||
{
|
||||
int16_t last_h_offset;
|
||||
int16_t last_v_offset;
|
||||
|
||||
int16_t *p_h_offset;
|
||||
int16_t *p_v_offset;
|
||||
|
||||
if ( pic->mpeg1_flag ){
|
||||
pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE;
|
||||
pic->top_field_first = 0;
|
||||
pic->repeat_first_field = 0;
|
||||
pic->progressive_frame = 1;
|
||||
pic->picture_coding_parameter = 0x000010;
|
||||
}
|
||||
|
||||
/* Reset flag */
|
||||
pic->picture_display_extension_flag[field_type] = 0;
|
||||
|
||||
last_h_offset = pic->last_frame_centre_horizontal_offset;
|
||||
last_v_offset = pic->last_frame_centre_vertical_offset;
|
||||
if ( field_type == FIRST_FIELD ){
|
||||
p_h_offset = pic->frame_centre_horizontal_offset;
|
||||
p_v_offset = pic->frame_centre_vertical_offset;
|
||||
*p_h_offset = last_h_offset;
|
||||
*(p_h_offset + 1) = last_h_offset;
|
||||
*(p_h_offset + 2) = last_h_offset;
|
||||
*p_v_offset = last_v_offset;
|
||||
*(p_v_offset + 1) = last_v_offset;
|
||||
*(p_v_offset + 2) = last_v_offset;
|
||||
} else {
|
||||
pic->frame_centre_horizontal_offset[3] = last_h_offset;
|
||||
pic->frame_centre_vertical_offset[3] = last_v_offset;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type)
|
||||
{
|
||||
pic->picture_header = 0;
|
||||
pic->sequence_header_data
|
||||
= ( INIT_HORIZONTAL_SIZE << 20 )
|
||||
| ( INIT_VERTICAL_SIZE << 8 )
|
||||
| ( INIT_ASPECT_RATIO << 4 )
|
||||
| ( INIT_FRAME_RATE );
|
||||
pic->mpeg1_flag = 0;
|
||||
pic->vinfo.horizontal_size
|
||||
= INIT_DISP_HORIZONTAL_SIZE;
|
||||
pic->vinfo.vertical_size
|
||||
= INIT_DISP_VERTICAL_SIZE;
|
||||
pic->picture_display_extension_flag[field_type]
|
||||
= 0;
|
||||
pic->pts_flag[field_type] = 0;
|
||||
|
||||
pic->sequence_gop_header = 0;
|
||||
pic->picture_header = 0;
|
||||
pic->sequence_header_flag = 0;
|
||||
pic->gop_flag = 0;
|
||||
pic->sequence_end_flag = 0;
|
||||
pic->sequence_display_extension_flag = 0;
|
||||
pic->last_frame_centre_horizontal_offset = 0;
|
||||
pic->last_frame_centre_vertical_offset = 0;
|
||||
pic->channel = chan;
|
||||
}
|
||||
#endif
|
||||
|
||||
void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
|
||||
dvb_filter_pes2ts_cb_t *cb, void *priv)
|
||||
{
|
||||
unsigned char *buf=p2ts->buf;
|
||||
|
||||
buf[0]=0x47;
|
||||
buf[1]=(pid>>8);
|
||||
buf[2]=pid&0xff;
|
||||
p2ts->cc=0;
|
||||
p2ts->cb=cb;
|
||||
p2ts->priv=priv;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_filter_pes2ts_init);
|
||||
|
||||
int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
|
||||
int len, int payload_start)
|
||||
{
|
||||
unsigned char *buf=p2ts->buf;
|
||||
int ret=0, rest;
|
||||
|
||||
//len=6+((pes[4]<<8)|pes[5]);
|
||||
|
||||
if (payload_start)
|
||||
buf[1]|=0x40;
|
||||
else
|
||||
buf[1]&=~0x40;
|
||||
while (len>=184) {
|
||||
buf[3]=0x10|((p2ts->cc++)&0x0f);
|
||||
memcpy(buf+4, pes, 184);
|
||||
if ((ret=p2ts->cb(p2ts->priv, buf)))
|
||||
return ret;
|
||||
len-=184; pes+=184;
|
||||
buf[1]&=~0x40;
|
||||
}
|
||||
if (!len)
|
||||
return 0;
|
||||
buf[3]=0x30|((p2ts->cc++)&0x0f);
|
||||
rest=183-len;
|
||||
if (rest) {
|
||||
buf[5]=0x00;
|
||||
if (rest-1)
|
||||
memset(buf+6, 0xff, rest-1);
|
||||
}
|
||||
buf[4]=rest;
|
||||
memcpy(buf+5+rest, pes, len);
|
||||
return p2ts->cb(p2ts->priv, buf);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_filter_pes2ts);
|
@@ -299,14 +299,28 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
|
||||
}
|
||||
|
||||
if (events->eventw == events->eventr) {
|
||||
int ret;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
|
||||
struct wait_queue_entry wait;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
if (flags & O_NONBLOCK)
|
||||
return -EWOULDBLOCK;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
|
||||
ret = wait_event_interruptible(events->wait_queue,
|
||||
dvb_frontend_test_event(fepriv, events));
|
||||
|
||||
#else
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&events->wait_queue, &wait);
|
||||
while (!dvb_frontend_test_event(fepriv, events)) {
|
||||
wait_woken(&wait, TASK_INTERRUPTIBLE, 0);
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
remove_wait_queue(&events->wait_queue, &wait);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -488,10 +502,11 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
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
|
||||
/* if we've got no parameters, just keep idling */
|
||||
if (fepriv->state & FESTATE_IDLE) {
|
||||
fepriv->delay = 3 * HZ;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/*
|
||||
* dvb-math provides some complex fixed-point math
|
||||
* operations shared between the dvb related stuff
|
||||
@@ -15,6 +16,7 @@
|
||||
* GNU Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#if (KERNEL_VERSION(6, 6, 0) > LINUX_VERSION_CODE)
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@@ -139,3 +141,6 @@ unsigned int intlog10(u32 value)
|
||||
return (log * 646456993) >> 31;
|
||||
}
|
||||
EXPORT_SYMBOL(intlog10);
|
||||
#else
|
||||
#include <linux/int_log.h>
|
||||
#endif
|
||||
|
@@ -665,7 +665,7 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
|
||||
h->ts_remain > 2 ?
|
||||
*(unsigned short *)h->from_where : 0);
|
||||
|
||||
#ifdef DVB_ULE_DEBUG
|
||||
#ifdef DVB_ULE_DEBUG
|
||||
hexdump(iov[0].iov_base, iov[0].iov_len);
|
||||
hexdump(iov[1].iov_base, iov[1].iov_len);
|
||||
hexdump(iov[2].iov_base, iov[2].iov_len);
|
||||
@@ -995,8 +995,8 @@ static void dvb_net_sec(struct net_device *dev,
|
||||
}
|
||||
|
||||
static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
const u8 *buffer2, size_t buffer2_len,
|
||||
struct dmx_section_filter *filter, u32 *buffer_flags)
|
||||
const u8 *buffer2, size_t buffer2_len,
|
||||
struct dmx_section_filter *filter, u32 *buffer_flags)
|
||||
{
|
||||
struct net_device *dev = filter->priv;
|
||||
|
||||
@@ -1290,6 +1290,7 @@ static int dvb_net_set_mac (struct net_device *dev, void *p)
|
||||
#else
|
||||
eth_hw_addr_set(dev, addr->sa_data);
|
||||
#endif
|
||||
|
||||
if (netif_running(dev))
|
||||
schedule_work(&priv->restart_net_feed_wq);
|
||||
|
||||
@@ -1589,15 +1590,43 @@ static long dvb_net_ioctl(struct file *file,
|
||||
return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
|
||||
}
|
||||
|
||||
static int locked_dvb_net_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct dvb_net *dvbnet = dvbdev->priv;
|
||||
int ret;
|
||||
|
||||
if (mutex_lock_interruptible(&dvbnet->remove_mutex))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (dvbnet->exit) {
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = dvb_generic_open(inode, file);
|
||||
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dvb_net_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct dvb_net *dvbnet = dvbdev->priv;
|
||||
|
||||
mutex_lock(&dvbnet->remove_mutex);
|
||||
|
||||
dvb_generic_release(inode, file);
|
||||
|
||||
if(dvbdev->users == 1 && dvbnet->exit == 1)
|
||||
if (dvbdev->users == 1 && dvbnet->exit == 1) {
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
} else {
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1605,7 +1634,7 @@ static int dvb_net_close(struct inode *inode, struct file *file)
|
||||
static const struct file_operations dvb_net_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = dvb_net_ioctl,
|
||||
.open = dvb_generic_open,
|
||||
.open = locked_dvb_net_open,
|
||||
.release = dvb_net_close,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
@@ -1624,10 +1653,13 @@ void dvb_net_release (struct dvb_net *dvbnet)
|
||||
{
|
||||
int i;
|
||||
|
||||
mutex_lock(&dvbnet->remove_mutex);
|
||||
dvbnet->exit = 1;
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
|
||||
if (dvbnet->dvbdev->users < 1)
|
||||
wait_event(dvbnet->dvbdev->wait_queue,
|
||||
dvbnet->dvbdev->users==1);
|
||||
dvbnet->dvbdev->users == 1);
|
||||
|
||||
dvb_unregister_device(dvbnet->dvbdev);
|
||||
|
||||
@@ -1646,6 +1678,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
|
||||
int i;
|
||||
|
||||
mutex_init(&dvbnet->ioctl_mutex);
|
||||
mutex_init(&dvbnet->remove_mutex);
|
||||
dvbnet->demux = dmx;
|
||||
|
||||
for (i=0; i<DVB_NET_DEVICES_MAX; i++)
|
||||
|
@@ -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);
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#endif
|
||||
|
||||
static DEFINE_MUTEX(dvbdev_mutex);
|
||||
static LIST_HEAD(dvbdevfops_list);
|
||||
static int dvbdev_debug;
|
||||
|
||||
module_param(dvbdev_debug, int, 0644);
|
||||
@@ -83,9 +84,9 @@ static const u8 minor_type[] = {
|
||||
};
|
||||
|
||||
#define nums2minor(num, type, id) \
|
||||
(((num) << 6) | ((id) << 4) | minor_type[type])
|
||||
(((num) << 6) | ((id) << 4) | minor_type[type])
|
||||
|
||||
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
|
||||
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS * 64)
|
||||
#endif
|
||||
|
||||
static struct class *dvb_class;
|
||||
@@ -122,9 +123,7 @@ fail:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations dvb_device_fops =
|
||||
{
|
||||
static const struct file_operations dvb_device_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = dvb_device_open,
|
||||
.llseek = noop_llseek,
|
||||
@@ -135,29 +134,38 @@ static struct cdev dvb_device_cdev;
|
||||
int dvb_generic_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
int ret = 0;
|
||||
|
||||
if (!dvbdev)
|
||||
return -ENODEV;
|
||||
|
||||
if (!dvbdev->users)
|
||||
return -EBUSY;
|
||||
mutex_lock(&dvbdev->lock);
|
||||
if (!dvbdev->users) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
||||
if (!dvbdev->readers)
|
||||
return -EBUSY;
|
||||
if (!dvbdev->readers) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
dvbdev->readers--;
|
||||
} else {
|
||||
if (!dvbdev->writers)
|
||||
return -EBUSY;
|
||||
if (!dvbdev->writers) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
dvbdev->writers--;
|
||||
}
|
||||
|
||||
dvbdev->users--;
|
||||
return 0;
|
||||
unlock:
|
||||
mutex_unlock(&dvbdev->lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_generic_open);
|
||||
|
||||
|
||||
int dvb_generic_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
@@ -165,13 +173,14 @@ int dvb_generic_release(struct inode *inode, struct file *file)
|
||||
if (!dvbdev)
|
||||
return -ENODEV;
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
||||
mutex_lock(&dvbdev->lock);
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
|
||||
dvbdev->readers++;
|
||||
} else {
|
||||
else
|
||||
dvbdev->writers++;
|
||||
}
|
||||
|
||||
dvbdev->users++;
|
||||
mutex_unlock(&dvbdev->lock);
|
||||
|
||||
dvb_device_put(dvbdev);
|
||||
|
||||
@@ -179,7 +188,6 @@ int dvb_generic_release(struct inode *inode, struct file *file)
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_generic_release);
|
||||
|
||||
|
||||
long dvb_generic_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
@@ -195,13 +203,13 @@ long dvb_generic_ioctl(struct file *file,
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_generic_ioctl);
|
||||
|
||||
|
||||
static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
|
||||
static int dvbdev_get_free_id(struct dvb_adapter *adap, int type)
|
||||
{
|
||||
u32 id = 0;
|
||||
|
||||
while (id < DVB_MAX_IDS) {
|
||||
struct dvb_device *dev;
|
||||
|
||||
list_for_each_entry(dev, &adap->device_list, list_head)
|
||||
if (dev->type == type && dev->id == id)
|
||||
goto skip;
|
||||
@@ -255,7 +263,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
|
||||
const char *name, int npads)
|
||||
const char *name, int npads)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -397,7 +405,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
|
||||
|
||||
static int dvb_register_media_device(struct dvb_device *dvbdev,
|
||||
int type, int minor,
|
||||
unsigned demux_sink_pads)
|
||||
unsigned int demux_sink_pads)
|
||||
{
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
|
||||
struct media_link *link;
|
||||
@@ -464,14 +472,16 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
enum dvb_device_type type, int demux_sink_pads)
|
||||
{
|
||||
struct dvb_device *dvbdev;
|
||||
struct file_operations *dvbdevfops;
|
||||
struct file_operations *dvbdevfops = NULL;
|
||||
struct dvbdevfops_node *node = NULL, *new_node = NULL;
|
||||
struct device *clsdev;
|
||||
int minor;
|
||||
int id, ret;
|
||||
|
||||
mutex_lock(&dvbdev_register_lock);
|
||||
|
||||
if ((id = dvbdev_get_free_id (adap, type)) < 0){
|
||||
id = dvbdev_get_free_id(adap, type);
|
||||
if (id < 0) {
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
*pdvbdev = NULL;
|
||||
pr_err("%s: couldn't find free device id\n", __func__);
|
||||
@@ -479,18 +489,44 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
}
|
||||
|
||||
*pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
|
||||
|
||||
if (!dvbdev){
|
||||
if (!dvbdev) {
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
|
||||
/*
|
||||
* When a device of the same type is probe()d more than once,
|
||||
* the first allocated fops are used. This prevents memory leaks
|
||||
* that can occur when the same device is probe()d repeatedly.
|
||||
*/
|
||||
list_for_each_entry(node, &dvbdevfops_list, list_head) {
|
||||
if (node->fops->owner == adap->module &&
|
||||
node->type == type && node->template == template) {
|
||||
dvbdevfops = node->fops;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dvbdevfops){
|
||||
kfree (dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return -ENOMEM;
|
||||
if (!dvbdevfops) {
|
||||
dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
|
||||
if (!dvbdevfops) {
|
||||
kfree(dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
new_node = kzalloc(sizeof(*new_node), GFP_KERNEL);
|
||||
if (!new_node) {
|
||||
kfree(dvbdevfops);
|
||||
kfree(dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
new_node->fops = dvbdevfops;
|
||||
new_node->type = type;
|
||||
new_node->template = template;
|
||||
list_add_tail(&new_node->list_head, &dvbdevfops_list);
|
||||
}
|
||||
|
||||
memcpy(dvbdev, template, sizeof(struct dvb_device));
|
||||
@@ -500,21 +536,22 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
dvbdev->adapter = adap;
|
||||
dvbdev->priv = priv;
|
||||
dvbdev->fops = dvbdevfops;
|
||||
init_waitqueue_head (&dvbdev->wait_queue);
|
||||
|
||||
mutex_init(&dvbdev->lock);
|
||||
init_waitqueue_head(&dvbdev->wait_queue);
|
||||
dvbdevfops->owner = adap->module;
|
||||
|
||||
list_add_tail (&dvbdev->list_head, &adap->device_list);
|
||||
|
||||
list_add_tail(&dvbdev->list_head, &adap->device_list);
|
||||
down_write(&minor_rwsem);
|
||||
#ifdef CONFIG_DVB_DYNAMIC_MINORS
|
||||
for (minor = 0; minor < MAX_DVB_MINORS; minor++)
|
||||
if (dvb_minors[minor] == NULL)
|
||||
if (!dvb_minors[minor])
|
||||
break;
|
||||
|
||||
if (minor == MAX_DVB_MINORS) {
|
||||
list_del (&dvbdev->list_head);
|
||||
kfree(dvbdevfops);
|
||||
if (new_node) {
|
||||
list_del(&new_node->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(new_node);
|
||||
}
|
||||
list_del(&dvbdev->list_head);
|
||||
kfree(dvbdev);
|
||||
up_write(&minor_rwsem);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
@@ -523,46 +560,51 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
#else
|
||||
minor = nums2minor(adap->num, type, id);
|
||||
#endif
|
||||
|
||||
dvbdev->minor = minor;
|
||||
dvb_minors[minor] = dvb_device_get(dvbdev);
|
||||
up_write(&minor_rwsem);
|
||||
|
||||
ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
|
||||
if (ret) {
|
||||
pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
|
||||
__func__);
|
||||
|
||||
__func__);
|
||||
if (new_node) {
|
||||
list_del(&new_node->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(new_node);
|
||||
}
|
||||
dvb_media_device_free(dvbdev);
|
||||
list_del (&dvbdev->list_head);
|
||||
kfree(dvbdevfops);
|
||||
list_del(&dvbdev->list_head);
|
||||
kfree(dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
|
||||
clsdev = device_create(dvb_class, adap->device,
|
||||
MKDEV(DVB_MAJOR, minor),
|
||||
dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
|
||||
if (IS_ERR(clsdev)) {
|
||||
pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
|
||||
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
|
||||
if (new_node) {
|
||||
list_del(&new_node->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(new_node);
|
||||
}
|
||||
dvb_media_device_free(dvbdev);
|
||||
list_del (&dvbdev->list_head);
|
||||
kfree(dvbdevfops);
|
||||
list_del(&dvbdev->list_head);
|
||||
kfree(dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return PTR_ERR(clsdev);
|
||||
}
|
||||
|
||||
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
|
||||
adap->num, dnames[type], id, minor, minor);
|
||||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_register_device);
|
||||
|
||||
|
||||
void dvb_remove_device(struct dvb_device *dvbdev)
|
||||
{
|
||||
if (!dvbdev)
|
||||
@@ -577,20 +619,17 @@ void dvb_remove_device(struct dvb_device *dvbdev)
|
||||
|
||||
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
|
||||
|
||||
list_del (&dvbdev->list_head);
|
||||
list_del(&dvbdev->list_head);
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_remove_device);
|
||||
|
||||
|
||||
static void dvb_free_device(struct kref *ref)
|
||||
{
|
||||
struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
|
||||
|
||||
kfree (dvbdev->fops);
|
||||
kfree (dvbdev);
|
||||
kfree(dvbdev);
|
||||
}
|
||||
|
||||
|
||||
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
|
||||
{
|
||||
kref_get(&dvbdev->ref);
|
||||
@@ -598,14 +637,12 @@ struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_device_get);
|
||||
|
||||
|
||||
void dvb_device_put(struct dvb_device *dvbdev)
|
||||
{
|
||||
if (dvbdev)
|
||||
kref_put(&dvbdev->ref, dvb_free_device);
|
||||
}
|
||||
|
||||
|
||||
void dvb_unregister_device(struct dvb_device *dvbdev)
|
||||
{
|
||||
dvb_remove_device(dvbdev);
|
||||
@@ -613,7 +650,6 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_unregister_device);
|
||||
|
||||
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
|
||||
|
||||
static int dvb_create_io_intf_links(struct dvb_adapter *adap,
|
||||
@@ -646,9 +682,9 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
|
||||
struct media_entity *demux = NULL, *ca = NULL;
|
||||
struct media_link *link;
|
||||
struct media_interface *intf;
|
||||
unsigned demux_pad = 0;
|
||||
unsigned dvr_pad = 0;
|
||||
unsigned ntuner = 0, ndemod = 0;
|
||||
unsigned int demux_pad = 0;
|
||||
unsigned int dvr_pad = 0;
|
||||
unsigned int ntuner = 0, ndemod = 0;
|
||||
int ret, pad_source, pad_sink;
|
||||
static const char *connector_name = "Television";
|
||||
|
||||
@@ -719,7 +755,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
|
||||
false);
|
||||
} else {
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0))
|
||||
pad_sink = media_get_pad_index(tuner, true,
|
||||
pad_sink = media_get_pad_index(tuner, MEDIA_PAD_FL_SINK,
|
||||
PAD_SIGNAL_ANALOG);
|
||||
if (pad_sink < 0)
|
||||
return -EINVAL;
|
||||
@@ -741,7 +777,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
|
||||
if (ntuner && ndemod) {
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0))
|
||||
/* NOTE: first found tuner source pad presumed correct */
|
||||
pad_source = media_get_pad_index(tuner, false,
|
||||
pad_source = media_get_pad_index(tuner, MEDIA_PAD_FL_SOURCE,
|
||||
PAD_SIGNAL_ANALOG);
|
||||
if (pad_source < 0)
|
||||
return -EINVAL;
|
||||
@@ -781,18 +817,18 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
|
||||
media_device_for_each_entity(entity, mdev) {
|
||||
if (entity->function == MEDIA_ENT_F_IO_DTV) {
|
||||
if (!strncmp(entity->name, DVR_TSOUT,
|
||||
strlen(DVR_TSOUT))) {
|
||||
strlen(DVR_TSOUT))) {
|
||||
ret = media_create_pad_link(demux,
|
||||
++dvr_pad,
|
||||
entity, 0, 0);
|
||||
++dvr_pad,
|
||||
entity, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (!strncmp(entity->name, DEMUX_TSOUT,
|
||||
strlen(DEMUX_TSOUT))) {
|
||||
strlen(DEMUX_TSOUT))) {
|
||||
ret = media_create_pad_link(demux,
|
||||
++demux_pad,
|
||||
entity, 0, 0);
|
||||
++demux_pad,
|
||||
entity, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -850,8 +886,10 @@ EXPORT_SYMBOL_GPL(dvb_create_media_graph);
|
||||
static int dvbdev_check_free_adapter_num(int num)
|
||||
{
|
||||
struct list_head *entry;
|
||||
|
||||
list_for_each(entry, &dvb_adapter_list) {
|
||||
struct dvb_adapter *adap;
|
||||
|
||||
adap = list_entry(entry, struct dvb_adapter, list_head);
|
||||
if (adap->num == num)
|
||||
return 0;
|
||||
@@ -859,7 +897,7 @@ static int dvbdev_check_free_adapter_num(int num)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dvbdev_get_free_adapter_num (void)
|
||||
static int dvbdev_get_free_adapter_num(void)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
@@ -872,7 +910,6 @@ static int dvbdev_get_free_adapter_num (void)
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
|
||||
int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
|
||||
struct module *module, struct device *device,
|
||||
short *adapter_nums)
|
||||
@@ -899,8 +936,8 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
memset (adap, 0, sizeof(struct dvb_adapter));
|
||||
INIT_LIST_HEAD (&adap->device_list);
|
||||
memset(adap, 0, sizeof(struct dvb_adapter));
|
||||
INIT_LIST_HEAD(&adap->device_list);
|
||||
|
||||
pr_info("DVB: registering new adapter (%s)\n", name);
|
||||
|
||||
@@ -910,13 +947,13 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
|
||||
adap->device = device;
|
||||
adap->mfe_shared = 0;
|
||||
adap->mfe_dvbdev = NULL;
|
||||
mutex_init (&adap->mfe_lock);
|
||||
mutex_init(&adap->mfe_lock);
|
||||
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
|
||||
mutex_init(&adap->mdev_lock);
|
||||
#endif
|
||||
|
||||
list_add_tail (&adap->list_head, &dvb_adapter_list);
|
||||
list_add_tail(&adap->list_head, &dvb_adapter_list);
|
||||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
|
||||
@@ -924,25 +961,26 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_register_adapter);
|
||||
|
||||
|
||||
int dvb_unregister_adapter(struct dvb_adapter *adap)
|
||||
{
|
||||
mutex_lock(&dvbdev_register_lock);
|
||||
list_del (&adap->list_head);
|
||||
list_del(&adap->list_head);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_unregister_adapter);
|
||||
|
||||
/* if the miracle happens and "generic_usercopy()" is included into
|
||||
the kernel, then this can vanish. please don't make the mistake and
|
||||
define this as video_usercopy(). this will introduce a dependency
|
||||
to the v4l "videodev.o" module, which is unnecessary for some
|
||||
cards (ie. the budget dvb-cards don't need the v4l module...) */
|
||||
/*
|
||||
* if the miracle happens and "generic_usercopy()" is included into
|
||||
* the kernel, then this can vanish. please don't make the mistake and
|
||||
* define this as video_usercopy(). this will introduce a dependency
|
||||
* to the v4l "videodev.o" module, which is unnecessary for some
|
||||
* cards (ie. the budget dvb-cards don't need the v4l module...)
|
||||
*/
|
||||
int dvb_usercopy(struct file *file,
|
||||
unsigned int cmd, unsigned long arg,
|
||||
int (*func)(struct file *file,
|
||||
unsigned int cmd, void *arg))
|
||||
unsigned int cmd, unsigned long arg,
|
||||
int (*func)(struct file *file,
|
||||
unsigned int cmd, void *arg))
|
||||
{
|
||||
char sbuf[128];
|
||||
void *mbuf = NULL;
|
||||
@@ -956,7 +994,7 @@ int dvb_usercopy(struct file *file,
|
||||
* For this command, the pointer is actually an integer
|
||||
* argument.
|
||||
*/
|
||||
parg = (void *) arg;
|
||||
parg = (void *)arg;
|
||||
break;
|
||||
case _IOC_READ: /* some v4l ioctls are marked wrong ... */
|
||||
case _IOC_WRITE:
|
||||
@@ -966,7 +1004,7 @@ int dvb_usercopy(struct file *file,
|
||||
} else {
|
||||
/* too big to allocate from stack */
|
||||
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
|
||||
if (NULL == mbuf)
|
||||
if (!mbuf)
|
||||
return -ENOMEM;
|
||||
parg = mbuf;
|
||||
}
|
||||
@@ -978,15 +1016,15 @@ int dvb_usercopy(struct file *file,
|
||||
}
|
||||
|
||||
/* call driver */
|
||||
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
|
||||
err = func(file, cmd, parg);
|
||||
if (err == -ENOIOCTLCMD)
|
||||
err = -ENOTTY;
|
||||
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
/* Copy results into user buffer */
|
||||
switch (_IOC_DIR(cmd))
|
||||
{
|
||||
switch (_IOC_DIR(cmd)) {
|
||||
case _IOC_READ:
|
||||
case (_IOC_WRITE | _IOC_READ):
|
||||
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
|
||||
@@ -998,7 +1036,6 @@ out:
|
||||
kfree(mbuf);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_usercopy);
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0))
|
||||
@@ -1083,13 +1120,15 @@ static int __init init_dvbdev(void)
|
||||
int retval;
|
||||
dev_t dev = MKDEV(DVB_MAJOR, 0);
|
||||
|
||||
if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
|
||||
retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB");
|
||||
if (retval != 0) {
|
||||
pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR);
|
||||
return retval;
|
||||
}
|
||||
|
||||
cdev_init(&dvb_device_cdev, &dvb_device_fops);
|
||||
if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
|
||||
retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS);
|
||||
if (retval != 0) {
|
||||
pr_err("dvb-core: unable register character device\n");
|
||||
goto error;
|
||||
}
|
||||
@@ -1113,12 +1152,19 @@ error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static void __exit exit_dvbdev(void)
|
||||
{
|
||||
struct dvbdevfops_node *node, *next;
|
||||
|
||||
class_destroy(dvb_class);
|
||||
cdev_del(&dvb_device_cdev);
|
||||
unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
|
||||
|
||||
list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) {
|
||||
list_del(&node->list_head);
|
||||
kfree(node->fops);
|
||||
kfree(node);
|
||||
}
|
||||
}
|
||||
|
||||
subsys_initcall(init_dvbdev);
|
||||
|
@@ -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
|
||||
|
@@ -780,7 +780,7 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
|
||||
|
||||
return &ci->en;
|
||||
}
|
||||
EXPORT_SYMBOL(cxd2099_attach);
|
||||
EXPORT_SYMBOL_GPL(cxd2099_attach);
|
||||
|
||||
MODULE_DESCRIPTION("cxd2099");
|
||||
MODULE_AUTHOR("Ralph Metzler");
|
||||
|
@@ -36,7 +36,11 @@
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
#if (KERNEL_VERSION(6, 6, 0) > LINUX_VERSION_CODE)
|
||||
#include <media/dvb_math.h>
|
||||
#else
|
||||
#include <linux/int_log.h>
|
||||
#endif
|
||||
#include "cxd2843.h"
|
||||
|
||||
#define Log10x100(x) ((s32)(((((u64) intlog2(x) * 0x1e1a5e2e) >> 47 ) + 1) >> 1))
|
||||
@@ -2701,7 +2705,7 @@ struct dvb_frontend *cxd2843_attach(struct i2c_adapter *i2c,
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(cxd2843_attach);
|
||||
EXPORT_SYMBOL_GPL(cxd2843_attach);
|
||||
|
||||
MODULE_DESCRIPTION("CXD2843/37/38 driver");
|
||||
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
|
||||
|
@@ -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;
|
||||
@@ -5097,4 +5087,4 @@ MODULE_DESCRIPTION("DRX-K driver");
|
||||
MODULE_AUTHOR("Ralph Metzler");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
EXPORT_SYMBOL(drxk_attach);
|
||||
EXPORT_SYMBOL_GPL(drxk_attach);
|
||||
|
@@ -152,7 +152,7 @@ struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe,
|
||||
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(lnbh25_attach);
|
||||
EXPORT_SYMBOL_GPL(lnbh25_attach);
|
||||
|
||||
MODULE_DESCRIPTION("LNBH25");
|
||||
MODULE_AUTHOR("Ralph Metzler");
|
||||
|
@@ -178,7 +178,7 @@ struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,
|
||||
return lnbx2x_attach(fe, i2c, override_set, override_clear,
|
||||
i2c_addr, LNBH24_TTX);
|
||||
}
|
||||
EXPORT_SYMBOL(lnbh24_attach);
|
||||
EXPORT_SYMBOL_GPL(lnbh24_attach);
|
||||
|
||||
struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, u8 override_set,
|
||||
@@ -187,7 +187,7 @@ struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
|
||||
return lnbx2x_attach(fe, i2c, override_set, override_clear,
|
||||
0x08, LNBP21_ISEL);
|
||||
}
|
||||
EXPORT_SYMBOL(lnbp21_attach);
|
||||
EXPORT_SYMBOL_GPL(lnbp21_attach);
|
||||
|
||||
MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21, lnbh24");
|
||||
MODULE_AUTHOR("Oliver Endriss, Igor M. Liplianin");
|
||||
|
@@ -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
|
||||
|
@@ -2338,7 +2338,7 @@ error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(stv0367ter_attach);
|
||||
EXPORT_SYMBOL_GPL(stv0367ter_attach);
|
||||
|
||||
static int stv0367cab_gate_ctrl(struct dvb_frontend *fe, int enable)
|
||||
{
|
||||
@@ -3462,7 +3462,7 @@ error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(stv0367cab_attach);
|
||||
EXPORT_SYMBOL_GPL(stv0367cab_attach);
|
||||
|
||||
MODULE_PARM_DESC(debug, "Set debug");
|
||||
MODULE_PARM_DESC(i2c_debug, "Set i2c debug");
|
||||
|
@@ -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);
|
||||
@@ -2154,7 +2153,7 @@ MODULE_DESCRIPTION("STV0367DD driver");
|
||||
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
EXPORT_SYMBOL(stv0367_attach);
|
||||
EXPORT_SYMBOL_GPL(stv0367_attach);
|
||||
|
||||
|
||||
|
||||
|
@@ -5254,7 +5254,7 @@ error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(stv090x_attach);
|
||||
EXPORT_SYMBOL_GPL(stv090x_attach);
|
||||
MODULE_PARM_DESC(verbose, "Set Verbosity level");
|
||||
MODULE_AUTHOR("Manu Abraham");
|
||||
MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");
|
||||
|
@@ -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];
|
||||
@@ -1643,7 +1646,7 @@ static int clear_slave(struct dvb_frontend *fe)
|
||||
|
||||
get_field(RXEND, &done);
|
||||
get_reg(DISRXBYTES, &n);
|
||||
printk("clear: done = %u, %u fifo bytes\n", done, n);
|
||||
//printk("clear: done = %u, %u fifo bytes\n", done, n);
|
||||
|
||||
for (get_reg(DISRXBYTES, &n); n; n--)
|
||||
get_reg(DISRXFIFO, &d);
|
||||
@@ -1699,7 +1702,7 @@ static int recv_slave_reply(struct dvb_frontend *fe,
|
||||
msleep(10);
|
||||
}
|
||||
get_reg(DISRXBYTES, &val);
|
||||
printk("done = %u, %u fifo bytes, i=%u\n", done, val, i);
|
||||
//printk("done = %u, %u fifo bytes, i=%u\n", done, val, i);
|
||||
if (i == to && !val)
|
||||
return -EIO;
|
||||
if (done && !val)
|
||||
|
@@ -407,7 +407,7 @@ const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
|
||||
printk(KERN_INFO "%s: Attaching STV6110x\n", __func__);
|
||||
return stv6110x->devctl;
|
||||
}
|
||||
EXPORT_SYMBOL(stv6110x_attach);
|
||||
EXPORT_SYMBOL_GPL(stv6110x_attach);
|
||||
|
||||
MODULE_AUTHOR("Manu Abraham");
|
||||
MODULE_DESCRIPTION("STV6110x Silicon tuner");
|
||||
|
@@ -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
|
||||
|
@@ -302,6 +302,7 @@ enum fe_spectral_inversion {
|
||||
* @FEC_7_15: Forward Error Correction Code 7/15
|
||||
* @FEC_29_45: Forward Error Correction Code 29/45
|
||||
* @FEC_31_45: Forward Error Correction Code 31/45
|
||||
*
|
||||
* Please note that not all FEC types are supported by a given standard.
|
||||
*/
|
||||
enum fe_code_rate {
|
||||
@@ -597,7 +598,7 @@ enum fe_interleaving {
|
||||
#define DTV_STAT_TOTAL_BLOCK_COUNT 69
|
||||
|
||||
/* Physical layer scrambling */
|
||||
#define DTV_SCRAMBLING_SEQUENCE_INDEX 70
|
||||
#define DTV_SCRAMBLING_SEQUENCE_INDEX 70
|
||||
#define DTV_INPUT 71
|
||||
|
||||
#define DTV_MAX_COMMAND DTV_INPUT
|
||||
|
@@ -10,6 +10,6 @@
|
||||
#define _DVBVERSION_H_
|
||||
|
||||
#define DVB_API_VERSION 5
|
||||
#define DVB_API_VERSION_MINOR 11
|
||||
#define DVB_API_VERSION_MINOR 12
|
||||
|
||||
#endif /*_DVBVERSION_H_*/
|
||||
|
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* dvb_filter.h
|
||||
*
|
||||
* Copyright (C) 2003 Convergence GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _DVB_FILTER_H_
|
||||
#define _DVB_FILTER_H_
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "demux.h"
|
||||
|
||||
typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
|
||||
|
||||
struct dvb_filter_pes2ts {
|
||||
unsigned char buf[188];
|
||||
unsigned char cc;
|
||||
dvb_filter_pes2ts_cb_t *cb;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
|
||||
dvb_filter_pes2ts_cb_t *cb, void *priv);
|
||||
|
||||
int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
|
||||
int len, int payload_start);
|
||||
|
||||
|
||||
#define PROG_STREAM_MAP 0xBC
|
||||
#define PRIVATE_STREAM1 0xBD
|
||||
#define PADDING_STREAM 0xBE
|
||||
#define PRIVATE_STREAM2 0xBF
|
||||
#define AUDIO_STREAM_S 0xC0
|
||||
#define AUDIO_STREAM_E 0xDF
|
||||
#define VIDEO_STREAM_S 0xE0
|
||||
#define VIDEO_STREAM_E 0xEF
|
||||
#define ECM_STREAM 0xF0
|
||||
#define EMM_STREAM 0xF1
|
||||
#define DSM_CC_STREAM 0xF2
|
||||
#define ISO13522_STREAM 0xF3
|
||||
#define PROG_STREAM_DIR 0xFF
|
||||
|
||||
#define DVB_PICTURE_START 0x00
|
||||
#define DVB_USER_START 0xb2
|
||||
#define DVB_SEQUENCE_HEADER 0xb3
|
||||
#define DVB_SEQUENCE_ERROR 0xb4
|
||||
#define DVB_EXTENSION_START 0xb5
|
||||
#define DVB_SEQUENCE_END 0xb7
|
||||
#define DVB_GOP_START 0xb8
|
||||
#define DVB_EXCEPT_SLICE 0xb0
|
||||
|
||||
#define SEQUENCE_EXTENSION 0x01
|
||||
#define SEQUENCE_DISPLAY_EXTENSION 0x02
|
||||
#define PICTURE_CODING_EXTENSION 0x08
|
||||
#define QUANT_MATRIX_EXTENSION 0x03
|
||||
#define PICTURE_DISPLAY_EXTENSION 0x07
|
||||
|
||||
#define I_FRAME 0x01
|
||||
#define B_FRAME 0x02
|
||||
#define P_FRAME 0x03
|
||||
|
||||
/* Initialize sequence_data */
|
||||
#define INIT_HORIZONTAL_SIZE 720
|
||||
#define INIT_VERTICAL_SIZE 576
|
||||
#define INIT_ASPECT_RATIO 0x02
|
||||
#define INIT_FRAME_RATE 0x03
|
||||
#define INIT_DISP_HORIZONTAL_SIZE 540
|
||||
#define INIT_DISP_VERTICAL_SIZE 576
|
||||
|
||||
|
||||
//flags2
|
||||
#define PTS_DTS_FLAGS 0xC0
|
||||
#define ESCR_FLAG 0x20
|
||||
#define ES_RATE_FLAG 0x10
|
||||
#define DSM_TRICK_FLAG 0x08
|
||||
#define ADD_CPY_FLAG 0x04
|
||||
#define PES_CRC_FLAG 0x02
|
||||
#define PES_EXT_FLAG 0x01
|
||||
|
||||
//pts_dts flags
|
||||
#define PTS_ONLY 0x80
|
||||
#define PTS_DTS 0xC0
|
||||
|
||||
#define TS_SIZE 188
|
||||
#define TRANS_ERROR 0x80
|
||||
#define PAY_START 0x40
|
||||
#define TRANS_PRIO 0x20
|
||||
#define PID_MASK_HI 0x1F
|
||||
//flags
|
||||
#define TRANS_SCRMBL1 0x80
|
||||
#define TRANS_SCRMBL2 0x40
|
||||
#define ADAPT_FIELD 0x20
|
||||
#define PAYLOAD 0x10
|
||||
#define COUNT_MASK 0x0F
|
||||
|
||||
// adaptation flags
|
||||
#define DISCON_IND 0x80
|
||||
#define RAND_ACC_IND 0x40
|
||||
#define ES_PRI_IND 0x20
|
||||
#define PCR_FLAG 0x10
|
||||
#define OPCR_FLAG 0x08
|
||||
#define SPLICE_FLAG 0x04
|
||||
#define TRANS_PRIV 0x02
|
||||
#define ADAP_EXT_FLAG 0x01
|
||||
|
||||
// adaptation extension flags
|
||||
#define LTW_FLAG 0x80
|
||||
#define PIECE_RATE 0x40
|
||||
#define SEAM_SPLICE 0x20
|
||||
|
||||
|
||||
#define MAX_PLENGTH 0xFFFF
|
||||
#define MMAX_PLENGTH (256*MAX_PLENGTH)
|
||||
|
||||
#ifndef IPACKS
|
||||
#define IPACKS 2048
|
||||
#endif
|
||||
|
||||
struct ipack {
|
||||
int size;
|
||||
int found;
|
||||
u8 *buf;
|
||||
u8 cid;
|
||||
u32 plength;
|
||||
u8 plen[2];
|
||||
u8 flag1;
|
||||
u8 flag2;
|
||||
u8 hlength;
|
||||
u8 pts[5];
|
||||
u16 *pid;
|
||||
int mpeg;
|
||||
u8 check;
|
||||
int which;
|
||||
int done;
|
||||
void *data;
|
||||
void (*func)(u8 *buf, int size, void *priv);
|
||||
int count;
|
||||
int repack_subids;
|
||||
};
|
||||
|
||||
struct dvb_video_info {
|
||||
u32 horizontal_size;
|
||||
u32 vertical_size;
|
||||
u32 aspect_ratio;
|
||||
u32 framerate;
|
||||
u32 video_format;
|
||||
u32 bit_rate;
|
||||
u32 comp_bit_rate;
|
||||
u32 vbv_buffer_size;
|
||||
s16 vbv_delay;
|
||||
u32 CSPF;
|
||||
u32 off;
|
||||
};
|
||||
|
||||
#define OFF_SIZE 4
|
||||
#define FIRST_FIELD 0
|
||||
#define SECOND_FIELD 1
|
||||
#define VIDEO_FRAME_PICTURE 0x03
|
||||
|
||||
struct mpg_picture {
|
||||
int channel;
|
||||
struct dvb_video_info vinfo;
|
||||
u32 *sequence_gop_header;
|
||||
u32 *picture_header;
|
||||
s32 time_code;
|
||||
int low_delay;
|
||||
int closed_gop;
|
||||
int broken_link;
|
||||
int sequence_header_flag;
|
||||
int gop_flag;
|
||||
int sequence_end_flag;
|
||||
|
||||
u8 profile_and_level;
|
||||
s32 picture_coding_parameter;
|
||||
u32 matrix[32];
|
||||
s8 matrix_change_flag;
|
||||
|
||||
u8 picture_header_parameter;
|
||||
/* bit 0 - 2: bwd f code
|
||||
bit 3 : fpb vector
|
||||
bit 4 - 6: fwd f code
|
||||
bit 7 : fpf vector */
|
||||
|
||||
int mpeg1_flag;
|
||||
int progressive_sequence;
|
||||
int sequence_display_extension_flag;
|
||||
u32 sequence_header_data;
|
||||
s16 last_frame_centre_horizontal_offset;
|
||||
s16 last_frame_centre_vertical_offset;
|
||||
|
||||
u32 pts[2]; /* [0] 1st field, [1] 2nd field */
|
||||
int top_field_first;
|
||||
int repeat_first_field;
|
||||
int progressive_frame;
|
||||
int bank;
|
||||
int forward_bank;
|
||||
int backward_bank;
|
||||
int compress;
|
||||
s16 frame_centre_horizontal_offset[OFF_SIZE];
|
||||
/* [0-2] 1st field, [3] 2nd field */
|
||||
s16 frame_centre_vertical_offset[OFF_SIZE];
|
||||
/* [0-2] 1st field, [3] 2nd field */
|
||||
s16 temporal_reference[2];
|
||||
/* [0] 1st field, [1] 2nd field */
|
||||
|
||||
s8 picture_coding_type[2];
|
||||
/* [0] 1st field, [1] 2nd field */
|
||||
s8 picture_structure[2];
|
||||
/* [0] 1st field, [1] 2nd field */
|
||||
s8 picture_display_extension_flag[2];
|
||||
/* [0] 1st field, [1] 2nd field */
|
||||
/* picture_display_extenion() 0:no 1:exit*/
|
||||
s8 pts_flag[2];
|
||||
/* [0] 1st field, [1] 2nd field */
|
||||
};
|
||||
|
||||
struct dvb_audio_info {
|
||||
int layer;
|
||||
u32 bit_rate;
|
||||
u32 frequency;
|
||||
u32 mode;
|
||||
u32 mode_extension ;
|
||||
u32 emphasis;
|
||||
u32 framesize;
|
||||
u32 off;
|
||||
};
|
||||
|
||||
int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr);
|
||||
|
||||
|
||||
#endif
|
@@ -19,13 +19,11 @@
|
||||
#define _DVB_NET_H_
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include <media/dvbdev.h>
|
||||
|
||||
struct net_device;
|
||||
|
||||
#define DVB_NET_DEVICES_MAX 10
|
||||
|
||||
#ifdef CONFIG_DVB_NET
|
||||
@@ -41,6 +39,9 @@
|
||||
* @exit: flag to indicate when the device is being removed.
|
||||
* @demux: pointer to &struct dmx_demux.
|
||||
* @ioctl_mutex: protect access to this struct.
|
||||
* @remove_mutex: mutex that avoids a race condition between a callback
|
||||
* called when the hardware is disconnected and the
|
||||
* file_operations of dvb_net.
|
||||
*
|
||||
* Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network
|
||||
* devices.
|
||||
@@ -53,6 +54,7 @@ struct dvb_net {
|
||||
unsigned int exit:1;
|
||||
struct dmx_demux *demux;
|
||||
struct mutex ioctl_mutex;
|
||||
struct mutex remove_mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -139,7 +139,7 @@ struct dvb_adapter {
|
||||
* struct dvb_device - represents a DVB device node
|
||||
*
|
||||
* @list_head: List head with all DVB devices
|
||||
* @ref: reference counter
|
||||
* @ref: reference count for this device
|
||||
* @fops: pointer to struct file_operations
|
||||
* @adapter: pointer to the adapter that holds this device node
|
||||
* @type: type of the device, as defined by &enum dvb_device_type.
|
||||
@@ -182,6 +182,7 @@ struct dvb_device {
|
||||
int readers;
|
||||
int writers;
|
||||
int users;
|
||||
struct mutex lock;
|
||||
|
||||
wait_queue_head_t wait_queue;
|
||||
/* don't really need those !? -- FIXME: use video_usercopy */
|
||||
@@ -202,6 +203,21 @@ struct dvb_device {
|
||||
void *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvbdevfops_node - fops nodes registered in dvbdevfops_list
|
||||
*
|
||||
* @fops: Dynamically allocated fops for ->owner registration
|
||||
* @type: type of dvb_device
|
||||
* @template: dvb_device used for registration
|
||||
* @list_head: list_head for dvbdevfops_list
|
||||
*/
|
||||
struct dvbdevfops_node {
|
||||
struct file_operations *fops;
|
||||
enum dvb_device_type type;
|
||||
const struct dvb_device *template;
|
||||
struct list_head list_head;
|
||||
};
|
||||
|
||||
/**
|
||||
* dvb_device_get - Increase dvb_device reference
|
||||
*
|
||||
@@ -260,10 +276,10 @@ int dvb_register_device(struct dvb_adapter *adap,
|
||||
/**
|
||||
* dvb_remove_device - Remove a registered DVB device
|
||||
*
|
||||
* @dvbdev: pointer to struct dvb_device
|
||||
*
|
||||
* This does not free memory. dvb_free_device() will do that when
|
||||
* reference counter is empty
|
||||
*
|
||||
* @dvbdev: pointer to struct dvb_device
|
||||
*/
|
||||
void dvb_remove_device(struct dvb_device *dvbdev);
|
||||
|
||||
|
@@ -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:
|
||||
|
||||
|
@@ -17,7 +17,19 @@ Tuner5=5,984
|
||||
Tuner6=6,1020
|
||||
Tuner7=7,1056
|
||||
Tuner8=8,1092
|
||||
Tuner9=1,1210
|
||||
Tuner10=2,1420
|
||||
Tuner11=3,1680
|
||||
Tuner12=4,2040
|
||||
Tuner9=9,1128
|
||||
Tuner10=10,1164
|
||||
Tuner11=11,1256
|
||||
Tuner12=12,1292
|
||||
Tuner13=13,1328
|
||||
Tuner14=14,1364
|
||||
Tuner15=15,1458
|
||||
Tuner16=16,1494
|
||||
Tuner17=17,1530
|
||||
Tuner18=18,1566
|
||||
Tuner19=19,1602
|
||||
Tuner20=20,1638
|
||||
Tuner21=21,1716
|
||||
Tuner22=22,1752
|
||||
Tuner23=23,1788
|
||||
Tuner24=24,1824
|
||||
|
186
lib/ddzap.c
186
lib/ddzap.c
@@ -1,5 +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>
|
||||
@@ -13,6 +15,7 @@
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
char line_start[16] = "";
|
||||
char line_end[16] = "\r";
|
||||
@@ -23,6 +26,14 @@ uint32_t packets = 0;
|
||||
uint32_t payload_packets = 0;
|
||||
uint32_t packet_errors = 0;
|
||||
|
||||
|
||||
#define SYS_FILE 200
|
||||
uint16_t pmt_pid[16];
|
||||
uint32_t numpmt = 0;
|
||||
uint8_t *pmts[16];
|
||||
int32_t ci = -1;
|
||||
uint32_t loop = 1;
|
||||
|
||||
uint8_t cc[8192] = { 0 };
|
||||
|
||||
enum { IQ_RED=1, IQ_GREE, IQ_BLUE , IQ_EVIL, IQ_LOG_RED, IQ_LOG_GREEN, IQ_LOG_BLUE , IQ_LOG_EVIL , IQ_TEST, };
|
||||
@@ -196,8 +207,8 @@ void pam_write (int fd, pamdata *iq){
|
||||
|
||||
void proc_ts(int i, uint8_t *buf)
|
||||
{
|
||||
uint16_t pid=0x1fff&((buf[1]<<8)|buf[2]);
|
||||
uint8_t ccin = buf[3] & 0x1F;
|
||||
uint16_t pid=0x1fff&((buf[1]<<8)|buf[2]);
|
||||
uint8_t ccin = buf[3] & 0x1F;
|
||||
|
||||
if (buf[0] == 0x47 && (buf[1] & 0x80) == 0) {
|
||||
if( pid != 8191 ) {
|
||||
@@ -225,6 +236,34 @@ void proc_ts(int i, uint8_t *buf)
|
||||
|
||||
#define TSBUFSIZE (100*188)
|
||||
|
||||
void tscheck_orig(int ts)
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint8_t id;
|
||||
int i, nts;
|
||||
int len;
|
||||
|
||||
buf=(uint8_t *)malloc(TSBUFSIZE);
|
||||
|
||||
while(1) {
|
||||
len=read(ts, buf, TSBUFSIZE);
|
||||
if (len<0)
|
||||
continue;
|
||||
if (len%188) { /* should not happen */
|
||||
printf("blah\n");
|
||||
continue;
|
||||
}
|
||||
if (buf[0]!=0x47) {
|
||||
printf("unaligned\n");
|
||||
read(ts, buf, 1);
|
||||
continue;
|
||||
}
|
||||
nts=len/188;
|
||||
for (i=0; i<nts; i++)
|
||||
proc_ts(i, buf+i*188);
|
||||
}
|
||||
}
|
||||
|
||||
void tscheck(int ts)
|
||||
{
|
||||
uint8_t *buf;
|
||||
@@ -234,20 +273,19 @@ void tscheck(int ts)
|
||||
|
||||
buf=(uint8_t *)malloc(TSBUFSIZE);
|
||||
|
||||
|
||||
while(1) {
|
||||
while(1) {
|
||||
len=read(ts, buf, TSBUFSIZE);
|
||||
if (len<0) {
|
||||
if (len<0)
|
||||
continue;
|
||||
if (len%188) { /* should not happen */
|
||||
printf("blah\n");
|
||||
continue;
|
||||
}
|
||||
if (buf[0]!=0x47) {
|
||||
printf("unaligned\n");
|
||||
read(ts, buf, 1);
|
||||
continue;
|
||||
}
|
||||
if (len%188) { /* should not happen */
|
||||
printf("blah\n");
|
||||
continue;
|
||||
}
|
||||
nts=len/188;
|
||||
for (i=0; i<nts; i++)
|
||||
proc_ts(i, buf+i*188);
|
||||
@@ -266,6 +304,76 @@ static uint32_t root2gold(uint32_t root)
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
ssize_t rread(int fd, uint8_t *buf, size_t count)
|
||||
{
|
||||
size_t len, todo=count;
|
||||
|
||||
while (todo) {
|
||||
len = read(fd, buf, todo);
|
||||
if (len < 0)
|
||||
return len;
|
||||
if (len == 0 && fd && loop!=1) {
|
||||
lseek64(fd, SEEK_SET, 0);
|
||||
loop -= loop ? 1 : 0;
|
||||
}
|
||||
buf+=len;
|
||||
todo-=len;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void decode(struct dddvb *dd, int fd)
|
||||
{
|
||||
uint8_t buf[200*188];
|
||||
uint8_t ts[188];
|
||||
struct dvbf_pid pidf[16];
|
||||
int pmt;
|
||||
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 != 188) {
|
||||
dprintf(2, "Error reading stream\n");
|
||||
exit(-1);
|
||||
}
|
||||
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);
|
||||
pmts[pmt]=pidf[pmt].buf;
|
||||
}
|
||||
//sleep(10);
|
||||
while (dddvb_ca_set_pmts(dd, ci, pmts) < 0)
|
||||
sleep(1);
|
||||
while (1) {
|
||||
len = rread(fd, buf, sizeof(buf));
|
||||
if (len < 0) {
|
||||
dprintf(2, "Error reading stream %d\n", errno);
|
||||
exit(-1);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct dddvb *dd;
|
||||
@@ -286,7 +394,7 @@ int main(int argc, char **argv)
|
||||
int color = 0;
|
||||
pamdata iq;
|
||||
|
||||
|
||||
memset(pmts, 0, sizeof(pmts));
|
||||
while (1) {
|
||||
int cur_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
@@ -311,16 +419,35 @@ int main(int argc, char **argv)
|
||||
{"nodvr", no_argument , 0, 'q'},
|
||||
{"pam", no_argument , 0, 'P'},
|
||||
{"pam_color", no_argument , 0, 'e'},
|
||||
{"decode", required_argument, 0, 'x'},
|
||||
{"loop", required_argument, 0, 'L'},
|
||||
{"help", no_argument , 0, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv,
|
||||
"e:c:i:f:s:d:p:hg:r:n:b:l:v:m:ota:qP",
|
||||
"e:c:i:f:s:d:p:hg:r:n:b:l:v:m:ota:qPx:L:",
|
||||
long_options, &option_index);
|
||||
if (c==-1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'x':
|
||||
{
|
||||
int j;
|
||||
char *str,*estr;
|
||||
|
||||
for (numpmt = 0, str = optarg; numpmt < 17 && *str; numpmt++, str=*estr?estr+1:estr) {
|
||||
if (numpmt)
|
||||
pmt_pid[numpmt-1] = strtoul(str, &estr, 10);
|
||||
else
|
||||
ci = strtoul(str, &estr, 10);
|
||||
}
|
||||
numpmt--;
|
||||
odvr = 4;
|
||||
break;
|
||||
}
|
||||
case 'L':
|
||||
loop = strtoul(optarg, NULL, 0);
|
||||
case 'e':
|
||||
color = strtoul(optarg, NULL, 0);
|
||||
case 'P':
|
||||
@@ -423,6 +550,8 @@ int main(int argc, char **argv)
|
||||
delsys = SYS_ISDBT;
|
||||
if (!strcmp(optarg, "ISDBS"))
|
||||
delsys = SYS_ISDBS;
|
||||
if (!strcmp(optarg, "FILE"))
|
||||
delsys = SYS_FILE;
|
||||
break;
|
||||
case 'p':
|
||||
if (!strcmp(optarg, "h") || !strcmp(optarg, "H"))
|
||||
@@ -446,6 +575,7 @@ int main(int argc, char **argv)
|
||||
" [-a [display line] (display continuity check in line)]\n"
|
||||
" [-P (output IQ diagram as pam)]\n"
|
||||
" [-e [color] (use color for pam 0=green)]\n"
|
||||
" [-x cinum[,pmt0,pmt1,..,.pmt15]]\n"
|
||||
"\n"
|
||||
" delivery_system = C,S,S2,T,T2,J83B,ISDBC,ISDBT\n"
|
||||
" polarity = h/H,v/V\n"
|
||||
@@ -456,9 +586,20 @@ int main(int argc, char **argv)
|
||||
|
||||
}
|
||||
}
|
||||
if (optind < argc) {
|
||||
fprintf(fout,"Warning: unused arguments\n");
|
||||
if (delsys==SYS_FILE) {
|
||||
if (optind >= argc) {
|
||||
fd = 0;
|
||||
} else {
|
||||
fd = open(argv[optind], O_RDONLY);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr,"error opening %s\n", argv[optind]);
|
||||
exit(-1);
|
||||
}
|
||||
optind++;
|
||||
}
|
||||
}
|
||||
if (optind < argc)
|
||||
fprintf(fout,"Warning: unused arguments\n");
|
||||
|
||||
if (delsys == ~0) {
|
||||
fprintf(fout,"You have to choose a delivery system: -d (C|S|S2|T|T2)\n");
|
||||
@@ -476,7 +617,12 @@ int main(int argc, char **argv)
|
||||
fprintf(fout,"dddvb_init failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
fprintf(fout,"dvbnum = %u\n", dd->dvbfe_num);
|
||||
if (delsys==SYS_FILE) {
|
||||
if (ci>=0)
|
||||
decode(dd, fd);
|
||||
fprintf(fout, "FILE delsys only alowed for decoding.\n");
|
||||
exit(-1);
|
||||
}
|
||||
dddvb_get_ts(dd, get_ts);
|
||||
|
||||
if (num != DDDVB_UNDEF)
|
||||
@@ -499,14 +645,6 @@ int main(int argc, char **argv)
|
||||
dddvb_set_ssi(&p, ssi);
|
||||
dddvb_dvb_tune(fe, &p);
|
||||
|
||||
#if 0
|
||||
{
|
||||
uint8_t ts[188];
|
||||
|
||||
dddvb_ca_write(dd, 0, ts, 188);
|
||||
|
||||
}
|
||||
#endif
|
||||
if (!odvr){
|
||||
while (1) {
|
||||
fe_status_t stat;
|
||||
@@ -523,9 +661,9 @@ int main(int argc, char **argv)
|
||||
sleep(1);
|
||||
}
|
||||
} else {
|
||||
#define BUFFSIZE (1024*188)
|
||||
fe_status_t stat;
|
||||
char filename[150];
|
||||
#define BUFFSIZE (1024*188)
|
||||
uint8_t buf[BUFFSIZE];
|
||||
|
||||
stat = 0;
|
||||
@@ -571,6 +709,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
tscheck(fd);
|
||||
break;
|
||||
case 4:
|
||||
decode(dd, fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
97
lib/src/ca.c
97
lib/src/ca.c
@@ -2,11 +2,13 @@
|
||||
#include "dddvb.h"
|
||||
#include "tools.h"
|
||||
#include "debug.h"
|
||||
#include "dvb_filter.h"
|
||||
|
||||
#include <linux/dvb/dmx.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/net.h>
|
||||
#include <linux/dvb/ca.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -30,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)
|
||||
{
|
||||
@@ -165,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;
|
||||
@@ -195,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)
|
||||
{
|
||||
@@ -273,10 +291,28 @@ static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
|
||||
len = ((sec[1] & 0x0f) << 8) | sec[2];
|
||||
len += 3;
|
||||
memcpy(sec, pmts[i], len);
|
||||
//dump(stderr, sec, len);
|
||||
section = section_codec(sec, len);
|
||||
if (!section) {
|
||||
dbgprintf(DEBUG_CA, "section_codec failed\n");;
|
||||
continue;
|
||||
}
|
||||
section_ext = section_ext_decode(section, 0);
|
||||
if (!section_ext) {
|
||||
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) {
|
||||
dbgprintf(DEBUG_CA, "mpeg_pmt_section_codec failed\n");;
|
||||
continue;
|
||||
}
|
||||
|
||||
//dbgprintf(DEBUG_CA, "PMT = %p section=%p\n", pmt, section);
|
||||
|
||||
ca->ca_pmt_version[i] = section_ext->version_number;
|
||||
if (ca->sentpmt) {
|
||||
//return 0;
|
||||
@@ -291,14 +327,16 @@ static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
|
||||
listmgmt = CA_LIST_MANAGEMENT_LAST;
|
||||
}
|
||||
}
|
||||
dbgprintf(DEBUG_CA, "set ca_pmt\n");
|
||||
|
||||
//dump(stderr, (uint8_t *) pmt, len);
|
||||
dbgprintf(DEBUG_CA, "format ca_pmt %p length %u\n", pmt, len);
|
||||
|
||||
if ((size = en50221_ca_format_pmt(pmt, capmt, sizeof(capmt), ca->moveca, listmgmt,
|
||||
CA_PMT_CMD_ID_OK_DESCRAMBLING)) < 0) {
|
||||
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");
|
||||
return -1;
|
||||
@@ -585,7 +623,7 @@ static int mmi_menu_callback(void *arg, uint8_t slot_id, uint16_t snum,
|
||||
|
||||
|
||||
static int init_ca_stack(struct dddvb_ca *ca)
|
||||
{
|
||||
{
|
||||
ca->tl = en50221_tl_create(1, 16);
|
||||
if (ca->tl == NULL) {
|
||||
dbgprintf(DEBUG_CA, "Failed to create transport layer\n");
|
||||
@@ -625,12 +663,27 @@ static int init_ca_stack(struct dddvb_ca *ca)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cam_reset(int fd)
|
||||
{
|
||||
ca_slot_info_t info;
|
||||
|
||||
info.num = 0;
|
||||
if (ioctl(fd, CA_GET_SLOT_INFO, &info))
|
||||
return;
|
||||
if (info.flags & CA_CI_MODULE_READY)
|
||||
return;
|
||||
if (!(info.flags & CA_CI_MODULE_PRESENT))
|
||||
return;
|
||||
ioctl(fd, CA_RESET);
|
||||
}
|
||||
|
||||
static int init_ca(struct dddvb *dd, int a, int f, int fd)
|
||||
{
|
||||
struct dddvb_ca *ca;
|
||||
char fname[80];
|
||||
|
||||
if (dd->dvbca_num >= DDDVB_MAX_DVB_CA)
|
||||
return -1;
|
||||
ca = &dd->dvbca[dd->dvbca_num];
|
||||
ca->dd = dd;
|
||||
ca->anum = a;
|
||||
@@ -638,11 +691,14 @@ static int init_ca(struct dddvb *dd, int a, int f, int fd)
|
||||
ca->nr = dd->dvbca_num + 1;
|
||||
ca->fd = fd;
|
||||
pthread_mutex_init(&ca->mutex, 0);
|
||||
|
||||
//cam_reset(fd);
|
||||
|
||||
init_ca_stack(ca);
|
||||
|
||||
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);
|
||||
@@ -654,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);
|
||||
}
|
||||
|
||||
@@ -669,7 +734,7 @@ int dddvb_ca_set_pmts(struct dddvb *dd, uint32_t nr, uint8_t **pmts)
|
||||
{
|
||||
struct dddvb_ca *ca = &dd->dvbca[nr];
|
||||
|
||||
dbgprintf(DEBUG_CA, "ca_set_pmt\n");
|
||||
dbgprintf(DEBUG_CA, "ca%u.%u.%u:ca_set_pmt\n", ca->nr,ca->anum,ca->fnum);
|
||||
return set_pmts(ca, pmts);
|
||||
}
|
||||
|
||||
|
@@ -71,7 +71,7 @@ LIBDDDVB_EXPORTED struct dddvb *dddvb_init(char *config, uint32_t flags)
|
||||
struct dddvb *dd;
|
||||
pthread_mutexattr_t mta;
|
||||
|
||||
dddvb_debug = flags;
|
||||
dddvb_debug = flags & 0xff;
|
||||
|
||||
pthread_mutex_lock(&dddvb_mutex);
|
||||
if (global_dd) {
|
||||
@@ -90,9 +90,11 @@ LIBDDDVB_EXPORTED struct dddvb *dddvb_init(char *config, uint32_t flags)
|
||||
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&dd->lock, &mta);
|
||||
|
||||
dd->get_ts = (flags & 0x100) ? 0 : 1;
|
||||
dd->use_ca = (flags & 0x200) ? 0 : 1;
|
||||
|
||||
dddvb_dvb_init(dd);
|
||||
global_dd = dd;
|
||||
dd->get_ts = 1;
|
||||
fail:
|
||||
pthread_mutex_unlock(&dddvb_mutex);
|
||||
return dd;
|
||||
|
@@ -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
|
||||
@@ -76,6 +80,8 @@ struct dddvb_fe {
|
||||
uint32_t lock;
|
||||
uint32_t quality;
|
||||
uint32_t pls_code;
|
||||
uint32_t inversion;
|
||||
uint32_t rolloff;
|
||||
int64_t strength;
|
||||
int64_t cnr;
|
||||
int64_t ber;
|
||||
@@ -90,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;
|
||||
@@ -126,6 +143,8 @@ struct dddvb_ca {
|
||||
uint8_t mmi_buf[16];
|
||||
int mmi_bufp;
|
||||
int sock;
|
||||
|
||||
struct dvbf_pid dvbf_tdt;
|
||||
};
|
||||
|
||||
struct dddvb {
|
||||
@@ -156,7 +175,8 @@ struct dddvb {
|
||||
unsigned int cam_proto;
|
||||
unsigned int cam_port;
|
||||
|
||||
unsigned int get_ts:1;
|
||||
unsigned int get_ts;
|
||||
unsigned int use_ca;
|
||||
};
|
||||
|
||||
int dddvb_dvb_init(struct dddvb *dd);
|
||||
|
@@ -23,7 +23,7 @@ extern uint32_t dddvb_debug;
|
||||
do { if (dddvb_debug & _mask_) fprintf(stderr, __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define dbgprintf(_mask_, ...) \
|
||||
do { if (dddvb_debug & _mask_) { fprintf(stderr, "[%5u] ", mtime(NULL)); \
|
||||
do { if (dddvb_debug & _mask_) { fprintf(stderr, "[%5u] ",(unsigned int) mtime(NULL)); \
|
||||
fprintf(stderr, __VA_ARGS__); } } while (0)
|
||||
#endif
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define DTV_SCRAMBLING_SEQUENCE_INDEX 70
|
||||
#define DTV_INPUT 71
|
||||
@@ -98,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,
|
||||
@@ -128,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]);
|
||||
@@ -213,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)
|
||||
@@ -244,7 +253,7 @@ static int set_en50607(struct dddvb_fe *fe, uint32_t freq_khz, uint32_t sr,
|
||||
uint32_t t = freq - 100;
|
||||
uint32_t input = 3 & (sat >> 6);
|
||||
int fd = fe->fd;
|
||||
|
||||
|
||||
dbgprintf(DEBUG_DVB, "input = %u, sat = %u\n", input, sat&0x3f);
|
||||
hor &= 1;
|
||||
cmd.msg[1] = slot << 3;
|
||||
@@ -252,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)
|
||||
@@ -344,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);
|
||||
@@ -604,6 +613,7 @@ int open_dmx(struct dddvb_fe *fe)
|
||||
struct dmx_pes_filter_params pesFilterParams;
|
||||
|
||||
sprintf(fname, "/dev/dvb/adapter%u/demux%u", fe->anum, fe->fnum);
|
||||
dbgprintf(DEBUG_DVB, "open %s\n", fname);
|
||||
|
||||
fe->dmx = open(fname, O_RDWR);
|
||||
if (fe->dmx < 0)
|
||||
@@ -651,12 +661,12 @@ static void get_stats(struct dddvb_fe *fe)
|
||||
|
||||
fe->strength = str = st.stat[0].svalue;
|
||||
dbgprintf(DEBUG_DVB, "fe%d: str=%lld.%03llddB\n",
|
||||
fe->nr, str/1000, abs(str%1000));
|
||||
fe->nr, (long long int)str/1000, (long long int)abs(str%1000));
|
||||
}
|
||||
if (!get_stat(fe->fd, DTV_STAT_CNR, &st)) {
|
||||
fe->cnr = cnr = st.stat[0].svalue;
|
||||
dbgprintf(DEBUG_DVB, "fe%d: cnr=%lld.%03llddB\n",
|
||||
fe->nr, cnr/1000, abs(cnr%1000));
|
||||
fe->nr, (long long int)cnr/1000, (long long int)abs(cnr%1000));
|
||||
}
|
||||
if (!get_stat(fe->fd, DTV_STAT_PRE_TOTAL_BIT_COUNT, &st) &&
|
||||
(st.stat[0].scale == FE_SCALE_COUNTER)) {
|
||||
@@ -668,19 +678,19 @@ static void get_stats(struct dddvb_fe *fe)
|
||||
(st.stat[0].scale == FE_SCALE_COUNTER)) {
|
||||
uval = st.stat[0].uvalue;
|
||||
dbgprintf(DEBUG_DVB, "fe%d: pre_error_bit_count = %llu\n",
|
||||
fe->nr, uval);
|
||||
fe->nr, (long long int)uval);
|
||||
}
|
||||
if (!get_stat(fe->fd, DTV_STAT_ERROR_BLOCK_COUNT, &st) &&
|
||||
(st.stat[0].scale == FE_SCALE_COUNTER)) {
|
||||
uval = st.stat[0].uvalue;
|
||||
dbgprintf(DEBUG_DVB, "fe%d: error_block_count = %llu\n",
|
||||
fe->nr, uval);
|
||||
fe->nr, (long long int)uval);
|
||||
}
|
||||
if (!get_stat(fe->fd, DTV_STAT_TOTAL_BLOCK_COUNT, &st) &&
|
||||
(st.stat[0].scale == FE_SCALE_COUNTER)) {
|
||||
uval = st.stat[0].uvalue;
|
||||
dbgprintf(DEBUG_DVB, "fe%d: total_block_count = %llu\n",
|
||||
fe->nr, uval);
|
||||
fe->nr, (long long int)uval);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,7 +699,6 @@ void dddvb_fe_handle(struct dddvb_fe *fe)
|
||||
uint32_t newtune, count = 0, max, nolock = 0;
|
||||
int ret;
|
||||
|
||||
|
||||
if (fe->dd->get_ts)
|
||||
open_dmx(fe);
|
||||
while (fe->state == 1) {
|
||||
@@ -726,13 +735,14 @@ void dddvb_fe_handle(struct dddvb_fe *fe)
|
||||
break;
|
||||
count = 0;
|
||||
get_stats(fe);
|
||||
dbgprintf(DEBUG_DVB, "fe: nolock = %u, stat = %u\n", nolock, fe->stat);
|
||||
if (fe->lock) {
|
||||
max = 20;
|
||||
nolock = 0;
|
||||
} else {
|
||||
max = 1;
|
||||
nolock++;
|
||||
if (nolock > 10)
|
||||
if (nolock > 200 || fe->stat == FE_TIMEDOUT)
|
||||
fe->tune = 1;
|
||||
}
|
||||
break;
|
||||
@@ -798,6 +808,8 @@ static int dddvb_fe_init(struct dddvb *dd, int a, int f, int fd)
|
||||
int r;
|
||||
uint32_t i, ds;
|
||||
|
||||
if (dd->dvbfe_num >= DDDVB_MAX_DVB_FE)
|
||||
return -1;
|
||||
fe = &dd->dvbfe[dd->dvbfe_num];
|
||||
|
||||
r = snprintf(fe->name, sizeof(fe->name), "/dev/dvb/adapter%d/frontend%d", a, f);
|
||||
@@ -809,8 +821,10 @@ static int dddvb_fe_init(struct dddvb *dd, int a, int f, int fd)
|
||||
dps.props = dp;
|
||||
dp[0].cmd = DTV_ENUM_DELSYS;
|
||||
r = ioctl(fd, FE_GET_PROPERTY, &dps);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
dbgprintf(DEBUG_DVB, "Could not get delsys, error=%d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < dp[0].u.buffer.len; i++) {
|
||||
ds = dp[0].u.buffer.data[i];
|
||||
dbgprintf(DEBUG_DVB, "delivery system %d\n", ds);
|
||||
@@ -825,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))
|
||||
@@ -867,7 +860,7 @@ static int scan_dvbfe(struct dddvb *dd)
|
||||
int a, f, fd;
|
||||
char fname[80];
|
||||
|
||||
for (a = 0; a < 16; a++) {
|
||||
for (a = 0; a < 256; a++) {
|
||||
for (f = 0; f < 24; f++) {
|
||||
sprintf(fname, "/dev/dvb/adapter%d/frontend%d", a, f);
|
||||
fd = open(fname, O_RDONLY);
|
||||
@@ -1029,7 +1022,8 @@ int dddvb_dvb_init(struct dddvb *dd)
|
||||
if (dd->cam_port == 0)
|
||||
dd->cam_port = 8888;
|
||||
}
|
||||
scan_dvbca(dd);
|
||||
if (dd->use_ca)
|
||||
scan_dvbca(dd);
|
||||
}
|
||||
|
||||
|
||||
|
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;
|
||||
}
|
@@ -331,12 +331,10 @@ static void calc_lq(struct dddvb_fe *fe)
|
||||
int64_t str, snr;
|
||||
uint32_t mod, fec, ber_num, ber_den, trans, pilot = 0, quality = 0, freq, rate;
|
||||
|
||||
get_property(fe->fd, DTV_TRANSMISSION_MODE, &fe->pls_code);
|
||||
dbgprintf(DEBUG_DVB, "fe%d: pls=0x%02x\n", fe->nr, fe->pls_code);
|
||||
|
||||
get_stat(fe->fd, DTV_STAT_SIGNAL_STRENGTH, &st);
|
||||
str = st.stat[0].svalue;
|
||||
dbgprintf(DEBUG_DVB, "fe%d: str=%lld\n", fe->nr, str);
|
||||
dbgprintf(DEBUG_DVB, "fe%d: str=%lld\n", fe->nr, (long long int)str);
|
||||
fe->strength = str;
|
||||
str = (str * 48) / 10000 + 344;
|
||||
if (str < 0)
|
||||
@@ -360,7 +358,7 @@ static void calc_lq(struct dddvb_fe *fe)
|
||||
ber_den = st.stat[0].uvalue;
|
||||
|
||||
dbgprintf(DEBUG_DVB, "fe%d: snr=%lld ber=%llu/%llu\n",
|
||||
fe->nr, snr, ber_num, ber_den);
|
||||
fe->nr, (long long int)snr,(long long int) ber_num,(long long int) ber_den);
|
||||
dbgprintf(DEBUG_DVB, "fe%d: fec=%u mod=%u\n", fe->nr, fec, mod);
|
||||
get_property(fe->fd, DTV_FREQUENCY, &freq);
|
||||
dbgprintf(DEBUG_DVB, "fe%d: actual frequency=%u\n", fe->nr, freq);
|
||||
@@ -368,9 +366,17 @@ static void calc_lq(struct dddvb_fe *fe)
|
||||
dbgprintf(DEBUG_DVB, "fe%d: actual symbol rate=%u\n", fe->nr, rate);
|
||||
switch (fe->n_param.param[PARAM_MSYS]) {
|
||||
case SYS_DVBS:
|
||||
get_property(fe->fd, DTV_INVERSION, &fe->inversion);
|
||||
get_property(fe->fd, DTV_ROLLOFF, &fe->rolloff);
|
||||
dbgprintf(DEBUG_DVB, "fe%d: inversion=%u rolloff=%u\n", fe->nr, fe->inversion, fe->rolloff);
|
||||
quality = dvbsq(snr, fec, ber_num, ber_den);
|
||||
break;
|
||||
case SYS_DVBS2:
|
||||
get_property(fe->fd, DTV_TRANSMISSION_MODE, &fe->pls_code);
|
||||
dbgprintf(DEBUG_DVB, "fe%d: pls=0x%02x\n", fe->nr, fe->pls_code);
|
||||
get_property(fe->fd, DTV_INVERSION, &fe->inversion);
|
||||
get_property(fe->fd, DTV_ROLLOFF, &fe->rolloff);
|
||||
dbgprintf(DEBUG_DVB, "fe%d: inversion=%u rolloff=%u\n", fe->nr, fe->inversion, fe->rolloff);
|
||||
quality = dvbs2q(snr, fec, mod, ber_num, ber_den);
|
||||
break;
|
||||
case SYS_DVBC_ANNEX_A:
|
||||
|
Reference in New Issue
Block a user