128 Commits

Author SHA1 Message Date
rjkm
0b54436695 correct version number 2025-01-21 21:46:39 +01:00
rjkm
a986a98b96 return PLS in transmission_mode 2024-11-16 14:34:24 +01:00
rjkm
345c3b8e0d fix compilation with newer kernels 2024-11-16 14:25:10 +01:00
rjkm
b172e83a4b show XO2 firmware version 2024-11-16 14:24:07 +01:00
rjkm
5fef324ea0 add support for license setting via MCI commands (only FSM cards for now) 2024-10-20 22:39:37 +02:00
rjkm
63f693946c make new compiler warning settings happy 2024-09-19 10:54:57 +02:00
rjkm
17b741b01d support 16 channel DVB-T card 2024-09-19 10:53:23 +02:00
rjkm
8e4379ef3e only allow values between 0-3 2024-09-19 10:52:37 +02:00
rjkm
1022b26d7f cleanup init for FSM and DVB-T cards 2024-09-19 10:51:57 +02:00
rjkm
59cbab6383 prevent lockup 2024-09-19 10:35:39 +02:00
rjkm
0fcd9563f1 only warn about zigzag if max_drift is set 2024-09-19 10:34:30 +02:00
rjkm
cf64ad4b0e show more information about card connected at GT link 2024-09-19 10:33:25 +02:00
rjkm
1c88e05931 factor out setting of input 2024-09-19 10:31:41 +02:00
rjkm
11b8c21cb5 revert ignoring of bad packets at startup 2024-09-19 10:29:48 +02:00
rjkm
3cc98a4995 adapt to newer kernel version 2024-09-19 10:28:59 +02:00
rjkm
0c328cd989 do not allow unaligned access 2024-09-19 10:23:58 +02:00
rjkm
ffbef1488e remove unused tasklet struct 2024-09-19 10:22:46 +02:00
rjkm
8badef38a7 use correct lib name 2024-09-19 10:19:51 +02:00
rjkm
5d47dbec26 add 16 channel version of DVB-T modulator 2024-09-19 10:18:51 +02:00
drmocm
0368446256 modulator info 2024-07-11 13:57:59 +02:00
drmocm
07d5675b06 some information for DVB-T modulators 2024-07-11 13:50:17 +02:00
rjkm
ea8e877dca use dvb_filter.h only locally 2024-04-26 16:33:45 +02:00
rjkm
9ec5f40324 also install dvb_filter.h 2024-04-26 16:17:43 +02:00
rjkm
50e230b48d add dvb filter 2024-03-29 14:05:49 +01:00
rjkm
4197d9a59e make copying to/from CA device more robust, add TDT callback 2024-03-29 14:04:33 +01:00
rjkm
62b0b57c5d Add some more comments to MCI API documentation. 2024-03-26 22:36:05 +01:00
rjkm
fe63f1d0b8 Change assignment of devices when using kernel dvb-core.
Modulators are now osdX.
2024-03-26 22:34:52 +01:00
rjkm
dc384c70af Add input select via configurable DiSeqC message. 2024-03-26 22:30:23 +01:00
rjkm
4e0bf8b182 Add reset function. 2024-03-26 22:28:31 +01:00
rjkm
e7390e1cd8 Ignore errors at start, they are from aold data in buffers/FIFOs. 2024-03-26 22:27:43 +01:00
rjkm
d54905cc14 Remove ISDB entries when using kernel dvb-core because array is too small.
ISDB modes are then not enumerated but still work.
2024-03-26 22:22:52 +01:00
rjkm
7779445112 Add example for 2 regions in DVB-C and move modulator.conf to modulator-t.conf 2024-03-26 22:21:09 +01:00
rjkm
3ba2128c4e Support several channel regions. They have to start with frequency now! 2024-03-26 22:17:41 +01:00
rjkm
8f2bf94b43 Add some comments about using kernel dvb-core. 2024-03-26 22:16:18 +01:00
rjkm
a927449610 Merge branch 'internal' of hippo:rjkm/dddvb into internal 2024-03-10 21:45:55 +01:00
rjkm
3295328aa9 Merge branch 'internal' of hippo:rjkm/dddvb into internal 2024-03-10 21:45:09 +01:00
drmocm
2b53b34350 even longer device filenames 2024-03-08 09:19:46 +01:00
rjkm
a6f022941f remove gt link tasklet code 2024-03-08 00:33:57 +01:00
rjkm
da1594d424 prevent warning if KERNEL_DVB_CORE=y is used 2024-03-08 00:19:22 +01:00
drmocm
32afa3e920 changed dvb file name length to 60 2024-03-07 19:42:49 +01:00
f8726493b1 adapt defines to make KERNEL_DVB_CORE (compile against kernel dvb-core) work again 2024-03-06 17:07:08 +01:00
525472b9f1 0.9.39 release 2024-02-13 12:54:51 +01:00
7423903c67 add ci power error bit define 2024-02-08 23:15:23 +01:00
690289c338 arm64 cannot handle unaligned readl 2024-02-08 22:57:40 +01:00
09021aec73 fix for older KERNELS 2024-02-05 10:33:20 +01:00
a1c604f212 decoding support 2024-02-05 10:27:55 +01:00
1124f00b34 increase slot reset time 2024-01-30 17:18:17 +01:00
70a119c0db read back correct values if using old API emulation 2023-12-13 19:05:22 +01:00
123291b26e adjust M8/M8A tuner type selection 2023-12-13 19:04:12 +01:00
85f8f5d2bd do not get extra status data as default 2023-12-13 19:03:18 +01:00
4d0c806262 use stricter locking in case somebody still uses redirect (deprecated) 2023-12-13 19:02:11 +01:00
9e6e34b857 adjust gitignore 2023-12-13 18:54:45 +01:00
327cc09d34 dvb_math functions moved to int_log 2023-12-13 16:44:12 +01:00
adaeb94a54 Merge branch 'internal' 2023-11-23 21:31:01 +01:00
570864a576 support gain with new MCI API 2023-11-23 21:30:20 +01:00
c681e4f24a support old gain command for new MCI firmware 2023-11-23 21:27:19 +01:00
0628769620 Merge branch 'internal' 2023-11-14 14:32:56 +01:00
934c619bcb documentation of modulator MCI API 2023-11-14 14:31:22 +01:00
847b8611bd Merge branch 'internal' 2023-11-07 23:17:35 +01:00
be74b9630f increase in case somebody does not use adapter_alloc=3 and gets tons of adapters 2023-11-07 23:16:24 +01:00
3d17ab8de5 add range checks 2023-11-07 23:16:12 +01:00
b76aa3c0c2 Merge branch 'internal' 2023-11-07 22:41:47 +01:00
ca9613d911 increase retry time to 4s 2023-11-07 22:41:03 +01:00
0daf0f79ae Merge branch 'internal' 2023-11-07 22:30:09 +01:00
drmocm
3884037c93 remove warnings 2023-11-07 10:06:30 +01:00
f23789e90c Merge branch 'internal' 2023-11-06 10:26:19 +01:00
0c603bc421 there is no more output_tasklet 2023-11-04 21:34:20 +01:00
f23648f938 only use dvb_attach if enabled 2023-11-03 14:11:25 +01:00
d8f3d40352 also output set value and make timeout clearer 2023-11-03 14:10:29 +01:00
de5051a85a add safety checks 2023-11-03 13:39:54 +01:00
d63916cba1 re-add workqueue and make WQ or tasklet selectable by module parameter
default to WQ for ARM64
(some SOCs use only one little A53 core for all MSI IRQs and
tasklets on the same core cannot process more than 10 TS streams
in uncached coherent memory)
2023-11-03 13:33:57 +01:00
3ef783c393 default to alt_dma for arm64 (coherent memory is slow/uncached) and some cleanup in alt_dma handling 2023-11-03 13:31:13 +01:00
cf7f19b8bc change handling of raw_stream value so that 1 just turns it on but does not change control register 2023-11-03 13:28:09 +01:00
0ad8eff8af make iq mode always lock 2023-11-03 13:04:37 +01:00
a0d4605ad8 return correct error stat instead of -1 2023-11-03 11:26:45 +01:00
948234d787 lock reader, write and user counts with mutex 2023-11-03 11:21:28 +01:00
05718a5965 extend sample Unicable table 2023-11-03 11:15:28 +01:00
aedb0a1b64 allow for longer lock time before retry 2023-11-03 11:13:56 +01:00
76697f420f add some more debugging messages 2023-11-03 11:12:52 +01:00
6c7a754004 add inversion and rolloff fields 2023-11-03 11:11:39 +01:00
bf85718376 also show rolloff and inversion state 2023-11-03 11:10:31 +01:00
5f8c0cb75a add DVB-C sample config 2023-11-03 11:01:11 +01:00
accad41c2c also support CI M2 2023-11-03 11:00:14 +01:00
72181bd0ad Allow workqueue on all CPUs 2023-10-24 23:36:36 +02:00
100aa25176 Merge branch 'internal' 2023-10-02 11:58:43 +02:00
73317671a3 Some CAMs do not reset properly. So, turn off power before slot reset. 2023-09-30 21:39:54 +02:00
f77d50e526 comment out debug messages 2023-09-29 16:59:00 +02:00
drmocm
25c730789d better stream set 2023-09-16 16:19:04 +02:00
drmocm
775ddf72ef s 2023-09-16 16:09:47 +02:00
drmocm
7b23c917d3 qam 2023-09-16 16:07:54 +02:00
drmocm
d91b2b7813 wrong qam table 2023-09-16 15:55:16 +02:00
drmocm
58c608ab30 set correct delsys 2023-09-16 15:12:18 +02:00
drmocm
8dc2fd062f stuff 2023-09-16 15:08:24 +02:00
drmocm
33ed0ec27c more stuff 2023-09-16 15:00:27 +02:00
drmocm
1ca4a8cea5 more changes 2023-09-16 14:56:27 +02:00
drmocm
bb1408a98a more changes 2023-09-16 14:52:32 +02:00
drmocm
9af63d41f7 new tuning for dvbc 2023-09-16 14:41:46 +02:00
95d23821b7 adapt to mainline kernel 2023-09-12 15:06:23 +02:00
059bfbb76e Merge branch 'internal' 2023-09-12 14:59:10 +02:00
454bb63993 use EXPORT_SYMBOL_GPL for frontends to fix problems with kernel 6.5.2 2023-09-12 14:57:09 +02:00
5b83e68887 Merge branch 'internal' 2023-09-05 14:29:23 +02:00
fc043cc914 Merge branch 'internal' 2023-08-01 22:29:25 +02:00
4d583fd5f4 Merge branch 'internal' 2023-07-22 19:52:27 +02:00
2c75179530 Merge branch 'internal' 2023-05-11 14:25:51 +02:00
rjkm
a443c3e8de Merge branch 'internal' 2023-03-03 13:47:11 +01:00
internal
979cb7a237 Merge branch 'internal' 2022-12-13 14:18:04 +01:00
internal
c86cb59638 Merge branch 'internal' 2022-12-12 11:39:23 +01:00
internal
31589952a8 Merge branch 'internal' 2022-11-17 15:21:27 +01:00
internal
f125fd503c Merge branch 'internal' 2022-10-31 21:06:38 +01:00
internal
00b0036b33 Merge branch 'internal' 2022-10-28 15:20:02 +02:00
internal
83a6dc3a1d Merge branch 'internal' 2022-10-26 15:58:36 +02:00
internal
ab4b0c8306 Merge branch 'internal' 2022-06-07 18:11:35 +02:00
internal
e0539d5074 Merge branch 'internal' 2022-05-02 21:41:27 +02:00
internal
d0793274d2 Merge branch 'internal' 2022-03-22 15:23:26 +01:00
internal
fb4f263aa3 Merge branch 'internal' 2022-03-21 17:40:59 +01:00
rjkm
e9ccab3578 Merge branch 'internal' 2022-02-20 23:22:36 +01:00
rjkm
a5f3b75d0a Merge branch 'internal' 2022-02-16 15:55:04 +01:00
rjkm
f02b135bdb Merge branch 'internal' 2021-12-06 15:15:18 +01:00
rjkm
ec655e1438 Merge branch 'internal' 2021-09-23 15:07:58 +02:00
rjkm
81793729e6 Merge branch 'internal' 2021-09-19 19:06:35 +02:00
rjkm
8986494cd3 Merge branch 'internal' 2021-08-20 14:36:46 +02:00
rjkm
fbc39f71f4 Merge branch 'internal' 2021-08-09 09:04:33 +02:00
none
ccc13aed48 Merge branch 'internal' 2021-06-23 16:30:26 +02:00
none
0fe2c2feb3 Merge branch 'internal' 2021-06-22 20:52:59 +02:00
none
4a93d1056a Merge branch 'internal' 2021-06-08 14:02:28 +02:00
none
bfddf62f64 Merge branch 'internal' 2021-06-08 10:49:43 +02:00
none
1d96274993 Merge branch 'internal' 2021-06-07 17:12:12 +02:00
none
23bdd90595 Merge branch 'internal' 2021-04-09 12:54:23 +02:00
69 changed files with 1883 additions and 1537 deletions

10
.gitignore vendored
View File

@@ -1,7 +1,3 @@
#
# Normal rules
#
.*
*.o
*.o.*
@@ -11,5 +7,9 @@
*.so
*.so.dbg
*.orig
*.mod.c
*.ko
*~
\#*#
\#*#
Module.symvers
modules.order

View File

@@ -3,13 +3,14 @@ MDIR ?=
KDIR ?= /lib/modules/$(kernelver)/build
PWD := $(shell pwd)
MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CXD2099=m CONFIG_DVB_LNBP21=m CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m CONFIG_DVB_STV0367=m CONFIG_DVB_TDA18212=m CONFIG_DVB_STV0367DD=m CONFIG_DVB_TDA18212DD=m CONFIG_DVB_OCTONET=m CONFIG_DVB_CXD2843=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6111=m CONFIG_DVB_LNBH25=m CONFIG_DVB_MXL5XX=m CONFIG_DVB_NET=y DDDVB=y
MODDEFS := CONFIG_DVB_CORE=m CONFIG_DVB_DDBRIDGE=m CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m CONFIG_DVB_CXD2099=m CONFIG_DVB_LNBP21=m CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m CONFIG_DVB_STV0367=m CONFIG_DVB_TDA18212=m CONFIG_DVB_STV0367DD=m CONFIG_DVB_TDA18212DD=m CONFIG_DVB_OCTONET=m CONFIG_DVB_CXD2843=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6111=m CONFIG_DVB_LNBH25=m CONFIG_DVB_MXL5XX=m DDDVB=y
KBUILD_EXTMOD = $(PWD)
ifeq ($(KERNEL_DVB_CORE),y)
DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD) -DKERNEL_DVB_CORE=y"
else
MODDEFS += CONFIG_DVB_NET=y
DDDVB_INC = "--include=$(KBUILD_EXTMOD)/include/dd_compat.h -I$(KBUILD_EXTMOD)/frontends -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux"
endif

View File

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

View File

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

View File

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

View File

@@ -30,7 +30,7 @@ char *Rolloff[8] = {
"rsvd",
};
void dump(const uint8_t *b, int l)
void dump(uint8_t *b, int l)
{
int i, j;
@@ -45,6 +45,15 @@ void dump(const uint8_t *b, int l)
}
}
void ldump(uint8_t *b, int l)
{
int i;
for (i = 0; i < l; i++)
printf("%02X", b[i]);
printf("\n");
}
void print_temp(struct mci_result *res)
{
printf("Die temperature = %u\n", res->sx8_bist.temperature);
@@ -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
View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX -DCONFIG_DVB_CXD2099 -DCONFIG_DVB_NET
EXTRA_CFLAGS += -DCONFIG_DVB_CXD2843 -DCONFIG_DVB_LNBP21 -DCONFIG_DVB_STV090x -DCONFIG_DVB_STV6110x -DCONFIG_DVB_DRXK -DCONFIG_DVB_STV0910 -DCONFIG_DVB_STV6111 -DCONFIG_DVB_LNBH25 -DCONFIG_DVB_MXL5XX -DCONFIG_DVB_CXD2099 -DCONFIG_DVB_NET -DCONFIG_DVB_TDA18271C2DD
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o

View File

@@ -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);

View File

@@ -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, &reg, 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;

View File

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

View File

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

View File

@@ -388,7 +388,7 @@ fail:
ddb_unmap(dev);
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
return -1;
return stat;
}
/****************************************************************************/

View File

@@ -48,6 +48,11 @@ static int no_voltage;
module_param(no_voltage, int, 0444);
MODULE_PARM_DESC(no_voltage, "Do not enable voltage on LNBH (will also disable 22KHz tone).");
static u8 input_diseqc_sequence[6] = { 0x00 };
static int input_diseqc_sequence_length = 1;
module_param_array(input_diseqc_sequence, byte, &input_diseqc_sequence_length, 0444);
MODULE_PARM_DESC(input_diseqc_sequence, "DiSEqC sequence to select input. Last byte & 15 selects input.");
/* MAX LNB interface related functions */
static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
@@ -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)

View File

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

View File

@@ -452,18 +452,20 @@ int ddbridge_mod_output_start(struct ddb_output *output)
static int mod_write_max2871(struct ddb *dev, u32 val)
{
u32 retry = 100;
ddbwritel(dev, val, MAX2871_OUTDATA);
ddbwritel(dev, MAX2871_CONTROL_CE | MAX2871_CONTROL_WRITE,
MAX2871_CONTROL);
while (1) {
while (--retry) {
u32 ControlReg = ddbreadl(dev, MAX2871_CONTROL);
if (ControlReg == 0xFFFFFFFF)
return -EIO;
if ((ControlReg & MAX2871_CONTROL_WRITE) == 0)
break;
if ((ControlReg & MAX2871_CONTROL_WRITE) == 0)
return 0;
udelay(10);
}
return 0;
return -EIO;
}
static u32 max2871_fsm[6] = {
@@ -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;
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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

View File

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

View File

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

181
docs/modulator_mci_api Normal file
View 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;
};
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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++)

View File

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

View File

@@ -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);

View File

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

View File

@@ -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");

View File

@@ -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");

View File

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

View File

@@ -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");

View File

@@ -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");

View File

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

View File

@@ -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");

View File

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

View File

@@ -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");

View File

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

View File

@@ -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");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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

View File

@@ -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_*/

View File

@@ -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

View File

@@ -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;
};
/**

View File

@@ -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);

View File

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

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -13,6 +13,10 @@
#include <linux/dvb/net.h>
#include <libucsi/dvb/section.h>
#include <libucsi/mpeg/section.h>
#include <libucsi/section.h>
#include <libucsi/section_buf.h>
#include <libdvben50221/en50221_stdcam.h>
#define DDDVB_MAX_DVB_FE 256
@@ -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);

View File

@@ -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

View File

@@ -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
View File

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

View File

@@ -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: