Compare commits

...

227 Commits

Author SHA1 Message Date
rjkm
710f9c6fbc add M8E 2025-02-25 15:55:23 +01:00
rjkm
849d9ec10f add M8E defines 2025-02-24 21:41:42 +01:00
rjkm
a79f57a675 add MAX M2 2025-02-24 20:25:34 +01:00
rjkm
0690bf6882 add new M8 2025-02-14 13:26:18 +01:00
rjkm
f5fcda81dc new version 2025-02-14 13:25:35 +01:00
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
internal
f8726493b1 adapt defines to make KERNEL_DVB_CORE (compile against kernel dvb-core) work again 2024-03-06 17:07:08 +01:00
internal
525472b9f1 0.9.39 release 2024-02-13 12:54:51 +01:00
internal
7423903c67 add ci power error bit define 2024-02-08 23:15:23 +01:00
internal
690289c338 arm64 cannot handle unaligned readl 2024-02-08 22:57:40 +01:00
internal
09021aec73 fix for older KERNELS 2024-02-05 10:33:20 +01:00
internal
a1c604f212 decoding support 2024-02-05 10:27:55 +01:00
internal
1124f00b34 increase slot reset time 2024-01-30 17:18:17 +01:00
internal
70a119c0db read back correct values if using old API emulation 2023-12-13 19:05:22 +01:00
internal
123291b26e adjust M8/M8A tuner type selection 2023-12-13 19:04:12 +01:00
internal
85f8f5d2bd do not get extra status data as default 2023-12-13 19:03:18 +01:00
internal
4d0c806262 use stricter locking in case somebody still uses redirect (deprecated) 2023-12-13 19:02:11 +01:00
internal
9e6e34b857 adjust gitignore 2023-12-13 18:54:45 +01:00
internal
327cc09d34 dvb_math functions moved to int_log 2023-12-13 16:44:12 +01:00
internal
adaeb94a54 Merge branch 'internal' 2023-11-23 21:31:01 +01:00
internal
570864a576 support gain with new MCI API 2023-11-23 21:30:20 +01:00
internal
c681e4f24a support old gain command for new MCI firmware 2023-11-23 21:27:19 +01:00
internal
0628769620 Merge branch 'internal' 2023-11-14 14:32:56 +01:00
internal
934c619bcb documentation of modulator MCI API 2023-11-14 14:31:22 +01:00
internal
847b8611bd Merge branch 'internal' 2023-11-07 23:17:35 +01:00
internal
be74b9630f increase in case somebody does not use adapter_alloc=3 and gets tons of adapters 2023-11-07 23:16:24 +01:00
internal
3d17ab8de5 add range checks 2023-11-07 23:16:12 +01:00
internal
b76aa3c0c2 Merge branch 'internal' 2023-11-07 22:41:47 +01:00
internal
ca9613d911 increase retry time to 4s 2023-11-07 22:41:03 +01:00
internal
0daf0f79ae Merge branch 'internal' 2023-11-07 22:30:09 +01:00
drmocm
3884037c93 remove warnings 2023-11-07 10:06:30 +01:00
internal
f23789e90c Merge branch 'internal' 2023-11-06 10:26:19 +01:00
internal
0c603bc421 there is no more output_tasklet 2023-11-04 21:34:20 +01:00
internal
f23648f938 only use dvb_attach if enabled 2023-11-03 14:11:25 +01:00
internal
d8f3d40352 also output set value and make timeout clearer 2023-11-03 14:10:29 +01:00
internal
de5051a85a add safety checks 2023-11-03 13:39:54 +01:00
internal
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
internal
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
internal
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
internal
0ad8eff8af make iq mode always lock 2023-11-03 13:04:37 +01:00
internal
a0d4605ad8 return correct error stat instead of -1 2023-11-03 11:26:45 +01:00
internal
948234d787 lock reader, write and user counts with mutex 2023-11-03 11:21:28 +01:00
internal
05718a5965 extend sample Unicable table 2023-11-03 11:15:28 +01:00
internal
aedb0a1b64 allow for longer lock time before retry 2023-11-03 11:13:56 +01:00
internal
76697f420f add some more debugging messages 2023-11-03 11:12:52 +01:00
internal
6c7a754004 add inversion and rolloff fields 2023-11-03 11:11:39 +01:00
internal
bf85718376 also show rolloff and inversion state 2023-11-03 11:10:31 +01:00
internal
5f8c0cb75a add DVB-C sample config 2023-11-03 11:01:11 +01:00
internal
accad41c2c also support CI M2 2023-11-03 11:00:14 +01:00
internal
72181bd0ad Allow workqueue on all CPUs 2023-10-24 23:36:36 +02:00
internal
100aa25176 Merge branch 'internal' 2023-10-02 11:58:43 +02:00
internal
73317671a3 Some CAMs do not reset properly. So, turn off power before slot reset. 2023-09-30 21:39:54 +02:00
internal
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
internal
95d23821b7 adapt to mainline kernel 2023-09-12 15:06:23 +02:00
internal
059bfbb76e Merge branch 'internal' 2023-09-12 14:59:10 +02:00
internal
454bb63993 use EXPORT_SYMBOL_GPL for frontends to fix problems with kernel 6.5.2 2023-09-12 14:57:09 +02:00
internal
5b83e68887 Merge branch 'internal' 2023-09-05 14:29:23 +02:00
internal
da4938e3aa use correct input 2023-09-05 14:28:05 +02:00
internal
3439fd7725 Merge branch 'internal' of hippo:rjkm/dddvb into internal 2023-08-01 22:31:15 +02:00
internal
fc043cc914 Merge branch 'internal' 2023-08-01 22:29:25 +02:00
internal
818b9cb58d support CI M2, M8 and M8A 2023-08-01 22:27:55 +02:00
internal
0bafbf534f support alternative modulation types 2023-08-01 22:27:55 +02:00
internal
e5072debc0 change lnb and ci bases to be configurable 2023-08-01 22:27:55 +02:00
internal
2f49ece88c cleanup 2023-08-01 22:27:55 +02:00
internal
52b40198eb only warn once about zigzag scanning 2023-08-01 22:27:55 +02:00
internal
98f98fea0e adjust to 6.4.0 kernel change 2023-08-01 22:27:55 +02:00
internal
ccfdc2b984 fix frontend allocation 2023-08-01 22:27:55 +02:00
internal
9c920141ca adjust usage count for frontends which do not have their own module 2023-08-01 22:27:55 +02:00
internal
6c2bbbe5b8 add ddb_mci_cmd_link_simple() 2023-08-01 22:27:55 +02:00
internal
3eaae81e6a adapt MCI defines to firmware 2023-08-01 22:27:55 +02:00
internal
aae6233b14 class has no owner field in kernel version >= 6.4.0 2023-08-01 22:27:55 +02:00
internal
c8f3c122af let SSI be set (default 0 is ste in dvb-core), correct tuner/demod settings 2023-08-01 22:27:55 +02:00
internal
7258b32045 add CI M2, M8 and M8A 2023-08-01 22:27:55 +02:00
internal
c2a2a27500 appease conversion warnings 2023-08-01 22:27:55 +02:00
internal
847aa3c044 flen was not defined yet, so move after assignment 2023-08-01 22:27:55 +02:00
internal
48d9945769 change flashdump to void 2023-08-01 22:27:55 +02:00
internal
307ce85223 select image start according to reg 0x10 2023-08-01 22:27:55 +02:00
internal
23b2e6d6a0 missing return value 2023-08-01 22:27:55 +02:00
internal
647e8d77c3 remove PCR mode setting 2023-08-01 22:27:55 +02:00
internal
4943ea294a rename M4_ defines to MX_ 2023-08-01 22:27:55 +02:00
internal
7118ecd9f5 adjust image start to card type 2023-08-01 22:27:55 +02:00
internal
02ded87d78 support CI M2, M8 and M8A 2023-07-31 22:31:44 +02:00
internal
9698b87204 support alternative modulation types 2023-07-31 22:31:23 +02:00
internal
4d087a3b8c change lnb and ci bases to be configurable 2023-07-31 22:29:08 +02:00
internal
a233c8a6f8 cleanup 2023-07-31 22:14:53 +02:00
internal
e55ef2f0fb only warn once about zigzag scanning 2023-07-31 22:10:05 +02:00
internal
a2f011f62d adjust to 6.4.0 kernel change 2023-07-31 22:08:22 +02:00
internal
7250608d53 fix frontend allocation 2023-07-31 22:07:40 +02:00
internal
5e5ff60b21 adjust usage count for frontends which do not have their own module 2023-07-31 22:04:49 +02:00
internal
060eac06b8 add ddb_mci_cmd_link_simple() 2023-07-31 22:02:11 +02:00
internal
dfde99c01e adapt MCI defines to firmware 2023-07-31 21:59:37 +02:00
internal
73f270d850 class has no owner field in kernel version >= 6.4.0 2023-07-31 21:37:50 +02:00
internal
781177ea44 let SSI be set (default 0 is ste in dvb-core), correct tuner/demod settings 2023-07-31 21:35:57 +02:00
internal
330f2c1821 add CI M2, M8 and M8A 2023-07-31 21:30:56 +02:00
internal
3fc610f546 appease conversion warnings 2023-07-31 21:30:29 +02:00
internal
c522f28d68 flen was not defined yet, so move after assignment 2023-07-31 21:29:44 +02:00
internal
0fa14cca02 change flashdump to void 2023-07-31 21:29:07 +02:00
internal
ed14095a2f select image start according to reg 0x10 2023-07-31 21:28:24 +02:00
internal
456886f4fb missing return value 2023-07-31 21:23:27 +02:00
internal
abbb9e324a remove PCR mode setting 2023-07-31 21:22:45 +02:00
internal
e18b425f41 rename M4_ defines to MX_ 2023-07-31 21:21:45 +02:00
internal
88e65b4db6 adjust image start to card type 2023-07-22 21:28:35 +02:00
internal
4d583fd5f4 Merge branch 'internal' 2023-07-22 19:52:27 +02:00
internal
f27b64b186 remove Octopus Net Pro IDs 2023-07-22 19:48:59 +02:00
internal
7478bcffb9 forgot to check in setmod1.c 2023-07-22 19:48:59 +02:00
internal
0d9b5ca619 prevent clean error in case test.ts does not exist 2023-07-22 19:48:59 +02:00
internal
e9399971f8 adapt to mainline kernel changes 2023-07-22 19:48:59 +02:00
internal
626aa6d7be device pointer is const now 2023-07-22 19:48:59 +02:00
internal
5bfa228d71 clean up app directory 2023-07-22 19:48:59 +02:00
internal
42df1e88d4 add messages to see what is going on 2023-07-22 19:48:59 +02:00
internal
57101c22b7 adapt to upstream header style 2023-07-22 19:48:59 +02:00
internal
37e423d19b add DVB-C2 2023-07-22 19:48:58 +02:00
internal
17914cb451 remove Octopus Net Pro IDs 2023-07-12 22:42:46 +02:00
internal
25009b3afd forgot to check in setmod1.c 2023-06-12 11:32:14 +02:00
internal
2c75179530 Merge branch 'internal' 2023-05-11 14:25:51 +02:00
internal
58535dd4e3 prevent clean error in case test.ts does not exist 2023-05-11 14:06:34 +02:00
internal
b51b7c0598 adapt to mainline kernel changes 2023-05-11 14:06:34 +02:00
internal
e9ed73b929 device pointer is const now 2023-05-11 14:06:34 +02:00
internal
c0e174505a clean up app directory 2023-05-11 14:06:34 +02:00
internal
87478ec63a add messages to see what is going on 2023-05-11 14:06:34 +02:00
internal
4f9cb2810e adapt to upstream header style 2023-05-11 14:06:34 +02:00
internal
5988565066 add DVB-C2 2023-05-11 14:06:34 +02:00
rjkm
6e4f8dc86b hardware DVB-T can only do 14 channels 2023-03-05 23:27:58 +01:00
drmocm
5d876b2615 edited help info 2023-03-05 23:27:58 +01:00
drmocm
2968f85c91 limit the number of modulators used with -m option 2023-03-05 23:27:58 +01:00
rjkm
a443c3e8de Merge branch 'internal' 2023-03-03 13:47:11 +01:00
rjkm
c008e44bf6 hardware DVB-T can only do 14 channels 2023-03-03 13:44:57 +01:00
internal
7e9650c841 add actual frequency and symbol rate to debug output 2023-03-03 13:44:57 +01:00
internal
a6565abde3 emulate old API for latest FSM firmware 2023-03-03 13:44:57 +01:00
internal
ee7c48e6ff return actual modulation for DVB-C 2023-03-03 13:44:57 +01:00
internal
6ce49ed990 return actual symbol rate for all delivery systems 2023-03-03 13:44:57 +01:00
internal
0b36a69c44 check if MCI interface present 2023-03-03 13:44:57 +01:00
internal
e64ceb90fb simplify dummy frontend config 2023-03-03 13:44:57 +01:00
internal
efbf312d98 include link and port number in debug message 2023-03-03 13:44:57 +01:00
drmocm
0c3c1f5753 edited help info 2023-02-04 16:13:10 +01:00
drmocm
4bf1f48926 limit the number of modulators used with -m option 2023-02-04 15:19:11 +01:00
internal
979cb7a237 Merge branch 'internal' 2022-12-13 14:18:04 +01:00
internal
7ce5232cd7 add actual frequency and symbol rate to debug output 2022-12-13 13:45:33 +01:00
internal
3f296bef62 emulate old API for latest FSM firmware 2022-12-13 13:44:34 +01:00
internal
ad01e9f508 return actual modulation for DVB-C 2022-12-13 13:34:22 +01:00
internal
e312df576c return actual symbol rate for all delivery systems 2022-12-13 13:33:57 +01:00
internal
4b5cd433f9 check if MCI interface present 2022-12-13 13:33:09 +01:00
internal
6c068c0cc3 simplify dummy frontend config 2022-12-13 13:32:03 +01:00
internal
1488f326d0 include link and port number in debug message 2022-12-13 13:31:02 +01:00
internal
c86cb59638 Merge branch 'internal' 2022-12-12 11:39:23 +01:00
internal
c78905d4a2 keep original FSM card id if old license id is 7 2022-12-12 11:24:45 +01:00
internal
31589952a8 Merge branch 'internal' 2022-11-17 15:21:27 +01:00
internal
7eb5c6e658 read back actual symbol rate 2022-11-17 15:13:15 +01:00
internal
172c6c93ba do not create test.ts by default 2022-11-10 14:15:41 +01:00
internal
f125fd503c Merge branch 'internal' 2022-10-31 21:06:38 +01:00
internal
0dd4f106ab fix port number detection on revision 1 FSM cards 2022-10-30 23:23:44 +01:00
internal
60426304db add MDIR again but use proper empty default 2022-10-30 23:22:35 +01:00
internal
00b0036b33 Merge branch 'internal' 2022-10-28 15:20:02 +02:00
internal
177e71d62a INSTALL_MOD_PATH=$(MDIR) does not work, partially revert "fix" 2022-10-28 15:18:46 +02:00
internal
83a6dc3a1d Merge branch 'internal' 2022-10-26 15:58:36 +02:00
drmocm
cc03d96de2 added modtest.c 2022-10-26 13:16:21 +02:00
internal
6336bd3689 comment out test init 2022-10-25 19:35:16 +02:00
internal
be79cec76e set legacy signal strength workaround according to channel number 2022-10-25 19:33:25 +02:00
internal
24801ab41a add error return values 2022-10-25 19:32:51 +02:00
internal
390f67c03b remove modulator calls for octonet 2022-10-25 19:32:00 +02:00
internal
fa4e3331d8 move compatibility stuff to dd_compat.h 2022-10-25 19:30:52 +02:00
internal
29cc552a6b not only used on exit, also on failed init 2022-10-25 19:29:38 +02:00
internal
42a0b65235 use correct pointer type 2022-10-25 19:28:36 +02:00
internal
b8abf46d06 add consts 2022-10-25 19:27:44 +02:00
internal
ce06e50881 remove modulator from octonet 2022-10-25 19:25:05 +02:00
internal
22ffb0ecac allow alternative modules dir 2022-10-25 19:23:06 +02:00
internal
92f2132d79 fix printf type 2022-10-25 19:23:06 +02:00
internal
727fba48be ringbuffer fix from upstream 2022-10-25 19:23:06 +02:00
internal
09e8a15d78 Add clean for apps directory. 2022-10-25 19:23:06 +02:00
internal
45c9f076bd Do not use BIT_ULL, because older kernels do not have it. 2022-10-25 19:23:06 +02:00
internal
5c2757d581 Use eth_hw_addr_set in newer kernels. 2022-10-25 19:23:06 +02:00
drmocm
817a464f4a same Makefile changes for test.ts 2022-06-21 15:19:04 +02:00
drmocm
d627e6995f added modconfig and chnaged Makefile accordingly 2022-06-21 15:08:25 +02:00
internal
ab4b0c8306 Merge branch 'internal' 2022-06-07 18:11:35 +02:00
internal
c8c1ee1835 style fixes 2022-06-07 16:37:10 +02:00
internal
002f39787a This line somehow got lost when adapting to mainline kernel version.
Signed-off-by: internal
2022-06-07 16:15:10 +02:00
internal
871821d6a0 pci_*_dma_mask no longer exists in 5.18 2022-06-07 16:12:19 +02:00
internal
2a88d220e4 allow MCI commands for SDR cards. 2022-06-04 10:42:22 +02:00
95 changed files with 4173 additions and 2786 deletions

8
.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

@ -1,14 +1,16 @@
kernelver ?= $(shell uname -r)
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
@ -29,10 +31,11 @@ dep:
DIR=`pwd`; (cd $(TOPDIR); make KBUILD_EXTMOD=$$DIR dep)
install: all
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) modules_install
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) INSTALL_MOD_PATH=$(MDIR) modules_install
depmod $(kernelver)
clean:
rm -rf */.*.o.d */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules*
$(MAKE) -C apps clean

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,26 +1,34 @@
all: cit citin flashprog modt ddtest setmod ddflash setmod2 pls setmod3 modconfig ddinfo getiq
TARGETS = cit ddtest setmod1 setmod2 modconfig ddinfo getiq modtest ddlicense
all: $(TARGETS)
CFLAGS = -g -Wall -Wno-unused -Wno-format
FFMPEG := $(shell command -v ffmpeg 2> /dev/null)
modtest: modtest.c
$(CC) -o modtest modtest.c -I../include/ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
test.ts:
ifndef FFMPEG
$(error "ffmpeg is not available please install to create test.ts")
endif
ffmpeg -f lavfi -i testsrc=duration=10:size=1280x720:rate=30 \
-f lavfi -i sine=f=440:b=4 -shortest -metadata \
service_provider="DD" -metadata service_name="Test" test.ts
cit: cit.c
$(CC) -o cit cit.c -lpthread
modt: modt.c
$(CC) -o modt modt.c -lpthread
setmod: setmod.c
$(CC) -o setmod setmod.c -I../include/
setmod2: setmod2.c
$(CC) -o setmod2 setmod2.c -I../include/
setmod3: setmod3.c
$(CC) -o setmod3 setmod3.c -I../include/
modconfig: modconfig.c
$(CC) -o modconfig modconfig.c -I../include/
%: %.c
$(CC) $(CFLAGS) -I../ddbridge -I../include/ $< -o $@
%.o: %.c
$(CC) $(CFLAGS) -I../ddbridge -o $@ $<
clean:
rm test.ts -f
for f in $(TARGETS) *.o *~ ; do \
if [ -e "$$f" ]; then \
rm "$$f" || exit 1; \
fi \
done

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

@ -1,60 +0,0 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
void proc_ts(int i, uint8_t *buf)
{
uint16_t pid=0x1fff&((buf[1]<<8)|buf[2]);
if (buf[3]&0xc0) /* only descrambled packets */
return;
/* only ORF */
if (pid==160 || pid==161 || pid==1001||pid==13001 || pid==0)
write(1, buf, 188);
}
#define TSBUFSIZE (100*188)
void citest()
{
uint8_t *buf;
uint8_t id;
int i, nts;
int len;
int ts=open("/dev/dvb/adapter4/ci0", O_RDONLY);
buf=(uint8_t *)malloc(TSBUFSIZE);
while(1) {
len=read(ts, buf, TSBUFSIZE);
if (len<0) {
continue;
}
if (buf[0]!=0x47) {
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);
}
}
int main()
{
citest();
}

View File

@ -1,55 +0,0 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/video.h>
#define TSBUFSIZE (100*188)
void citest()
{
uint8_t *buf;
uint8_t id;
int i, nts;
int len;
int ts0=open("/dev/dvb/adapter0/dvr0", O_RDONLY);
int ts1=open("/dev/dvb/adapter4/sec0", O_WRONLY);
int demux0=open("/dev/dvb/adapter0/demux0", O_RDWR);
struct dmx_pes_filter_params pesFilterParams;
pesFilterParams.input = DMX_IN_FRONTEND;
pesFilterParams.output = DMX_OUT_TS_TAP;
pesFilterParams.pes_type = DMX_PES_OTHER;
pesFilterParams.flags = DMX_IMMEDIATE_START;
pesFilterParams.pid = 8192;
if (ioctl(demux0, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
printf("Could not set PES filter\n");
return;
}
buf=(uint8_t *)malloc(TSBUFSIZE);
while(1) {
len=read(ts0, buf, TSBUFSIZE);
if (len<=0)
break;
if (buf[0]!=0x47)
printf("oops\n");
write(ts1, buf, len);
}
}
int main()
{
citest();
}

View File

@ -1 +0,0 @@
octonet/ddflash.c

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);
@ -274,7 +283,7 @@ void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res)
if (res->status == MCI_DEMOD_LOCKED) {
switch (res->mode) {
case 0:
case M4_MODE_DVBSX:
case MX_MODE_DVBSX:
if (res->dvbs2_signal_info.standard != 1) {
int short_frame = 0, pilots = 0;
char *modcod = "unknown";
@ -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");
@ -308,10 +318,10 @@ void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res)
}
printf("Inversion: %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off");
break;
case M4_MODE_DVBT:
case MX_MODE_DVBT:
printf("Locked DVB-T\n");
break;
case M4_MODE_DVBT2:
case MX_MODE_DVBT2:
printf("Locked DVB-T2\n");
break;
}
@ -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

@ -1,290 +0,0 @@
/*
/* flashprog - Programmer for flash on Digital Devices Octopus
*
* Copyright (C) 2010-2011 Digital Devices GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <errno.h>
#include "flash.h"
#include "flash.c"
void get_ddid(int ddb, struct ddb_id *ddbid) {
uint8_t id[4];
if (ioctl(ddb, IOCTL_DDB_ID, ddbid)>=0)
return;
memset(ddbid, 0, sizeof(*ddbid));
flashread(ddb, linknr, id, 0, 4);
printf("%02x %02x %02x %02x\n",
id[0], id[1], id[2], id[3]);
ddbid->subvendor=(id[0] << 8) | id[1];
ddbid->subdevice=(id[2] << 8) | id[3];
}
int sure()
{
char c;
printf("\n\nWARNING! Flashing a new FPGA image might make your card unusable!\n");
printf("\n\nWARNUNG! Das Flashen eines neuen FPGA-Images kann Ihre Karte unbrauchbar machen.\n");
printf("\n\nAre you sure? y/n?");
printf("\n\nSind Sie sicher? y/n?");
fflush(0);
c = getchar();
if (c!='y') {
printf("\nFlashing aborted.\n\n");
return -1;
}
printf("\nStarting to flash\n\n");
return 0;
}
int main(int argc, char **argv)
{
char ddbname[80];
char *flashname;
int type = 0;
struct ddb_id ddbid;
uint8_t *buffer;
int BufferSize = 0;
int BlockErase = 0;
uint32_t FlashOffset = 0x10000;
int ddb;
int i, err;
uint32_t SectorSize=0;
uint32_t FlashSize=0;
int Flash;
uint32_t svid=0, jump=0, dump=0;
int bin;
int ddbnum = 0;
int force = 0;
char *fname = NULL;
while (1) {
int option_index = 0;
int c;
static struct option long_options[] = {
{"svid", required_argument, NULL, 's'},
{"help", no_argument , NULL, 'h'},
{"force", no_argument , NULL, 'f'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"d:n:s:o:l:dfhjb:",
long_options, &option_index);
if (c==-1)
break;
switch (c) {
case 'b':
fname = optarg;
break;
case 'd':
dump = strtoul(optarg, NULL, 16);
break;
case 's':
svid = strtoul(optarg, NULL, 16);
break;
case 'o':
FlashOffset = strtoul(optarg, NULL, 16);
break;
case 'n':
ddbnum = strtol(optarg, NULL, 0);
break;
case 'l':
linknr = strtol(optarg, NULL, 0);
break;
case 'f':
force = 1;
break;
case 'j':
jump = 1;
break;
case 'h':
default:
break;
}
}
if (optind<argc) {
printf("Warning: unused arguments\n");
}
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
ddb=open(ddbname, O_RDWR);
if (ddb < 0) {
printf("Could not open device\n");
return -1;
}
Flash = flashdetect(ddb, &SectorSize, &FlashSize, &flashname);
get_ddid(ddb, &ddbid);
#if 0
printf("%04x %04x %04x %04x %08x %08x\n",
ddbid.vendor, ddbid.device,
ddbid.subvendor, ddbid.subdevice,
ddbid.hw, ddbid.regmap);
#endif
if (dump) {
flashdump(ddb, linknr, dump, 128);
return 0;
}
if (!SectorSize)
return 0;
if (jump) {
uint32_t Jump = 0x200000;
BufferSize = SectorSize;
FlashOffset = FlashSize - SectorSize;
buffer = malloc(BufferSize);
if (!buffer) {
printf("out of memory\n");
return 0;
}
memset(buffer, 0xFF, BufferSize);
memset(&buffer[BufferSize - 256 + 0x10], 0x00, 16);
buffer[BufferSize - 256 + 0x10] = 0xbd;
buffer[BufferSize - 256 + 0x11] = 0xb3;
buffer[BufferSize - 256 + 0x12] = 0xc4;
buffer[BufferSize - 256 + 0x1a] = 0xfe;
buffer[BufferSize - 256 + 0x1e] = 0x03;
buffer[BufferSize - 256 + 0x1f] = ( ( Jump >> 16 ) & 0xFF );
buffer[BufferSize - 256 + 0x20] = ( ( Jump >> 8 ) & 0xFF );
buffer[BufferSize - 256 + 0x21] = ( ( Jump ) & 0xFF );
} else if (svid) {
BufferSize = SectorSize;
FlashOffset = 0;
buffer = malloc(BufferSize);
if (!buffer) {
printf("out of memory\n");
return 0;
}
memset(buffer,0xFF,BufferSize);
buffer[0] = ((svid >> 24 ) & 0xFF);
buffer[1] = ((svid >> 16 ) & 0xFF);
buffer[2] = ((svid >> 8 ) & 0xFF);
buffer[3] = ((svid ) & 0xFF);
} else {
int fh, i;
int fsize;
char *name;
if (!fname)
fname = devid2fname(ddbid.device, &name);
if (name)
printf("Card: %s\n", name);
fh = open(fname, O_RDONLY);
if (fh < 0 ) {
printf("File %s not found \n", fname);
return 0;
}
printf("Using bitstream %s\n", fname);
fsize = lseek(fh,0,SEEK_END);
if( fsize > FlashSize/2 - 0x10000 || fsize < SectorSize )
{
close(fh);
printf("Invalid File Size \n");
return 0;
}
if( Flash == ATMEL_AT45DB642D ) {
BlockErase = fsize >= 8192;
if( BlockErase )
BufferSize = (fsize + 8191) & ~8191;
else
BufferSize = (fsize + 1023) & ~1023;
} else {
BufferSize = (fsize + SectorSize - 1 ) & ~(SectorSize - 1);
}
printf(" Size %08x, target %08x\n", BufferSize, FlashOffset);
buffer = malloc(BufferSize);
if( buffer == NULL ) {
close(fh);
printf("out of memory\n");
return 0;
}
memset(buffer, 0xFF, BufferSize);
lseek(fh, 0, SEEK_SET);
read(fh, buffer, fsize);
close(fh);
if (BufferSize >= 0x10000) {
for(i = 0; i < 0x200; i += 1 ) {
if ( *(uint16_t *) (&buffer[i]) == 0xFFFF )
break;
buffer[i] = 0xFF;
}
}
}
if (!force && sure()<0)
return 0;
switch(Flash) {
case ATMEL_AT45DB642D:
err = FlashWriteAtmel(ddb,FlashOffset,buffer,BufferSize);
break;
case SSTI_SST25VF016B:
case SSTI_SST25VF032B:
err = FlashWriteSSTI_B(ddb,FlashOffset,buffer,BufferSize);
break;
case SSTI_SST25VF064C:
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x3C);
break;
case SPANSION_S25FL116K:
case SPANSION_S25FL164K:
case WINBOND_W25Q16JV:
case WINBOND_W25Q32JV:
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x1C);
break;
}
if (err < 0)
printf("Programming Error\n");
else
printf("Programming Done\n");
free(buffer);
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,10 +280,10 @@ int mci_cmd(int dev, struct mci_command *cmd)
memset(&msg, 0, sizeof(msg));
msg.link = 0;
memcpy(&msg.cmd, cmd, sizeof(msg.cmd));
//dump((uint8_t *) &msg.cmd, sizeof(msg.cmd));
dump((uint8_t *) &msg.cmd, sizeof(msg.cmd));
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
dprintf(2, "mci_cmd error %d\n", errno);
dprintf(2, "mci_cmd error %d (%s)\n", errno, strerror(errno));
return ret;
}
status = msg.res.status;
@ -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,
@ -310,16 +314,10 @@ struct mci_command msg_channels = {
struct mci_command msg_stream = {
.mod_command = MOD_SETUP_STREAM,
.mod_channel = 1,
.mod_channel = 0,
.mod_stream = 0,
.mod_setup_stream = {
.standard = MOD_STANDARD_DVBC_8,
#if 0
.ofdm = {
.fft_size = 1,
.guard_interval = 0,
}
#endif
},
};
@ -377,22 +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);
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)
@ -434,6 +439,15 @@ void streams_cb(void *priv, char *par, char *val)
} else if (!strcasecmp(par, "stream")) {
mc->stream.mod_stream = strtol(val, NULL, 10);
printf("set stream %u to channel %u\n", mc->stream.mod_stream, mc->stream.mod_channel);
printf("%u %u %u %u %u %u %u %u\n",
mc->stream.mod_command,
mc->stream.mod_channel,
mc->stream.mod_stream,
mc->stream.mod_setup_stream.standard,
mc->stream.mod_setup_stream.symbol_rate,
mc->stream.mod_setup_stream.stream_format,
mc->stream.mod_setup_stream.qam.modulation,
mc->stream.mod_setup_stream.qam.rolloff);
mci_cmd(mc->fd, &mc->stream);
} else
printf("invalid streams parameter: %s = %s\n", par, val);
@ -458,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(&res->license, sizeof(res->license));
//dump((const uint8_t *)&res->license, sizeof(res->license));
return ret;
}
@ -467,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;
@ -475,6 +488,7 @@ 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;
@ -486,7 +500,7 @@ int main(int argc, char*argv[])
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "d:c:",
c = getopt_long(argc, argv, "d:c:",
long_options, &option_index);
if (c == -1)
break;
@ -517,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

@ -1,36 +0,0 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#define SNUM 1000
//671
void send(void)
{
uint8_t buf[188*SNUM], *cts;
int i;
uint32_t c=0;
int fdo;
fdo=open("/dev/dvb/adapter0/mod0", O_WRONLY);
while (1) {
read(0, buf, sizeof(buf));
write(fdo, buf, 188*SNUM);
}
}
int main()
{
send();
}

1277
apps/modtest.c Normal file

File diff suppressed because it is too large Load Diff

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

@ -1362,7 +1362,7 @@ int read_id(int dev, int argc, char* argv[], uint32_t Flags)
for (i = 0; i < len; i++)
printf("%02x ", Id[i]);
printf("\n");
return 0;
}
int i2cread(int dev, int argc, char* argv[], uint32_t Flags)

View File

@ -36,6 +36,7 @@ static int update_flash(struct ddflash *ddf)
char *fname, *default_fname;
int res, stat = 0;
char *name = 0, *dname;
uint32_t imgadr = 0x10000;
switch (ddf->id.device) {
case 0x300:
@ -109,6 +110,14 @@ static int update_flash(struct ddflash *ddf)
return stat;
break;
default:
{
uint32_t val;
if (!readreg(ddf->fd, (ddf->link << 28) | 0x10, &val)) {
//printf("reg0x10=%08x\n", val);
if ((val >> 24) == 5)
imgadr = 0;
}
}
fname = ddf->fname;
default_fname = devid2fname(ddf->id.device, &name);
if (!fname)
@ -119,7 +128,8 @@ static int update_flash(struct ddflash *ddf)
printf("Flash: %s\n", ddf->flash_name);
printf("Version: %08x\n", ddf->id.hw);
printf("REGMAP : %08x\n", ddf->id.regmap);
if ((res = update_image(ddf, fname, 0x10000, ddf->size / 2, 1, 0)) == 1)
printf("Address: %08x\n", imgadr);
if ((res = update_image(ddf, fname, imgadr, ddf->size / 2, 1, 0)) == 1)
stat |= 1;
return stat;
}

View File

@ -167,7 +167,7 @@ static int flashread(int ddb, int link, uint8_t *buf, uint32_t addr, uint32_t le
}
#endif
int flashdump(int ddb, int link, uint32_t addr, uint32_t len)
void flashdump(int ddb, int link, uint32_t addr, uint32_t len)
{
int i, j;
uint8_t buf[32];
@ -630,13 +630,14 @@ int flashwrite_pagemode(struct ddflash *ddf, int dev, uint32_t FlashOffset,
uint8_t cmd[260];
int i, j;
uint32_t flen, blen;
int blockerase = be && ((FlashOffset & 0xFFFF) == 0 ) && (flen >= 0x10000);
int blockerase;
blen = flen = lseek(dev, 0, SEEK_END) - fw_off;
if (blen % 0xff)
blen = (blen + 0xff) & 0xffffff00;
//printf("blen = %u, flen = %u\n", blen, flen);
setbuf(stdout, NULL);
blockerase = be && ((FlashOffset & 0xFFFF) == 0 ) && (flen >= 0x10000);
cmd[0] = 0x50; // EWSR
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0);
@ -927,7 +928,10 @@ static const struct devids ids[] = {
DEV(0x0011, "Octopus CI", "DVBBridgeV2B_DD01_0011.fpga"),
DEV(0x0012, "Octopus CI", "DVBBridgeV2B_DD01_0012_STD.fpga"),
DEV(0x0013, "Octopus PRO", "DVBBridgeV2B_DD01_0013_PRO.fpga"),
DEV(0x0014, "Octopus CI M2", "DVBBridgeV3A_DD01_0014_CIM2.fpga"),
DEV(0x0020, "Octopus GT Mini", "DVBBridgeV2C_DD01_0020.fpga"),
DEV(0x0022, "Octopus MAXM8", "DVBBridgeV3A_DD01_0022_M8.fpga"),
DEV(0x0024, "Octopus MAXM8A", "DVBBridgeV3A_DD01_0024_M8A.fpga"),
DEV(0x0201, "Modulator", "DVBModulatorV1B_DVBModulatorV1B.bit"),
DEV(0x0203, "Modulator Test", "DVBModulatorV1B_DD01_0203.fpga"),
DEV(0x0210, "Modulator V2", "DVBModulatorV2A_DD01_0210.fpga"),
@ -1075,12 +1079,12 @@ static int check_fw(struct ddflash *ddf, char *fn, uint32_t *fw_off)
close(fd);
for (p = 0; p < fsize && buf[p]; p++) {
char *key = &buf[p], *val = NULL;
char *key = (char *) &buf[p], *val = NULL;
for (; p < fsize && buf[p] != 0x0a; p++) {
if (buf[p] == ':') {
buf[p] = 0;
val = &buf[p + 1];
val = (char *) &buf[p + 1];
}
}
if (val == NULL || p == fsize)

View File

@ -1,167 +0,0 @@
/*
* pls.c: Convert between Gold and Root Codes for DVB-S2 PLS
*
* Copyright (C) 2017 Marcus Metzler <mocm@metzlerbros.de>
* Ralph Metzler <rjkm@metzlerbros.de>
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 only, as published by the Free Software Foundation.
*
*
* 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include <stdio.h>
#include <stdint.h>
/* According to ETSI EN 302 307 5.5.4 the PLS (Physical Layer
Scrambling) for DVB-S2 consists of a complex randomization
sequence which is ultimately derived from two recursively
defined m-sequences (=MLS or maximum length sequences)
x(i) and y(i) of polynomials over GF(2) with m=18
(thus their length is 2^18 - 1).
These m-sequences with sequence y starting from y(0) and
sequence x starting from x(n) are combined to form a set
of 2^18 - 1 different Gold code sequences.
This starting number n of sequence x selects which
of those 2^18 - 1 Gold code sequences to use.
As a DVB-S2 tuning parameter n is called the scrambling sequence index
(cf. ETSI EN 300 468 table 41) or Gold sequence index,
commonly also just called "Gold code".
The 18 values of the sequence x starting from x(n)
(x(n) ... x(n+17)) are also called the "Root code".
So, Gold and Root codes are not different ways of PLS, they are
just different ways to select the same sequence start point.
The initial values for x(i), i=0..18 are x(0)=1, x(1)=0, .., x(17)=0 .
The polynomial used for the x sequence recursion is 1+x^7+x^18.
If the lower 18 bits of a variable "uint32_t X" contain x(n) ... x(n+17),
then we can simply calculate x(n+1) ... x(n+18) by doing:
X = (((X ^ (X >> 7)) & 1) << 17) | (X >> 1);
So, if X contained the "Root code" corresponding to "Gold code" n,
it will now contain the "Root code" corresponding to "Gold code" (n+1).
Note that X=0 and n=2^18 - 1 do not exist (or rather the lattter is the same
as n = 0) and for n=0 to 2^18 - 2 and X=1 to 2^18 - 1 there is a
one-to-one correspondence (bijection).
Note that PLS has nothing to do with encryption for DRM purposes. It is used
to minimize interference between transponders.
"Combo code":
There is no such thing as a combo code. It is the result of a bug in older
STV090x drivers which resulted in a crazy race condition between a Gold->Root
conversion in the STV and an ongoing I2C write.
Better forget about it and determine the proper Root or Gold code.
*/
static uint32_t gold2root(uint32_t gold)
{
uint32_t x, g;
for (g = 0, x = 1; g < gold; g++)
x = (((x ^ (x >> 7)) & 1) << 17) | (x >> 1);
return x;
}
static uint32_t root2gold(uint32_t root)
{
uint32_t x, g;
for (g = 0, x = 1; g < 0x3ffff; g++) {
if (root == x)
return g;
x = (((x ^ (x >> 7)) & 1) << 17) | (x >> 1);
}
return 0xffffffff;
}
int main(int argc, char **argv)
{
uint32_t gold = 0xffffffff, root = 0xffffffff;
while (1) {
int option_index = 0;
int c;
static struct option long_options[] = {
{"gold", required_argument, 0, 'g'},
{"root", required_argument, 0, 'r'},
{"help", no_argument , 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"r:g:h",
long_options, &option_index);
if (c==-1)
break;
switch (c) {
case 'g':
gold = strtoul(optarg, NULL, 0);
break;
case 'r':
root = strtoul(optarg, NULL, 0);
break;
case 'h':
printf("pls -g gold_code\n");
printf("or\n");
printf("pls -r root_code\n");
exit(-1);
default:
break;
}
}
if (optind < argc) {
printf("Warning: unused arguments\n");
}
if (gold != 0xffffffff && root != 0xffffffff) {
printf("Only specify root or gold code\n");
exit(-1);
};
if (gold != 0xffffffff) {
if (gold < 0x3ffff) {
root = gold2root(gold);
printf("gold = %llu (0x%05x) root = %llu (0x%05x)\n",
gold, gold, root, root);
} else
printf("Invalid gold code specified.\n");
exit(0);
}
if (root != 0xffffffff) {
if (root > 0 && root < 0x40000)
gold = root2gold(root);
if (gold != 0xffffffff)
printf("gold = %llu (0x%05x) root = %llu (0x%05x)\n",
gold, gold, root, root);
else
printf("Invalid root code specified.\n");
exit(0);
}
printf("Specify either root or gold code with -r or -g.\n");
}

View File

@ -10,6 +10,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <getopt.h>
#include <linux/dvb/mod.h>
@ -31,17 +32,134 @@ static int set_property(int fd, uint32_t cmd, uint32_t data)
return 0;
}
int main()
static int get_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;
ret = ioctl(fd, FE_GET_PROPERTY, &c);
if (ret < 0) {
fprintf(stderr, "FE_GET_PROPERTY returned %d\n", ret);
return -1;
}
*data = p.u.data;
return 0;
}
int main(int argc, char*argv[])
{
int fd;
struct dvb_mod_params mp;
struct dvb_mod_channel_params mc;
uint32_t data;
int32_t adapter = 0, channel = 0, gain = -1, att=-1, mod=-1;
int32_t base = -1, freq = -1, rate = -1, srate = -1;
char mod_name[128];
fd = open("/dev/dvb/adapter0/mod0", O_RDONLY);
while (1) {
int cur_optind = optind ? optind : 1;
int option_index = 0;
int c;
static struct option long_options[] = {
{"adapter", required_argument, 0, 'a'},
{"channel", required_argument, 0, 'c'},
{"att", required_argument, 0, 't'},
{"gain", required_argument, 0, 'g'},
{"base", required_argument, 0, 'b'},
{"frequency", required_argument, 0, 'f'},
{"rate", required_argument, 0, 'r'},
{"modulation", required_argument, 0, 'm'},
{"symbolrate", required_argument, 0, 's'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"a:c:g:b:f:r:t:m:s:",
long_options, &option_index);
if (c==-1)
break;
set_property(fd, MODULATOR_MODULATION, QAM_256);
set_property(fd, MODULATOR_SYMBOL_RATE, 6900000);
set_property(fd, MODULATOR_FREQUENCY, 114000000);
switch (c) {
case 'a':
adapter = strtoul(optarg, NULL, 0);
break;
case 'c':
channel = strtoul(optarg, NULL, 0);
break;
case 'g':
gain = strtoul(optarg, NULL, 0);
break;
case 't':
att = strtoul(optarg, NULL, 0);
break;
case 'b':
base = strtoul(optarg, NULL, 0);
break;
case 'f':
freq = strtoul(optarg, NULL, 0);
break;
case 'm':
mod = strtoul(optarg, NULL, 0);
break;
case 's':
srate = strtoul(optarg, NULL, 0);
break;
case 'r':
if (!strcmp(optarg, "DVBT_8"))
rate = SYS_DVBT_8;
else if (!strcmp(optarg, "DVBT_7"))
rate = SYS_DVBT_7;
else if (!strcmp(optarg, "DVBT_6"))
rate = SYS_DVBT_6;
else if (!strcmp(optarg, "ISDBT_6"))
rate = SYS_ISDBT_6;
else rate = strtoul(optarg, NULL, 0);
break;
default:
break;
}
}
if (optind < argc) {
printf("too many arguments\n");
exit(1);
}
snprintf(mod_name, 127, "/dev/dvb/adapter%d/mod%d", adapter, channel);
fd = open(mod_name, O_RDONLY);
if (fd < 0) {
printf("Could not open modulator device.\n");
exit(1);
}
/* gain 0-255 */
//get_property(fd, MODULATOR_GAIN, &data);
//printf("Modulator gain = %u\n", data);
//set_property(fd, MODULATOR_GAIN, 100);
//get_property(fd, MODULATOR_ATTENUATOR, &data);
//printf("Modulator attenuator = %u\n", data);
if (att >= 0)
set_property(fd, MODULATOR_ATTENUATOR, att);
if (gain >= 0)
set_property(fd, MODULATOR_GAIN, gain);
if (base > 0)
set_property(fd, MODULATOR_BASE_FREQUENCY, base);
if (freq > 0)
set_property(fd, MODULATOR_FREQUENCY, freq);
if (rate > 0)
set_property(fd, MODULATOR_OUTPUT_RATE, rate);
if (mod >= 0)
set_property(fd, MODULATOR_MODULATION, mod);
if (srate > 0)
set_property(fd, MODULATOR_SYMBOL_RATE, srate);
close(fd);
}

View File

@ -1,149 +0,0 @@
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <getopt.h>
#include <linux/dvb/mod.h>
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 get_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;
ret = ioctl(fd, FE_GET_PROPERTY, &c);
if (ret < 0) {
fprintf(stderr, "FE_GET_PROPERTY returned %d\n", ret);
return -1;
}
*data = p.u.data;
return 0;
}
int main(int argc, char*argv[])
{
int fd;
struct dvb_mod_params mp;
struct dvb_mod_channel_params mc;
uint32_t data;
int32_t adapter = 0, channel = 0, gain = -1;
int32_t base = -1, freq = -1, rate = -1;
char mod_name[128];
while (1) {
int cur_optind = optind ? optind : 1;
int option_index = 0;
int c;
static struct option long_options[] = {
{"adapter", required_argument, 0, 'a'},
{"channel", required_argument, 0, 'c'},
{"gain", required_argument, 0, 'g'},
{"base", required_argument, 0, 'b'},
{"frequency", required_argument, 0, 'f'},
{"rate", required_argument, 0, 'r'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv,
"a:c:g:b:f:r:",
long_options, &option_index);
if (c==-1)
break;
switch (c) {
case 'a':
adapter = strtoul(optarg, NULL, 0);
break;
case 'c':
channel = strtoul(optarg, NULL, 0);
break;
case 'g':
gain = strtoul(optarg, NULL, 0);
break;
case 'b':
base = strtoul(optarg, NULL, 0);
break;
case 'f':
freq = strtoul(optarg, NULL, 0);
break;
case 'r':
if (!strcmp(optarg, "DVBT_8"))
rate = SYS_DVBT_8;
else if (!strcmp(optarg, "DVBT_7"))
rate = SYS_DVBT_7;
else if (!strcmp(optarg, "DVBT_6"))
rate = SYS_DVBT_6;
else if (!strcmp(optarg, "ISDBT_6"))
rate = SYS_ISDBT_6;
else rate = strtoul(optarg, NULL, 0);
break;
default:
break;
}
}
if (optind < argc) {
printf("too many arguments\n");
exit(1);
}
snprintf(mod_name, 127, "/dev/dvb/adapter%d/mod%d", adapter, channel);
fd = open(mod_name, O_RDONLY);
if (fd < 0) {
printf("Could not open modulator device.\n");
exit(1);
}
/* gain 0-255 */
//get_property(fd, MODULATOR_GAIN, &data);
//printf("Modulator gain = %u\n", data);
//set_property(fd, MODULATOR_GAIN, 100);
//get_property(fd, MODULATOR_ATTENUATOR, &data);
//printf("Modulator attenuator = %u\n", data);
if (gain > 0)
set_property(fd, MODULATOR_GAIN, gain);
if (base > 0)
set_property(fd, MODULATOR_BASE_FREQUENCY, base);
if (freq > 0)
set_property(fd, MODULATOR_FREQUENCY, freq);
if (rate > 0)
set_property(fd, MODULATOR_OUTPUT_RATE, rate);
close(fd);
}

View File

@ -1,105 +0,0 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/video.h>
char line_start[16] = "";
char line_end[16] = "\r";
uint32_t cc_errors = 0;
uint32_t packets = 0;
uint32_t payload_packets = 0;
uint32_t packet_errors = 0;
uint8_t cc[8192] = { 0 };
void proc_ts(int i, uint8_t *buf)
{
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 ) {
if (ccin & 0x10) {
if( cc[pid] != 0 ) {
// TODO: 1 repetition allowed
if ((((cc[pid] + 1) & 0x0F) != (ccin & 0x0F)) ) {
cc_errors += 1;
printf("%04x: %u != %u\n", pid, (cc[pid] + 1) & 0x0F, ccin & 0x0F);
}
}
cc[pid] = ccin;
}
payload_packets += 1;
}
} else
packet_errors += 1;
if( (packets & 0x3FFF ) == 0) {
printf("%s Packets: %12u non null %12u, errors: %12u, CC errors: %12u%s",
line_start, packets, payload_packets, packet_errors, cc_errors, line_end);
fflush(stdout);
}
packets += 1;
}
#define TSBUFSIZE (100*188)
void citest(char* n)
{
uint8_t *buf;
uint8_t id;
int i, nts;
int len;
int ts=open(n, O_RDONLY);
buf=(uint8_t *)malloc(TSBUFSIZE);
while(1) {
len=read(ts, buf, TSBUFSIZE);
if (len<0) {
continue;
}
if (buf[0]!=0x47) {
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);
}
}
int main(int argc, char* argv[])
{
if( argc < 2 )
{
printf("tscheck <file>|<device> [<display line>]\n");
exit(0);
}
if( argc > 2 )
{
int line = atoi(argv[2]);
if( line >= 0 && line < 64 )
{
snprintf(line_start,sizeof(line_start)-1,"\0337\033[%d;0H",line);
strncpy(line_end,"\0338",sizeof(line_end)-1);
}
}
citest(argv[1]);
}

View File

@ -1,12 +1,10 @@
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
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
#mci-objs = ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o ddbridge-io.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o #mci.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
ifneq ($(KERNEL_DVB_CORE),y)
obj-$(CONFIG_DVB_OCTONET) += octonet.o

View File

@ -1,15 +1,13 @@
#
# Makefile for the ddbridge device driver
#
#NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux -I$(KBUILD_EXTMOD)/dvb-frontends -I$(KBUILD_EXTMOD)/tuners
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
obj-$(CONFIG_DVB_OCTONET) += octonet.o
#ccflags-y += -Idrivers/media/include/linux/
#ccflags-y += -Idrivers/media/dvb-frontends/
#ccflags-y += -Idrivers/media/tuners/
ccflags-y += -Idrivers/media/dvb-frontends/
ccflags-y += -Idrivers/media/tuners/

View File

@ -3,7 +3,7 @@
#
ddbridge-objs = ddbridge-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-modulator.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
octonet-objs = octonet-main.o ddbridge-hw.o ddbridge-i2c.o ddbridge-ns.o ddbridge-core.o ddbridge-io.o ddbridge-ci.o ddbridge-max.o ddbridge-mci.o ddbridge-sx8.o ddbridge-m4.o dvb_netstream.o
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
obj-$(CONFIG_DVB_OCTONET) += octonet.o

View File

@ -32,7 +32,7 @@ static int wait_ci_ready(struct ddb_ci *ci)
ndelay(500);
do {
if (ddbreadl(ci->port->dev,
CI_CONTROL(ci->nr)) & CI_READY)
CI_CONTROL(ci)) & CI_READY)
break;
usleep_range(1, 2);
if ((--count) == 0)
@ -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->nr));
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;
}
@ -62,7 +63,7 @@ static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
struct ddb_ci *ci = ca->data;
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
CI_DO_ATTRIBUTE_RW(ci->nr));
CI_DO_ATTRIBUTE_RW(ci));
wait_ci_ready(ci);
return 0;
}
@ -75,10 +76,10 @@ static int read_cam_control(struct dvb_ca_en50221 *ca,
u32 res;
ddbwritel(ci->port->dev, CI_READ_CMD | address,
CI_DO_IO_RW(ci->nr));
CI_DO_IO_RW(ci));
ndelay(500);
do {
res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr));
res = ddbreadl(ci->port->dev, CI_READDATA(ci));
if (res & CI_READY)
break;
usleep_range(1, 2);
@ -94,7 +95,7 @@ static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
struct ddb_ci *ci = ca->data;
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
CI_DO_IO_RW(ci->nr));
CI_DO_IO_RW(ci));
wait_ci_ready(ci);
return 0;
}
@ -104,15 +105,15 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
struct ddb_ci *ci = ca->data;
ddbwritel(ci->port->dev, CI_POWER_ON,
CI_CONTROL(ci->nr));
CI_CONTROL(ci));
msleep(300);
ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
CI_CONTROL(ci->nr));
CI_CONTROL(ci));
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
CI_CONTROL(ci->nr));
usleep_range(20, 25);
CI_CONTROL(ci));
msleep(20);
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
CI_CONTROL(ci->nr));
CI_CONTROL(ci));
return 0;
}
@ -120,7 +121,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
{
struct ddb_ci *ci = ca->data;
ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr));
ddbwritel(ci->port->dev, 0, CI_CONTROL(ci));
msleep(300);
return 0;
}
@ -128,17 +129,17 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
{
struct ddb_ci *ci = ca->data;
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci));
ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
CI_CONTROL(ci->nr));
CI_CONTROL(ci));
return 0;
}
static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
{
struct ddb_ci *ci = ca->data;
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci));
int stat = 0;
if (val & CI_CAM_DETECT)
@ -162,6 +163,8 @@ static struct dvb_ca_en50221 en_templ = {
static void ci_attach(struct ddb_port *port)
{
struct ddb_ci *ci;
const struct ddb_info *info = port->dev->link[port->lnr].info;
u32 off = info->ci_base ? info->ci_base : 0x400;
ci = kzalloc(sizeof(*ci), GFP_KERNEL);
if (!ci)
@ -171,6 +174,7 @@ static void ci_attach(struct ddb_port *port)
port->en = &ci->en;
ci->port = port;
ci->nr = port->nr - 2;
ci->regs = DDB_LINK_TAG(port->lnr) | (off + 32 * ci->nr);
}
/* DuoFlex Dual CI support */
@ -234,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;
@ -370,7 +378,7 @@ static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
if (!dma->vbuf[i])
return -ENOMEM;
}
if (((u64)dma->vbuf[i] & 0xfff))
if (((uintptr_t) dma->vbuf[i] & 0xfff))
dev_err(&pdev->dev, "DMA memory at %px not aligned!\n", dma->vbuf[i]);
}
return 0;
@ -467,7 +475,7 @@ static void calc_con(struct ddb_output *output, u32 *con, u32 *con2, u32 flags)
gap = output->port->gap;
max_bitrate = 0;
}
if (dev->link[0].info->type == DDB_OCTOPUS_CI && output->port->nr > 1) {
if (dev->link[0].info->ci_mask && output->port->nr > 1) {
*con = 0x10c;
if (dev->link[0].ids.regmapid >= 0x10003 && !(flags & 1)) {
if (!(flags & 2)) {
@ -534,7 +542,9 @@ static int ddb_output_start_unlocked(struct ddb_output *output)
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
}
if (output->port->class == DDB_PORT_MOD) {
#ifndef CONFIG_MACH_OCTONET
err = ddbridge_mod_output_start(output);
#endif
} else {
if (output->port->input[0]->port->class == DDB_PORT_LOOP)
con = (1UL << 13) | 0x14;
@ -578,9 +588,11 @@ static void ddb_output_stop_unlocked(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
#ifndef CONFIG_MACH_OCTONET
if (output->port->class == DDB_PORT_MOD)
ddbridge_mod_output_stop(output);
else
#endif
ddbwritel(dev, 0, TS_CONTROL(output));
if (output->dma) {
ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
@ -622,12 +634,14 @@ static void ddb_input_stop_unlocked(struct ddb_input *input)
input->dma->running = 0;
if (input->dma->stall_count)
dev_warn(input->port->dev->dev,
"DMA stalled %u times!\n",
"l%ui%u: DMA stalled %u times!\n",
input->port->lnr, input->nr,
input->dma->stall_count);
update_loss(input->dma);
if (input->dma->packet_loss > 1)
dev_warn(input->port->dev->dev,
"%u packets lost due to low DMA performance!\n",
"l%ui%u: %u packets lost due to low DMA performance!\n",
input->port->lnr, input->nr,
input->dma->packet_loss);
}
}
@ -666,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)
@ -793,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))
@ -863,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;
@ -952,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;
}
@ -984,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;
@ -1062,8 +1091,12 @@ static struct dvb_device dvbdev_ci = {
static long mod_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
#ifndef CONFIG_MACH_OCTONET
return ddb_dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl);
}
#else
return 0;
#endif
}
static const struct file_operations mod_fops = {
.owner = THIS_MODULE,
@ -1112,15 +1145,24 @@ static int dummy_read_status(struct dvb_frontend *fe, enum fe_status *status)
static void dummy_release(struct dvb_frontend *fe)
{
kfree(fe);
#ifdef CONFIG_MEDIA_ATTACH
__module_get(THIS_MODULE);
#endif
}
static enum dvbfe_algo dummy_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}
static struct dvb_frontend_ops dummy_ops = {
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBS, SYS_DVBS2 },
.delsys = { SYS_DVBC_ANNEX_A },
.info = {
.name = "DUMMY DVB-C/C2 DVB-T/T2",
.frequency_stepsize_hz = 166667, /* DVB-T only */
.frequency_min_hz = 47000000, /* DVB-T: 47125000 */
.frequency_max_hz = 865000000, /* DVB-C: 862000000 */
.name = "DUMMY DVB-C",
.frequency_stepsize_hz = 0,
.frequency_tolerance_hz = 0,
.frequency_min_hz = 47000000,
.frequency_max_hz = 865000000,
.symbol_rate_min = 870000,
.symbol_rate_max = 11700000,
.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
@ -1133,17 +1175,15 @@ static struct dvb_frontend_ops dummy_ops = {
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
},
.get_frontend_algo = dummy_algo,
.release = dummy_release,
.read_status = dummy_read_status,
};
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;
@ -1153,11 +1193,7 @@ static int demod_attach_dummy(struct ddb_input *input)
{
struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
#if 0
dvb->fe = dvb_attach(dummy_attach);
#else
dvb->fe = dummy_attach();
#endif
return 0;
}
@ -1228,6 +1264,7 @@ static int demod_attach_stv0367dd(struct ddb_input *input)
return 0;
}
#ifdef CONFIG_DVB_DRXK
static int tuner_attach_tda18271(struct ddb_input *input)
{
struct i2c_adapter *i2c = &input->port->i2c->adap;
@ -1246,6 +1283,7 @@ static int tuner_attach_tda18271(struct ddb_input *input)
}
return 0;
}
#endif
static int tuner_attach_tda18212dd(struct ddb_input *input)
{
@ -1530,7 +1568,9 @@ static void dvb_input_detach(struct ddb_input *input)
dvb_netstream_release(&dvb->dvbns);
fallthrough;
case 0x20:
#ifdef CONFIG_DVB_NET
dvb_net_release(&dvb->dvbnet);
#endif
fallthrough;
case 0x12:
dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
@ -1576,8 +1616,7 @@ static int dvb_register_adapters(struct ddb *dev)
}
if (adapter_alloc >= 3 || dev->link[0].info->type == DDB_MOD ||
dev->link[0].info->type == DDB_OCTONET ||
dev->link[0].info->type == DDB_OCTOPRO) {
dev->link[0].info->type == DDB_OCTONET) {
port = &dev->port[0];
adap = port->dvb[0].adap;
ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
@ -1709,9 +1748,11 @@ static int dvb_input_attach(struct ddb_input *input)
return ret;
dvb->attached = 0x12;
#ifdef CONFIG_DVB_NET
ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux);
if (ret < 0)
return ret;
#endif
dvb->attached = 0x20;
if (input->port->dev->ns_num) {
@ -1817,6 +1858,10 @@ static int dvb_input_attach(struct ddb_input *input)
break;
case DDB_TUNER_MCI_SX8:
case DDB_TUNER_MCI_M4:
case DDB_TUNER_MCI_M8:
case DDB_TUNER_MCI_M8A:
case DDB_TUNER_MCI_M8E:
case DDB_TUNER_MCI_M2:
if (ddb_fe_attach_mci(input, port->type) < 0)
return -ENODEV;
break;
@ -1990,6 +2035,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]);
@ -2080,7 +2126,7 @@ static void ddb_port_probe(struct ddb_port *port)
return;
}
if (port->nr == 1 && link->info->type == DDB_OCTOPUS_CI &&
if (port->nr == 1 && link->info->ci_mask &&
link->info->i2c_mask == 1) {
port->name = "NO TAB";
port->class = DDB_PORT_NONE;
@ -2108,15 +2154,16 @@ static void ddb_port_probe(struct ddb_port *port)
port->name = "DUAL MCI";
port->type_name = "MCI";
port->class = DDB_PORT_TUNER;
port->type = DDB_TUNER_MCI + link->info->mci_type;
port->type = link->info->mci_type;
return;
}
if (port->nr > 1 && link->info->type == DDB_OCTOPUS_CI) {
if (port->nr > 1 && (link->info->ci_mask & (1 << port->nr))) {
port->name = "CI internal";
port->type_name = "INTERNAL";
port->class = DDB_PORT_CI;
port->type = DDB_CI_INTERNAL;
return;
}
if (!port->i2c)
@ -2394,7 +2441,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),
@ -2404,18 +2453,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);
@ -2426,83 +2470,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
/****************************************************************************/
/****************************************************************************/
@ -2530,7 +2555,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 &&
@ -2544,7 +2568,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;
@ -2648,10 +2675,6 @@ static void ddb_ports_init(struct ddb *dev)
if (!rm)
continue;
ports = info->port_num;
if ((l == 0) && (info->type == DDB_MOD) &&
(dev->link[0].ids.revision == 1)) {
ports = ddbreadl(dev, 0x260) >> 24;
}
for (i = 0; i < ports; i++, p++) {
port = &dev->port[p];
port->dev = dev;
@ -2698,32 +2721,38 @@ static void ddb_ports_init(struct ddb *dev)
continue;
switch (info->type) {
case DDB_OCTOPUS_CI:
if (i >= 2) {
case DDB_OCTONET:
case DDB_OCTOPUS:
if (info->ci_mask & (1 << i)) {
ddb_input_init(port, 2 + i, 0, 2 + i);
ddb_input_init(port, 4 + i, 1, 4 + i);
ddb_output_init(port, i);
break;
}
fallthrough;
case DDB_OCTONET:
case DDB_OCTOPUS:
case DDB_OCTOPRO:
ddb_input_init(port, 2 * i, 0, 2 * i);
ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1);
ddb_output_init(port, i);
ddb_input_init(port, 2 * i, 0, 2 * p);
ddb_input_init(port, 2 * i + 1, 1, 2 * p + 1);
ddb_output_init(port, i);
break;
case DDB_OCTOPUS_MAX:
case DDB_OCTOPUS_MAX_CT:
case DDB_OCTOPUS_MCI:
if (info->ci_mask & (1 << i)) {
ddb_input_init(port, 2 + i, 0, 2 + i);
ddb_input_init(port, 4 + i, 1, 4 + i);
ddb_output_init(port, i);
break;
}
ddb_input_init(port, 2 * i, 0, 2 * p);
ddb_input_init(port, 2 * i + 1, 1, 2 * p + 1);
break;
case DDB_MOD:
#ifndef CONFIG_MACH_OCTONET
ddb_output_init(port, i);
ddb_irq_set(dev, 0, i + rm->irq_base_rate,
&ddbridge_mod_rate_handler,
&dev->output[i]);
#endif
break;
default:
break;
@ -2740,12 +2769,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);
}
}
}
@ -2847,9 +2885,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;
@ -3299,6 +3336,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;
@ -3312,6 +3351,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;
}
@ -3448,7 +3489,11 @@ static const struct file_operations ddb_fops = {
#if (KERNEL_VERSION(3, 4, 0) > LINUX_VERSION_CODE)
static char *ddb_devnode(struct device *device, mode_t *mode)
#else
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
static char *ddb_devnode(struct device *device, umode_t *mode)
#else
static char *ddb_devnode(const struct device *device, umode_t *mode)
#endif
#endif
{
struct ddb *dev = dev_get_drvdata(device);
@ -4025,11 +4070,13 @@ static struct device_attribute ddb_attrs_fanspeed[] = {
static struct class ddb_class = {
.name = "ddbridge",
#if (KERNEL_VERSION(6, 4, 0) > LINUX_VERSION_CODE)
.owner = THIS_MODULE,
#endif
.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)
@ -4039,7 +4086,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);
@ -4172,32 +4219,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);
@ -4209,7 +4233,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)
@ -4271,13 +4294,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);
@ -4428,6 +4452,52 @@ 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;
if (dev->link[0].ids.revision == 1)
lic = ddbreadl(dev, 0x260) >> 24;
switch (lic) {
case 0:
case 4:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0000);
break;
case 1:
case 8:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0003);
break;
case 2:
case 24:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0001);
break;
case 3:
case 16:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0002);
break;
default:
break;
}
dev_info(dev->dev, "Modulator channels: %u\n", dev->link[0].info->port_num);
}
}
return 0;
@ -4455,8 +4525,10 @@ int ddb_init(struct ddb *dev)
if (ddb_i2c_init(dev) < 0)
goto fail;
ddb_ports_init(dev);
#ifndef CONFIG_MACH_OCTONET
if (dev->link[0].info->type == DDB_MOD)
ddbridge_mod_init(dev);
#endif
if (ddb_buffers_alloc(dev) < 0) {
dev_info(dev->dev,
"Could not allocate buffer memory\n");
@ -4543,7 +4615,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

@ -246,7 +246,6 @@ static const struct ddb_regmap octopus_map = {
.odma = &octopus_odma,
.odma_buf = &octopus_odma_buf,
.input = &octopus_input,
.output = &octopus_output,
};
@ -463,23 +462,25 @@ static const struct ddb_info ddb_satixs2v3 = {
};
static const struct ddb_info ddb_ci = {
.type = DDB_OCTOPUS_CI,
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus CI",
.regmap = &octopus_map,
.port_num = 4,
.i2c_mask = 0x03,
.ci_mask = 0x0c,
};
static const struct ddb_info ddb_cis = {
.type = DDB_OCTOPUS_CI,
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus CI single",
.regmap = &octopus_map,
.port_num = 3,
.i2c_mask = 0x03,
.ci_mask = 0x04,
};
static const struct ddb_info ddb_ci_s2_pro = {
.type = DDB_OCTOPUS_CI,
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus CI S2 Pro",
.regmap = &octopus_map,
.port_num = 4,
@ -487,10 +488,11 @@ static const struct ddb_info ddb_ci_s2_pro = {
.board_control = 2,
.board_control_2 = 4,
.hw_min = 0x010007,
.ci_mask = 0x0c,
};
static const struct ddb_info ddb_ci_s2_pro_a = {
.type = DDB_OCTOPUS_CI,
.type = DDB_OCTOPUS,
.name = "Digital Devices Octopus CI S2 Pro Advanced",
.regmap = &octopus_map,
.port_num = 4,
@ -498,6 +500,7 @@ static const struct ddb_info ddb_ci_s2_pro_a = {
.board_control = 2,
.board_control_2 = 4,
.hw_min = 0x010007,
.ci_mask = 0x0c,
};
static const struct ddb_info ddb_dvbct = {
@ -570,6 +573,17 @@ static const struct ddb_info ddb_mod_fsm_4 = {
.lostlock_irq = 9,
};
static const struct ddb_info ddb_mod_fsm = {
.type = DDB_MOD,
.name = "Digital Devices DVB-C FSM",
.version = 2,
.regmap = &octopus_mod_2_map,
.port_num = 0,
.temp_num = 1,
.tempmon_irq = 8,
.lostlock_irq = 9,
};
static const struct ddb_info ddb_sdr_atv = {
.type = DDB_MOD,
.name = "Digital Devices SDR ATV",
@ -605,27 +619,19 @@ static const struct ddb_info ddb_sdr_dvbt = {
.name = "Digital Devices DVBT",
.version = 18,
.regmap = &octopus_sdr_map,
.port_num = 16,
.port_num = 14,
.temp_num = 1,
.tempmon_irq = 8,
};
static const struct ddb_info ddb_octopro_hdin = {
.type = DDB_OCTOPRO_HDIN,
.name = "Digital Devices OctopusNet Pro HDIN",
.regmap = &octopro_hdin_map,
.port_num = 10,
.i2c_mask = 0x3ff,
.mdio_base = 0x10020,
};
static const struct ddb_info ddb_octopro = {
.type = DDB_OCTOPRO,
.name = "Digital Devices OctopusNet Pro",
.regmap = &octopro_map,
.port_num = 10,
.i2c_mask = 0x3ff,
.mdio_base = 0x10020,
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 = {
@ -636,6 +642,7 @@ static const struct ddb_info ddb_s2_48 = {
.i2c_mask = 0x01,
.board_control = 1,
.tempmon_irq = 24,
.lnb_base = 0x400,
};
static const struct ddb_info ddb_ct2_8 = {
@ -708,8 +715,9 @@ static const struct ddb_info ddb_s2x_48 = {
.i2c_mask = 0x00,
.tempmon_irq = 24,
.mci_ports = 4,
.mci_type = 0,
.mci_type = DDB_TUNER_MCI_SX8,
.temp_num = 1,
.lnb_base = 0x400,
};
static const struct ddb_info ddb_s2x_48_b = {
@ -720,8 +728,9 @@ static const struct ddb_info ddb_s2x_48_b = {
.i2c_mask = 0x00,
.tempmon_irq = 24,
.mci_ports = 4,
.mci_type = 0,
.mci_type = DDB_TUNER_MCI_SX8,
.temp_num = 1,
.lnb_base = 0x400,
};
static const struct ddb_info ddb_m4 = {
@ -732,8 +741,72 @@ static const struct ddb_info ddb_m4 = {
.i2c_mask = 0x00,
.tempmon_irq = 24,
.mci_ports = 2,
.mci_type = 1,
.mci_type = DDB_TUNER_MCI_M4,
.temp_num = 1,
.lnb_base = 0x400,
};
static const struct ddb_info ddb_m8 = {
.type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX M8",
.regmap = &octopus_mci_map,
.port_num = 4,
.i2c_mask = 0x00,
.tempmon_irq = 24,
.mci_ports = 4,
.mci_type = DDB_TUNER_MCI_M8,
.temp_num = 1,
.lnb_base = 0x400,
};
static const struct ddb_info ddb_m8a = {
.type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX M8A",
.regmap = &octopus_mci_map,
.port_num = 4,
.tempmon_irq = 24,
.mci_ports = 4,
.mci_type = DDB_TUNER_MCI_M8A,
.temp_num = 1,
.lnb_base = 0x400,
};
static const struct ddb_info ddb_m8e = {
.type = DDB_OCTOPUS_MCI,
.name = "Digital Devices MAX M8E",
.regmap = &octopus_mci_map,
.port_num = 4,
.tempmon_irq = 24,
.mci_ports = 4,
.mci_type = DDB_TUNER_MCI_M8E,
.temp_num = 1,
.lnb_base = 0x400,
};
static const struct ddb_info ddb_ci_m2 = {
.type = DDB_OCTOPUS_MCI,
.name = "Digital Devices Octopus CI M2",
.regmap = &octopus_mci_map,
.port_num = 4,
.tempmon_irq = 24,
.mci_ports = 1,
.mci_type = DDB_TUNER_MCI_M2,
.temp_num = 1,
.ci_mask = 0x0c,
.ci_base = 0x400,
.lnb_base = 0x480,
};
static const struct ddb_info ddb_m2 = {
.type = DDB_OCTOPUS_MCI,
.name = "Digital Devices Octopus M2",
.regmap = &octopus_mci_map,
.port_num = 4,
.tempmon_irq = 24,
.mci_ports = 1,
.mci_type = DDB_TUNER_MCI_M2,
.temp_num = 1,
.lnb_base = 0x480,
};
/****************************************************************************/
@ -866,13 +939,19 @@ static const struct ddb_device_id ddb_device_ids[] = {
DDB_DEVID(0x0012, 0x0042, ddb_ci),
DDB_DEVID(0x0013, 0x0043, ddb_ci_s2_pro),
DDB_DEVID(0x0013, 0x0044, ddb_ci_s2_pro_a),
DDB_DEVID(0x0014, 0x0045, ddb_ci_m2),
DDB_DEVID(0x0020, 0x0012, ddb_gtl_mini),
DDB_DEVID(0x0022, 0x0052, ddb_m8),
DDB_DEVID(0x0024, 0x0053, ddb_m8a),
DDB_DEVID(0x0025, 0x0054, ddb_m2),
DDB_DEVID(0x0026, 0x0055, ddb_m8e),
/* Modulators */
DDB_DEVID(0x0201, 0x0001, ddb_mod),
DDB_DEVID(0x0201, 0x0002, ddb_mod),
DDB_DEVID(0x0201, 0x0004, ddb_mod_4), /* dummy entry ! */
DDB_DEVID(0x0203, 0x0001, ddb_mod),
DDB_DEVID(0x0210, 0x0004, ddb_mod_fsm), /* dummy entry ! */
DDB_DEVID(0x0210, 0x0000, ddb_mod_fsm_4), /* dummy entry ! */
DDB_DEVID(0x0210, 0x0001, ddb_mod_fsm_24),
DDB_DEVID(0x0210, 0x0002, ddb_mod_fsm_16),
@ -880,16 +959,8 @@ 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_sdr_iq2),
/* testing on OctopusNet Pro */
DDB_DEVID(0x0320, 0xffff, ddb_octopro_hdin),
DDB_DEVID(0x0321, 0xffff, ddb_none),
DDB_DEVID(0x0322, 0xffff, ddb_octopro),
DDB_DEVID(0x0323, 0xffff, ddb_none),
DDB_DEVID(0x0328, 0xffff, ddb_none),
DDB_DEVID(0x0329, 0xffff, ddb_octopro_hdin),
DDB_DEVID(0xffff, 0xffff, ddb_none),
};

View File

@ -72,11 +72,12 @@ static int search_s2(struct dvb_frontend *fe)
cmd.dvbs2_search.retry = 0;
cmd.dvbs2_search.frequency = p->frequency * 1000;
cmd.dvbs2_search.symbol_rate = p->symbol_rate;
cmd.dvbs2_search.scrambling_sequence_index = 0; //p->scrambling_sequence_index;
cmd.dvbs2_search.scrambling_sequence_index =
p->scrambling_sequence_index;
if (p->stream_id != NO_STREAM_ID_FILTER)
cmd.dvbs2_search.input_stream_id = p->stream_id;
cmd.tuner = state->mci.nr;
cmd.demod = state->mci.tuner;
cmd.tuner = state->mci.tuner;
cmd.demod = state->mci.demod;
cmd.output = state->mci.nr;
stat = ddb_mci_cmd(&state->mci, &cmd, NULL);
@ -404,7 +405,7 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
ddb_mci_get_strength(fe);
if (res.status == MCI_DEMOD_WAIT_SIGNAL)
*status = 0x01;
else if (res.status == M4_DEMOD_WAIT_TS)
else if (res.status == MX_DEMOD_WAIT_TS)
*status = 0x03;
else if (res.status == MCI_DEMOD_TIMEOUT)
*status = FE_TIMEDOUT;
@ -456,6 +457,9 @@ static void release(struct dvb_frontend *fe)
kfree(mci_base);
}
kfree(state);
#ifdef CONFIG_MEDIA_ATTACH
__module_get(THIS_MODULE);
#endif
}
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
@ -473,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 */
@ -525,7 +531,136 @@ static struct mci_cfg ddb_max_m4_cfg = {
.base_init = base_init,
};
struct dvb_frontend *ddb_m4_attach(struct ddb_input *input, int nr, int tuner)
static struct dvb_frontend_ops m_ops = {
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C,
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 */
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
.symbol_rate_min = 100000,
.symbol_rate_max = 100000000,
.frequency_stepsize_hz = 0,
.frequency_tolerance_hz = 0,
.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 |
FE_CAN_QAM_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
},
.release = release,
.get_frontend_algo = get_algo,
.get_frontend = get_frontend,
.read_status = read_status,
.tune = tune,
.sleep = sleep,
};
static struct mci_cfg ddb_max_m_cfg = {
.type = 0,
.fe_ops = &m_ops,
.base_size = sizeof(struct m4_base),
.state_size = sizeof(struct m4),
.init = init,
.base_init = base_init,
};
static struct dvb_frontend_ops m_s_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_ISDBS },
.info = {
.name = "M_S",
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
.symbol_rate_min = 100000,
.symbol_rate_max = 100000000,
.frequency_stepsize_hz = 0,
.frequency_tolerance_hz = 0,
.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 |
FE_CAN_QAM_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
},
.release = release,
.get_frontend_algo = get_algo,
.get_frontend = get_frontend,
.read_status = read_status,
.tune = tune,
.sleep = sleep,
};
static struct mci_cfg ddb_max_m_s_cfg = {
.type = 0,
.fe_ops = &m_s_ops,
.base_size = sizeof(struct m4_base),
.state_size = sizeof(struct m4),
.init = init,
.base_init = base_init,
};
static struct dvb_frontend_ops m_a_ops = {
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C,
SYS_ISDBC,
SYS_DVBT, SYS_DVBT2, SYS_ISDBT,
},
.info = {
.name = "M_A",
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */
.frequency_max_hz = 2150000000, /* DVB-C: 862000000 */
.symbol_rate_min = 100000,
.symbol_rate_max = 100000000,
.frequency_stepsize_hz = 0,
.frequency_tolerance_hz = 0,
.caps = FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 |
FE_CAN_QAM_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS | FE_CAN_2G_MODULATION
},
.release = release,
.get_frontend_algo = get_algo,
.get_frontend = get_frontend,
.read_status = read_status,
.tune = tune,
.sleep = sleep,
};
static struct mci_cfg ddb_max_m_a_cfg = {
.type = 0,
.fe_ops = &m_a_ops,
.base_size = sizeof(struct m4_base),
.state_size = sizeof(struct m4),
.init = init,
.base_init = base_init,
};
static struct mci_cfg *ddb_max_cfgs [] = {
&ddb_max_m4_cfg,
&ddb_max_m_a_cfg,
&ddb_max_m_s_cfg,
&ddb_max_m_cfg,
};
struct dvb_frontend *ddb_mx_attach(struct ddb_input *input, int nr, int tuner, int type)
{
return ddb_mci_attach(input, &ddb_max_m4_cfg, nr, tuner);
return ddb_mci_attach(input, ddb_max_cfgs[type & 3], nr, tuner);
}
EXPORT_SYMBOL(ddb_mx_attach);

View File

@ -84,7 +84,7 @@ int pci_irq_vector(struct pci_dev *dev, unsigned int nr)
/****************************************************************************/
/****************************************************************************/
static void __devexit ddb_irq_disable(struct ddb *dev)
static void ddb_irq_disable(struct ddb *dev)
{
if (dev->link[0].info->regmap->irq_version == 2) {
ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL);
@ -114,7 +114,7 @@ static void __devexit ddb_msi_exit(struct ddb *dev)
#endif
}
static void __devexit ddb_irq_exit(struct ddb *dev)
static void ddb_irq_exit(struct ddb *dev)
{
ddb_irq_disable(dev);
if (dev->msi == 2)
@ -283,11 +283,17 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
pci_set_master(pdev);
#if (KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE)
if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))
#else
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
} else return -ENODEV;
} else
#endif
return -ENODEV;
dev = vzalloc(sizeof(*dev));
if (!dev)
@ -333,7 +339,7 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
u32 min = dev->link[0].info->hw_min;
dev_err(dev->dev, "Update firmware to at least version %u.%u to ensure full functionality!\n",
(min & 0xff0000) >> 16, min & 0xffff);
(min & 0xff0000) >> 16, min & 0xffff);
}
if (dev->link[0].info->ns_num) {
@ -344,45 +350,22 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
if (dev->link[0].info->type != DDB_MOD)
ddbwritel(dev, 0, DMA_BASE_WRITE);
if (dev->link[0].info->type == DDB_MOD
&& dev->link[0].info->version <= 1) {
if (dev->link[0].info->type == DDB_MOD &&
dev->link[0].info->version <= 1) {
if (ddbreadl(dev, 0x1c) == 4)
dev->link[0].info =
get_ddb_info(0xdd01, 0x0201, 0xdd01, 0x0004);
}
if (dev->link[0].info->type == DDB_MOD
&& dev->link[0].info->version == 2) {
u32 lic = ddbreadl(dev, 0x1c) & 7;
if (dev->link[0].info->type == DDB_MOD &&
dev->link[0].info->version == 2) {
if (dev->link[0].ids.revision == 1)
lic = ddbreadl(dev, 0x260) >> 24;
switch (lic) {
case 0:
case 4:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0000);
break;
case 1:
case 8:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0003);
break;
case 2:
case 24:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0001);
break;
case 3:
case 16:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0002);
break;
default:
break;
}
dev->link[0].info = get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0004);
else if ((ddbreadl(dev, 0x1c) & 7) != 7)
dev->link[0].info = get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0004);
}
dev_info(dev->dev, "device name: %s\n", dev->link[0].info->name);
dev_info(dev->dev, "%s\n", dev->link[0].info->name);
dev_info(dev->dev, "HW %08x REGMAP %08x FW %u.%u\n",
dev->link[0].ids.hwid, dev->link[0].ids.regmapid,
(dev->link[0].ids.hwid & 0xff0000) >> 16,
@ -405,7 +388,7 @@ fail:
ddb_unmap(dev);
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
return -1;
return stat;
}
/****************************************************************************/
@ -434,7 +417,12 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = {
DDB_DEVICE_ANY(0x0011),
DDB_DEVICE_ANY(0x0012),
DDB_DEVICE_ANY(0x0013),
DDB_DEVICE_ANY(0x0014),
DDB_DEVICE_ANY(0x0020),
DDB_DEVICE_ANY(0x0022),
DDB_DEVICE_ANY(0x0024),
DDB_DEVICE_ANY(0x0025),
DDB_DEVICE_ANY(0x0026),
DDB_DEVICE_ANY(0x0201),
DDB_DEVICE_ANY(0x0203),
DDB_DEVICE_ANY(0x0210),
@ -442,17 +430,10 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = {
DDB_DEVICE_ANY(0x0221),
DDB_DEVICE_ANY(0x0222),
DDB_DEVICE_ANY(0x0223),
DDB_DEVICE_ANY(0x0320),
DDB_DEVICE_ANY(0x0321),
DDB_DEVICE_ANY(0x0322),
DDB_DEVICE_ANY(0x0323),
DDB_DEVICE_ANY(0x0328),
DDB_DEVICE_ANY(0x0329),
{0}
};
MODULE_DEVICE_TABLE(pci, ddb_id_table);
static pci_ers_result_t ddb_pci_slot_reset(struct pci_dev *dev)
{
pr_info("pci_slot_reset\n");
@ -492,7 +473,6 @@ static const struct pci_error_handlers ddb_error = {
.resume = ddb_pci_resume,
};
static struct pci_driver ddb_pci_driver = {
.name = "ddbridge",
.id_table = ddb_id_table,

View File

@ -28,6 +28,10 @@
/* MAX LNB interface related module parameters */
static int delmode;
module_param(delmode, int, 0444);
MODULE_PARM_DESC(delmode, "frontend delivery system mode");
static int fmode;
module_param(fmode, int, 0444);
MODULE_PARM_DESC(fmode, "frontend emulation mode");
@ -44,31 +48,36 @@ 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)
{
u32 c, v = 0, tag = DDB_LINK_TAG(link);
u32 base = dev->link[link].info->lnb_base;
v = LNB_TONE & (dev->link[link].lnb.tone << (15 - lnb));
ddbwritel(dev, cmd | v, tag | LNB_CONTROL(lnb));
ddbwritel(dev, cmd | v, tag | base | LNB_CONTROL(lnb));
for (c = 0; c < 10; c++) {
v = ddbreadl(dev, tag | LNB_CONTROL(lnb));
v = ddbreadl(dev, tag | base | LNB_CONTROL(lnb));
if ((v & LNB_BUSY) == 0)
break;
msleep(20);
}
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;
@ -91,6 +100,7 @@ static int max_send_master_cmd(struct dvb_frontend *fe,
struct ddb *dev = port->dev;
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
u32 tag = DDB_LINK_TAG(port->lnr);
u32 base = dev->link[port->lnr].info->lnb_base;
int i;
u32 fmode = dev->link[port->lnr].lnb.fmode;
@ -101,13 +111,18 @@ 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);
mutex_lock(&dev->link[port->lnr].lnb.lock);
ddbwritel(dev, 0, tag | LNB_BUF_LEVEL(dvb->input));
ddbwritel(dev, 0, tag | base | LNB_BUF_LEVEL(dvb->input));
for (i = 0; i < cmd->msg_len; i++)
ddbwritel(dev, cmd->msg[i], tag | LNB_BUF_WRITE(dvb->input));
ddbwritel(dev, cmd->msg[i], tag | base | LNB_BUF_WRITE(dvb->input));
lnb_command(dev, port->lnr, dvb->input, LNB_CMD_DISEQC);
mutex_unlock(&dev->link[port->lnr].lnb.lock);
return 0;
@ -117,11 +132,12 @@ static int lnb_send_diseqc(struct ddb *dev, u32 link, u32 input,
struct dvb_diseqc_master_cmd *cmd)
{
u32 tag = DDB_LINK_TAG(link);
u32 base = dev->link[link].info->lnb_base;
int i;
ddbwritel(dev, 0, tag | LNB_BUF_LEVEL(input));
ddbwritel(dev, 0, tag | base | LNB_BUF_LEVEL(input));
for (i = 0; i < cmd->msg_len; i++)
ddbwritel(dev, cmd->msg[i], tag | LNB_BUF_WRITE(input));
ddbwritel(dev, cmd->msg[i], tag | base | LNB_BUF_WRITE(input));
lnb_command(dev, link, input, LNB_CMD_DISEQC);
return 0;
}
@ -369,6 +385,7 @@ static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
struct ddb_port *port = input->port;
struct ddb *dev = port->dev;
u32 tag = DDB_LINK_TAG(port->lnr);
u32 base = dev->link[port->lnr].info->lnb_base;
struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
u32 fmode = dev->link[port->lnr].lnb.fmode;
@ -377,14 +394,14 @@ static int max_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
default:
case 0:
case 3:
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(dvb->input));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(dvb->input));
break;
case 1:
case 2:
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(0));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(1));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(2));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(3));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(0));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(1));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(2));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(3));
break;
}
mutex_unlock(&dev->link[port->lnr].lnb.lock);
@ -465,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;
@ -501,7 +523,8 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
/* MAX MCI related functions */
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_m4_attach(struct ddb_input *input, int nr, int tuner);
struct dvb_frontend *ddb_mx_attach(struct ddb_input *input, int nr, int tuner, int type);
int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
{
@ -519,11 +542,50 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
if (fm >= 3)
tuner = 0;
dvb->fe = ddb_sx8_attach(input, demod, tuner, &dvb->set_input);
dvb->input = tuner;
break;
case DDB_TUNER_MCI_M4:
fm = 0;
dvb->fe = ddb_m4_attach(input, demod, tuner);
dvb->fe = ddb_mx_attach(input, demod, tuner, 0);
dvb->input = tuner;
break;
case DDB_TUNER_MCI_M8:
fm = 3;
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:
case DDB_TUNER_MCI_M8E:
fm = 3;
dvb->fe = ddb_mx_attach(input, demod, tuner, 3);
dvb->input = 0;
break;
case DDB_TUNER_MCI_M2:
{
u32 mode, mmode;
// delmode: 0 - sat,sat 1-cable,cable/sat
switch (delmode & 1) {
case 0:
mode = 2;
mmode = 2; /* M_S */
break;
case 1:
mode = 1;
mmode = demod ? 3 : 1; /* demod 1=M/0=M_A */
break;
}
if (!demod)
ddb_mci_cmd_link_simple(link, MCI_CMD_SET_INPUT_CONFIG,
0xff, mode | (delmode & 0x10));
dvb->fe = ddb_mx_attach(input, demod, tuner, mmode);
dvb->input = tuner;
fm = 0;
break;
}
default:
return -EINVAL;
}
@ -531,7 +593,7 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
dev_err(dev->dev, "No MCI card found!\n");
return -ENODEV;
}
if (input->nr < 4) {
if (!input->nr || (input->nr < 4 && type != DDB_TUNER_MCI_M8)) {
lnb_command(dev, port->lnr, input->nr, LNB_CMD_INIT);
lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF);
}
@ -544,15 +606,10 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd;
dvb->fe->ops.diseqc_send_burst = max_send_burst;
dvb->fe->sec_priv = input;
switch (type) {
case DDB_TUNER_MCI_M4:
break;
default:
if (type == DDB_TUNER_MCI_SX8) {
#ifndef KERNEL_DVB_CORE
dvb->fe->ops.set_input = max_set_input;
#endif
break;
}
dvb->input = tuner;
return 0;
}

View File

@ -134,6 +134,8 @@ int ddb_mci_cmd_link(struct ddb_link *link,
struct mci_result res;
int stat;
if (!link->mci_ok)
return -EFAULT;
if (!result)
result = &res;
mutex_lock(&link->mci_lock);
@ -150,6 +152,17 @@ int ddb_mci_cmd_link(struct ddb_link *link,
return stat;
}
int ddb_mci_cmd_link_simple(struct ddb_link *link, u8 command, u8 demod, u8 value)
{
struct mci_command cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.command = command;
cmd.demod = demod;
cmd.params8[0] = value;
return ddb_mci_cmd_link(link, &cmd, 0);
}
static void mci_handler(void *priv)
{
struct ddb_link *link = (struct ddb_link *) priv;
@ -197,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;
@ -294,8 +307,9 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
p->frequency =
mci->signal_info.dvbs2_signal_info.frequency;
p->symbol_rate =
mci->signal_info.dvbs2_signal_info.symbol_rate;
switch (p->delivery_system) {
default:
case SYS_DVBS:
case SYS_DVBS2:
{
@ -338,6 +352,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
break;
}
case SYS_DVBC_ANNEX_A:
p->modulation =
mci->signal_info.dvbc_signal_info.constellation + 1;
break;
case SYS_DVBT:
break;
@ -347,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

@ -96,11 +96,13 @@
#define SX8_DEMOD_IQ_MODE (1)
#define SX8_DEMOD_WAIT_MATYPE (3)
#define M4_DEMOD_WAIT_TS (6)
#define M4_DEMOD_C2SCAN (16)
#define MX_DEMOD_WAIT_TS (6)
#define MX_DEMOD_C2SCAN (16)
#define MCI_STATUS_OK (0x00)
#define MCI_STATUS_UNSUPPORTED (0x80)
#define MCI_STATUS_BUSY (0xFA)
#define MCI_STATUS_HARDWARE_ERROR (0xFB)
#define MCI_STATUS_INVALID_PARAMETER (0xFC)
#define MCI_STATUS_RETRY (0xFD)
#define MCI_STATUS_NOT_READY (0xFE)
@ -111,6 +113,8 @@
#define MCI_CMD_GETSIGNALINFO (0x03)
//#define MCI_CMD_RFPOWER (0x04)
#define MCI_CMD_SET_INPUT_CONFIG (0x05)
#define MCI_CMD_SEARCH_DVBS (0x10)
#define MCI_CMD_SEARCH_ISDBS (0x11)
@ -123,6 +127,9 @@
#define MCI_CMD_SEARCH_ISDBC (0x25)
#define MCI_CMD_SEARCH_J83B (0x26)
#define MCI_CMD_SEARCH_ATSC (0x27)
#define MCI_CMD_SEARCH_ATSC3 (0x28)
#define MCI_CMD_GET_IQSYMBOL (0x30)
#define MCI_BANDWIDTH_UNKNOWN (0)
@ -140,42 +147,45 @@
#define SX8_CMD_ENABLE_IQOUTPUT (0x44)
#define SX8_CMD_DISABLE_IQOUTPUT (0x45)
#define M4_CMD_GET_L1INFO (0x50)
#define M4_CMD_GET_IDS (0x51)
#define M4_CMD_GET_DVBT_TPS (0x52)
#define MX_CMD_GET_L1INFO (0x50)
#define MX_CMD_GET_IDS (0x51)
#define MX_CMD_GET_DVBT_TPS (0x52)
#define MCI_CMD_GET_BBHEADER (0x53)
#define M4_CMD_GET_ISDBT_TMCC (0x54)
#define M4_CMD_GET_ISDBS_TMCC (0x55)
#define M4_CMD_GET_ISDBC_TSMF (0x56)
#define MX_CMD_GET_ISDBT_TMCC (0x54)
#define MX_CMD_GET_ISDBS_TMCC (0x55)
#define MX_CMD_GET_ISDBC_TSMF (0x56)
#define M4_CMD_GET_BBHEADER (MCI_CMD_GET_BBHEADER)
#define MX_CMD_GET_BBHEADER (MCI_CMD_GET_BBHEADER)
#define M4_L1INFO_SEL_PRE (0)
#define M4_L1INFO_SEL_DSINFO (1)
#define M4_L1INFO_SEL_PLPINFO (2)
#define M4_L1INFO_SEL_PLPINFO_C (3)
#define M4_L1INFO_SEL_SETID (0x80)
#define MX_L1INFO_SEL_PRE (0)
#define MX_L1INFO_SEL_DSINFO (1)
#define MX_L1INFO_SEL_PLPINFO (2)
#define MX_L1INFO_SEL_PLPINFO_C (3)
#define MX_L1INFO_SEL_SETID (0x80)
#define MCI_BANDWIDTH_EXTENSION (0x80) // currently used only for J83B in Japan
#define M4_MODE_DVBSX (2)
#define M4_MODE_DVBC (3)
#define M4_MODE_DVBT (4)
#define M4_MODE_DVBT2 (5)
#define M4_MODE_DVBC2 (6)
#define M4_MODE_J83B (7)
#define M4_MODE_ISDBT (8)
#define M4_MODE_ISDBC (9)
#define M4_MODE_ISDBS (10)
#define MX_MODE_DVBSX (2)
#define MX_MODE_DVBC (3)
#define MX_MODE_DVBT (4)
#define MX_MODE_DVBT2 (5)
#define MX_MODE_DVBC2 (6)
#define MX_MODE_J83B (7)
#define MX_MODE_ISDBT (8)
#define MX_MODE_ISDBC (9)
#define MX_MODE_ISDBS (10)
#define MX_MODE_ISDBS3 (11)
#define MX_MODE_ATSC (12)
#define MX_MODE_ATSC3 (13)
#define M4_DVBC_CONSTELLATION_16QAM (0)
#define M4_DVBC_CONSTELLATION_32QAM (1)
#define M4_DVBC_CONSTELLATION_64QAM (2) // also valid for J83B and ISDB-C
#define M4_DVBC_CONSTELLATION_128QAM (3)
#define M4_DVBC_CONSTELLATION_256QAM (4) // also valid for J83B and ISDB-C
#define MX_DVBC_CONSTELLATION_16QAM (0)
#define MX_DVBC_CONSTELLATION_32QAM (1)
#define MX_DVBC_CONSTELLATION_64QAM (2) // also valid for J83B and ISDB-C
#define MX_DVBC_CONSTELLATION_128QAM (3)
#define MX_DVBC_CONSTELLATION_256QAM (4) // also valid for J83B and ISDB-C
#define M4_SIGNALINFO_FLAG_CHANGE (0x01)
#define M4_SIGNALINFO_FLAG_EWS (0x02)
#define MX_SIGNALINFO_FLAG_CHANGE (0x01)
#define MX_SIGNALINFO_FLAG_EWS (0x02)
#define SX8_ROLLOFF_35 0
#define SX8_ROLLOFF_25 1
@ -263,8 +273,11 @@
#define MOD_QAM_ISDBC_64 (0x08)
#define MOD_QAM_ISDBC_256 (0x09)
#define CMD_GET_SERIALNUMBER (0xF0)
#define CMD_EXPORT_LICENSE (0xF0)
#define CMD_GET_SERIALNUMBER (0xF0)
#define CMD_EXPORT_LICENSE (0xF0)
#define CMD_IMPORT_LICENSE (0xF1)
#define CMD_POWER_DOWN (0xF2)
#define CMD_POWER_UP (0xF3)
struct mod_setup_channels {
u8 flags;
@ -478,6 +491,20 @@ struct mci_command {
struct mod_setup_channels mod_setup_channels[4];
struct mod_setup_stream mod_setup_stream;
struct mod_setup_output mod_setup_output;
struct {
u8 Cmd;
u8 Offset;
u8 Length;
u8 Rsvd1;
u32 Rsvd2[2];
u8 Data[96];
} sx8_packet_filter;
struct {
u8 ID[8];
u8 LK[24];
} license;
};
};
@ -966,6 +993,7 @@ struct mci_cfg {
int ddb_mci_cmd(struct mci *state, struct mci_command *command, struct mci_result *result);
int ddb_mci_cmd_link(struct ddb_link *link, struct mci_command *command, struct mci_result *result);
int ddb_mci_cmd_link_simple(struct ddb_link *link, u8 command, u8 demod, u8 value);
int ddb_mci_get_status(struct mci *mci, struct mci_result *res);
int ddb_mci_get_snr(struct dvb_frontend *fe);
int ddb_mci_get_info(struct mci *mci);

View File

@ -195,6 +195,48 @@ static int mod_calc_obitrate(struct ddb_mod *mod)
return 0;
}
static int mod_set_stream(struct ddb_output *output)
{
struct ddb *dev = output->port->dev;
u32 stream = output->nr;
struct ddb_mod *mod = &dev->mod[output->nr];
struct ddb_link *link = &dev->link[0];
struct mci_result res;
u32 channel;
struct mci_command cmd = {
.mod_command = MOD_SETUP_STREAM,
.mod_channel = stream,
.mod_stream = stream,
.mod_setup_stream = {
.standard = MOD_STANDARD_DVBC_8,
.symbol_rate = mod->symbolrate,
.qam = {
.modulation = mod->modulation - 1,
.rolloff = 13,
}
},
};
if (dev->link[0].info->version != 2)
return 0;
if (dev->link[0].ids.revision != 1)
return 0;
if ((dev->link[0].ids.hwid & 0xffffff) < 9065)
return 0;
if (!mod->frequency && !mod->symbolrate && !mod->modulation)
return 0;
if (mod->frequency)
channel = (mod->frequency - 114000000) / 8000000;
if (!mod->symbolrate)
mod->symbolrate = 6900000;
if (!mod->modulation)
mod->modulation = 5;
cmd.mod_channel = channel;
cmd.mod_setup_stream.symbol_rate = mod->symbolrate;
cmd.mod_setup_stream.qam.modulation = mod->modulation - 1;
return ddb_mci_cmd_link(link, &cmd, &res);
}
static int mod_set_symbolrate(struct ddb_mod *mod, u32 srate)
{
struct ddb *dev = mod->port->dev;
@ -210,6 +252,7 @@ static int mod_set_symbolrate(struct ddb_mod *mod, u32 srate)
}
mod->symbolrate = srate;
mod_calc_obitrate(mod);
mod_set_stream(mod->port->output);
return 0;
}
@ -227,6 +270,7 @@ static int mod_set_modulation(struct ddb_mod *mod,
ddbwritel(dev, qamtab[modulation],
CHANNEL_SETTINGS(mod->port->nr));
mod_calc_obitrate(mod);
mod_set_stream(mod->port->output);
return 0;
}
@ -241,6 +285,7 @@ static int mod_set_frequency(struct ddb_mod *mod, u32 frequency)
if ((freq < 114) || (freq > 874))
return -EINVAL;
mod->frequency = frequency;
mod_set_stream(mod->port->output);
return 0;
}
@ -330,13 +375,19 @@ int ddbridge_mod_output_start(struct ddb_output *output)
u32 LF = 9000000UL;
u32 d = gcd(KF, LF);
u32 checkLF;
#if 0
if (dev->link[0].ids.revision == 1) {
mod->Control |= CHANNEL_CONTROL_ENABLE_DVB;
return -EINVAL;
break;
if ((dev->link[0].ids.revision == 1)) {
if ((dev->link[0].info->version == 2)) {
if ((dev->link[0].ids.hwid & 0xffffff) >= 9065) {
mod->Control |= CHANNEL_CONTROL_ENABLE_DVB;
break;
}
} else {
mod->Control |= CHANNEL_CONTROL_ENABLE_DVB;
break;
}
}
#endif
ddbwritel(dev, mod->modulation - 1, CHANNEL_SETTINGS(Channel));
ddbwritel(dev, Output, CHANNEL_SETTINGS2(Channel));
@ -401,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] = {
@ -523,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;
}
@ -635,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 = 24,
.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;
@ -1744,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:
@ -1787,7 +1858,8 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
(struct dtv_properties __user *) parg;
int i, ret = 0;
if (dev->link[0].info->version >= 16 && cmd != FE_SET_PROPERTY)
if (dev->link[0].info->version >= 16 &&
(cmd != FE_SET_PROPERTY && cmd != IOCTL_DDB_MCI_CMD))
return -EINVAL;
mutex_lock(&dev->ioctl_mutex);
switch (cmd) {
@ -1885,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;
}
@ -1913,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];
@ -2080,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;
@ -2097,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++) {
@ -2112,40 +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 */
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

@ -248,8 +248,7 @@
/* ------------------------------------------------------------------------- */
#define LNB_BASE (0x400)
#define LNB_CONTROL(i) (LNB_BASE + (i) * 0x20 + 0x00)
#define LNB_CONTROL(i) ((i) * 0x20 + 0x00)
#define LNB_CMD (7ULL << 0)
#define LNB_CMD_NOP 0
#define LNB_CMD_INIT 1
@ -260,32 +259,31 @@
#define LNB_CMD_DISEQC 6
#define LNB_CMD_SCIF 7
#define LNB_BUSY BIT_ULL(4)
#define LNB_TONE BIT_ULL(15)
#define LNB_BUSY (1ULL << 4)
#define LNB_TONE (1ULL << 15)
#define LNB_INTERRUPT_BASE 4
#define LNB_STATUS(i) (LNB_BASE + (i) * 0x20 + 0x04)
#define LNB_VOLTAGE(i) (LNB_BASE + (i) * 0x20 + 0x08)
#define LNB_CONFIG(i) (LNB_BASE + (i) * 0x20 + 0x0c)
#define LNB_BUF_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10)
#define LNB_BUF_WRITE(i) (LNB_BASE + (i) * 0x20 + 0x14)
#define LNB_STATUS(i) ((i) * 0x20 + 0x04)
#define LNB_VOLTAGE(i) ((i) * 0x20 + 0x08)
#define LNB_CONFIG(i) ((i) * 0x20 + 0x0c)
#define LNB_BUF_LEVEL(i) ((i) * 0x20 + 0x10)
#define LNB_BUF_WRITE(i) ((i) * 0x20 + 0x14)
#define LNB_SETTING(i) (LNB_BASE + (i) * 0x20 + 0x0c)
#define LNB_FIFO_LEVEL(i) (LNB_BASE + (i) * 0x20 + 0x10)
#define LNB_RESET_FIFO(i) (LNB_BASE + (i) * 0x20 + 0x10)
#define LNB_WRITE_FIFO(i) (LNB_BASE + (i) * 0x20 + 0x14)
#define LNB_SETTING(i) ((i) * 0x20 + 0x0c)
#define LNB_FIFO_LEVEL(i) ((i) * 0x20 + 0x10)
#define LNB_RESET_FIFO(i) ((i) * 0x20 + 0x10)
#define LNB_WRITE_FIFO(i) ((i) * 0x20 + 0x14)
/* ------------------------------------------------------------------------- */
/* CI Interface (only CI-Bridge) */
#define CI_BASE (0x400)
#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00)
#define CI_CONTROL(_ci) ((_ci)->regs + 0x00)
#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04)
#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08)
#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c)
#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10)
#define CI_DO_ATTRIBUTE_RW(_ci) ((_ci)->regs + 0x04)
#define CI_DO_IO_RW(_ci) ((_ci)->regs + 0x08)
#define CI_READDATA(_ci) ((_ci)->regs + 0x0c)
#define CI_DO_READ_ATTRIBUTES(_ci) ((_ci)->regs + 0x10)
#define CI_RESET_CAM (0x00000001)
#define CI_POWER_ON (0x00000002)
@ -296,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)
@ -305,8 +304,8 @@
#define CI_READ_CMD (0x40000000)
#define CI_WRITE_CMD (0x80000000)
#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14)
#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18)
#define CI_BLOCKIO_SEND(_ci) ((_ci)->regs + 0x14)
#define CI_BLOCKIO_RECEIVE(_ci) ((_ci)->regs + 0x18)
#define CI_BLOCKIO_SEND_COMMAND (0x80000000)
#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000)

View File

@ -117,6 +117,9 @@ static void release(struct dvb_frontend *fe)
kfree(mci_base);
}
kfree(state);
#ifdef CONFIG_MEDIA_ATTACH
__module_get(THIS_MODULE);
#endif
}
static int ddb_mci_tsconfig(struct mci *state, u32 config)
@ -149,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) {
@ -168,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;
@ -382,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 =
@ -491,18 +501,21 @@ static int set_parameters(struct dvb_frontend *fe)
stop_iq(fe);
switch (p->modulation) {
case APSK_256:
case APSK_256_L:
mask = 0x7f;
break;
case APSK_128:
mask = 0x3f;
break;
case APSK_64:
case APSK_64_L:
mask = 0x1f;
break;
case APSK_32:
mask = 0x0f;
break;
case APSK_16:
case APSK_16_L:
mask = 0x07;
break;
default:
@ -546,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

@ -147,13 +147,10 @@ struct ddb_info {
u32 type;
#define DDB_NONE 0
#define DDB_OCTOPUS 1
#define DDB_OCTOPUS_CI 2
#define DDB_MOD 3
#define DDB_OCTONET 4
#define DDB_OCTOPUS_MAX 5
#define DDB_OCTOPUS_MAX_CT 6
#define DDB_OCTOPRO 7
#define DDB_OCTOPRO_HDIN 8
#define DDB_OCTOPUS_MCI 9
u32 version;
char *name;
@ -175,11 +172,14 @@ struct ddb_info {
#define TS_QUIRK_ALT_OSC 8
u8 mci_ports;
u8 mci_type;
u8 ci_mask;
u32 tempmon_irq;
u32 lostlock_irq;
u32 mdio_base;
u32 hw_min;
u32 ci_base;
u32 lnb_base;
const struct ddb_regmap *regmap;
};
@ -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;
@ -247,6 +248,7 @@ struct ddb_ci {
struct dvb_ca_en50221 en;
struct ddb_port *port;
u32 nr;
u32 regs;
};
struct ddb_io {
@ -320,6 +322,10 @@ struct ddb_port {
#define DDB_TUNER_MCI 48
#define DDB_TUNER_MCI_SX8 (DDB_TUNER_MCI + 0)
#define DDB_TUNER_MCI_M4 (DDB_TUNER_MCI + 1)
#define DDB_TUNER_MCI_M8 (DDB_TUNER_MCI + 2)
#define DDB_TUNER_MCI_M8A (DDB_TUNER_MCI + 3)
#define DDB_TUNER_MCI_M2 (DDB_TUNER_MCI + 4)
#define DDB_TUNER_MCI_M8E (DDB_TUNER_MCI + 5)
struct ddb_input *input[2];
struct ddb_output *output;
@ -334,6 +340,8 @@ struct mod_base {
u32 frequency;
u32 flat_start;
u32 flat_end;
u32 attenuation;
u32 gain;
};
struct ddb_mod {
@ -417,7 +425,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 */
@ -530,7 +537,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.41"
/* linked function prototypes */
@ -574,5 +581,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

@ -1,19 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* dmxdev.c - DVB demultiplexer device
*
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media 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.
*
*/
#define pr_fmt(fmt) "dmxdev: " fmt
@ -369,13 +359,13 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
static void dvb_dmxdev_filter_timeout(struct timer_list *t)
{
struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer);
struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer);
dmxdevfilter->buffer.error = -ETIMEDOUT;
spin_lock_irq(&dmxdevfilter->dev->lock);
dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
spin_unlock_irq(&dmxdevfilter->dev->lock);
wake_up(&dmxdevfilter->buffer.queue);
dmxdevfilter->buffer.error = -ETIMEDOUT;
spin_lock_irq(&dmxdevfilter->dev->lock);
dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
spin_unlock_irq(&dmxdevfilter->dev->lock);
wake_up(&dmxdevfilter->buffer.queue);
}
static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
@ -384,8 +374,8 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
del_timer(&dmxdevfilter->timer);
if (para->timeout) {
dmxdevfilter->timer.expires =
jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
dmxdevfilter->timer.expires =
jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
add_timer(&dmxdevfilter->timer);
}
}
@ -415,6 +405,7 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
}
}
#endif
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_section_filter *filter,
@ -475,11 +466,14 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_ts_feed *feed,
u32 *buffer_flags)
struct dmx_ts_feed *feed,
u32 *buffer_flags)
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
#ifdef CONFIG_DVB_MMAP
struct dvb_vb2_ctx *ctx;
#endif
int ret;
spin_lock(&dmxdevfilter->dev->lock);
@ -846,6 +840,11 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS;
if (dmxdev->exit) {
mutex_unlock(&dmxdev->mutex);
return -ENODEV;
}
for (i = 0; i < dmxdev->filternum; i++)
if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
break;
@ -1482,7 +1481,7 @@ static const struct dvb_device dvbdev_dvr = {
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
{
int i;
int i, ret;
if (dmxdev->demux->open(dmxdev->demux) < 0)
return -EUSERS;
@ -1505,21 +1504,36 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
DMXDEV_STATE_FREE);
}
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
ret = dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
DVB_DEVICE_DEMUX, dmxdev->filternum);
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
if (ret < 0)
goto err_register_dvbdev;
ret = dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
if (ret < 0)
goto err_register_dvr_dvbdev;
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
return 0;
err_register_dvr_dvbdev:
dvb_unregister_device(dmxdev->dvbdev);
err_register_dvbdev:
vfree(dmxdev->filter);
dmxdev->filter = NULL;
return ret;
}
EXPORT_SYMBOL(dvb_dmxdev_init);
void dvb_dmxdev_release(struct dmxdev *dmxdev)
{
mutex_lock(&dmxdev->mutex);
dmxdev->exit = 1;
mutex_unlock(&dmxdev->mutex);
if (dmxdev->dvbdev->users > 1) {
wait_event(dmxdev->dvbdev->wait_queue,
dmxdev->dvbdev->users == 1);

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* dvb_ca.c: generic DVB functions for EN50221 CAM interfaces
*
@ -158,13 +158,19 @@ 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)
{
unsigned int i;
dvb_free_device(ca->dvbdev);
dvb_device_put(ca->dvbdev);
for (i = 0; i < ca->slot_count; i++)
vfree(ca->slot_info[i].rx_buffer.data);
@ -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

@ -1,20 +1,10 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* dvb_demux.c - DVB kernel demux API
*
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media 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.
*
*/
#define pr_fmt(fmt) "dvb_demux: " fmt
@ -138,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;
@ -256,7 +246,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
{
struct dvb_demux *demux = feed->demux;
struct dmx_section_feed *sec = &feed->feed.sec;
u16 limit, seclen, n;
u16 limit, seclen;
if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
return 0;
@ -285,7 +275,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
/* to be sure always set secbuf */
sec->secbuf = sec->secbuf_base + sec->secbufp;
for (n = 0; sec->secbufp + 2 < limit; n++) {
while (sec->secbufp + 2 < limit) {
seclen = section_length(sec->secbuf);
if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
|| seclen + sec->secbufp > limit)
@ -323,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 */
@ -359,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 */
@ -489,8 +479,8 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
}
dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
pid, demux->cnt_storage[pid],
buf[3] & 0xf);
pid, demux->cnt_storage[pid],
buf[3] & 0xf);
demux->cnt_storage[pid] = buf[3] & 0xf;
}
}

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

@ -141,7 +141,7 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv)
dvb_free_device(fepriv->dvbdev);
dvb_device_put(fepriv->dvbdev);
dvb_frontend_invoke_release(fe, fe->ops.release);
@ -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(fe->dvb->device,
"Frontend requested software zigzag, but didn't set the frequency step size\n");
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;
@ -924,6 +939,7 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
/* If the standard is for satellite, convert frequencies to kHz */
switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS:
case SYS_DVBS2:
case SYS_TURBO:
@ -949,6 +965,7 @@ static u32 dvb_frontend_get_stepsize(struct dvb_frontend *fe)
u32 step = max(fe_step, tuner_step);
switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS:
case SYS_DVBS2:
case SYS_TURBO:
@ -980,6 +997,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
/* range check: symbol rate */
switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS:
case SYS_DVBS2:
case SYS_TURBO:
@ -1047,6 +1065,10 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
c->input = NO_INPUT;
switch (c->delivery_system) {
case SYS_DSS:
c->modulation = QPSK;
c->rolloff = ROLLOFF_20;
break;
case SYS_DVBS:
case SYS_DVBS2:
case SYS_TURBO:
@ -1839,6 +1861,7 @@ static void prepare_tuning_algo_parameters(struct dvb_frontend *fe)
} else {
/* default values */
switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS:
case SYS_DVBS2:
case SYS_ISDBS:
@ -2312,6 +2335,9 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
case SYS_DVBC_ANNEX_C:
rolloff = 113;
break;
case SYS_DSS:
rolloff = 120;
break;
case SYS_DVBS:
case SYS_TURBO:
case SYS_ISDBS:
@ -2582,8 +2608,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_DISEQC_SEND_BURST:
if (fe->ops.diseqc_send_burst) {
err = fe->ops.diseqc_send_burst(fe,
(enum fe_sec_mini_cmd)parg);
err = fe->ops.diseqc_send_burst(fe, (long)parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
@ -2591,9 +2616,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_SET_TONE:
if (fe->ops.set_tone) {
err = fe->ops.set_tone(fe,
(enum fe_sec_tone_mode)parg);
fepriv->tone = (enum fe_sec_tone_mode)parg;
fepriv->tone = (long)parg;
err = fe->ops.set_tone(fe, fepriv->tone);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
@ -2601,9 +2625,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_SET_VOLTAGE:
if (fe->ops.set_voltage) {
err = fe->ops.set_voltage(fe,
(enum fe_sec_voltage)parg);
fepriv->voltage = (enum fe_sec_voltage)parg;
fepriv->voltage = (long)parg;
err = fe->ops.set_voltage(fe, fepriv->voltage);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
@ -2767,7 +2790,6 @@ typedef unsigned int __poll_t;
#define EPOLLOUT POLLOUT
#endif
static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
{
struct dvb_device *dvbdev = file->private_data;
@ -2796,7 +2818,17 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
if (fe->exit == DVB_FE_DEVICE_REMOVED)
return -ENODEV;
if (adapter->mfe_shared) {
if (adapter->mfe_shared == 2) {
mutex_lock(&adapter->mfe_lock);
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
if (adapter->mfe_dvbdev &&
!adapter->mfe_dvbdev->writers) {
mutex_unlock(&adapter->mfe_lock);
return -EBUSY;
}
adapter->mfe_dvbdev = dvbdev;
}
} else if (adapter->mfe_shared) {
mutex_lock(&adapter->mfe_lock);
if (!adapter->mfe_dvbdev)
@ -2974,7 +3006,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe)
else if (fe->ops.tuner_ops.sleep)
ret = fe->ops.tuner_ops.sleep(fe);
if (fe->ops.sleep)
if (fe->ops.suspend)
ret = fe->ops.suspend(fe);
else if (fe->ops.sleep)
ret = fe->ops.sleep(fe);
return ret;
@ -2990,7 +3024,9 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
fe->id);
fe->exit = DVB_FE_DEVICE_RESUME;
if (fe->ops.init)
if (fe->ops.resume)
ret = fe->ops.resume(fe);
else if (fe->ops.init)
ret = fe->ops.init(fe);
if (fe->ops.tuner_ops.resume)
@ -3024,6 +3060,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
.name = fe->ops.info.name,
#endif
};
int ret;
dev_dbg(dvb->device, "%s:\n", __func__);
@ -3053,8 +3090,14 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF;
dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND, 0);
ret = dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND, 0);
if (ret) {
dvb_frontend_put(fe);
mutex_unlock(&frontend_mutex);
return ret;
}
dev_info(fe->dvb->device,
"DVB: registering adapter %i frontend %i (%s)...\n",

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

@ -60,6 +60,9 @@
#include <media/dvb_demux.h>
#include <media/dvb_net.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
#include <linux/nospec.h>
#endif
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
{
@ -662,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);
@ -678,7 +681,7 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
hexdump(ule_where - TS_SZ, TS_SZ);
}
ule_dump = 1;
#endif
#endif
h->dev->stats.rx_errors++;
h->dev->stats.rx_crc_errors++;
@ -992,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;
@ -1062,7 +1065,7 @@ static int dvb_net_feed_start(struct net_device *dev)
int ret = 0, i;
struct dvb_net_priv *priv = netdev_priv(dev);
struct dmx_demux *demux = priv->demux;
const unsigned char *mac = (unsigned char *) dev->dev_addr;
const unsigned char *mac = (const unsigned char *) dev->dev_addr;
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
mutex_lock(&priv->mutex);
@ -1282,7 +1285,11 @@ static int dvb_net_set_mac (struct net_device *dev, void *p)
struct dvb_net_priv *priv = netdev_priv(dev);
struct sockaddr *addr=p;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0))
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
#else
eth_hw_addr_set(dev, addr->sa_data);
#endif
if (netif_running(dev))
schedule_work(&priv->restart_net_feed_wq);
@ -1381,8 +1388,11 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
dvbnet->dvbdev->adapter->num, if_num);
net->addr_len = 6;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0))
memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);
#else
eth_hw_addr_set(net, dvbnet->dvbdev->adapter->proposed_mac);
#endif
dvbnet->device[if_num] = net;
priv = netdev_priv(net);
@ -1477,14 +1487,21 @@ static int dvb_net_do_ioctl(struct file *file,
struct net_device *netdev;
struct dvb_net_priv *priv_data;
struct dvb_net_if *dvbnetif = parg;
int if_num = dvbnetif->if_num;
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
!dvbnet->state[dvbnetif->if_num]) {
if (if_num >= DVB_NET_DEVICES_MAX) {
ret = -EINVAL;
goto ioctl_error;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
#endif
if (!dvbnet->state[if_num]) {
ret = -EINVAL;
goto ioctl_error;
}
netdev = dvbnet->device[dvbnetif->if_num];
netdev = dvbnet->device[if_num];
priv_data = netdev_priv(netdev);
dvbnetif->pid=priv_data->pid;
@ -1537,14 +1554,21 @@ static int dvb_net_do_ioctl(struct file *file,
struct net_device *netdev;
struct dvb_net_priv *priv_data;
struct __dvb_net_if_old *dvbnetif = parg;
int if_num = dvbnetif->if_num;
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
!dvbnet->state[dvbnetif->if_num]) {
if (if_num >= DVB_NET_DEVICES_MAX) {
ret = -EINVAL;
goto ioctl_error;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
#endif
if (!dvbnet->state[if_num]) {
ret = -EINVAL;
goto ioctl_error;
}
netdev = dvbnet->device[dvbnetif->if_num];
netdev = dvbnet->device[if_num];
priv_data = netdev_priv(netdev);
dvbnetif->pid=priv_data->pid;
@ -1566,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;
}
@ -1582,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,
};
@ -1601,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);
@ -1623,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

@ -63,7 +63,7 @@ int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
* this pairs with smp_store_release() in dvb_ringbuffer_write(),
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
*
* for memory barriers also see Documentation/core-api/circular-buffers.txt
* for memory barriers also see Documentation/core-api/circular-buffers.rst
*/
return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
#endif
@ -75,7 +75,7 @@ ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
{
ssize_t free;
/* ACCESS_ONCE() to load read pointer on writer side
/* READ_ONCE() to load read pointer on writer side
* this pairs with smp_store_release() in dvb_ringbuffer_read(),
* dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(),
* or dvb_ringbuffer_reset()
@ -171,7 +171,7 @@ ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, si
#else
/* smp_store_release() for read pointer update to ensure
* that buf is not overwritten until read is complete,
* this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
* this pairs with READ_ONCE() in dvb_ringbuffer_free()
*/
smp_store_release(&rbuf->pread, 0);
#endif
@ -203,7 +203,7 @@ void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
#else
/* smp_store_release() for read pointer update to ensure
* that buf is not overwritten until read is complete,
* this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
* this pairs with READ_ONCE() in dvb_ringbuffer_free()
*/
smp_store_release(&rbuf->pread, 0);
#endif
@ -391,7 +391,9 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t*
idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
}
consumed = (idx - rbuf->pread) % rbuf->size;
consumed = (idx - rbuf->pread);
if (consumed < 0)
consumed += rbuf->size;
while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {

View File

@ -5,10 +5,6 @@
* Copyright (C) 2015 Samsung Electronics
*
* Author: jh1009.sung@samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*/
#include <linux/err.h>
@ -171,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;
@ -358,7 +351,14 @@ 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)
{
vb2_core_querybuf(&ctx->vb_q, b->index, b);
struct vb2_queue *q = &ctx->vb_q;
struct vb2_buffer *vb2 = vb2_get_buffer(q, b->index);
if (!vb2) {
dprintk(1, "[%s] invalid buffer index\n", ctx->name);
return -EINVAL;
}
vb2_core_querybuf(&ctx->vb_q, vb2, b);
dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
return 0;
}
@ -368,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,
@ -382,9 +382,15 @@ 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;
ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL);
if (!vb2) {
dprintk(1, "[%s] invalid buffer index\n", ctx->name);
return -EINVAL;
}
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

@ -1,20 +1,10 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* dvbdev.c
*
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media 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.
*
*/
#define pr_fmt(fmt) "dvbdev: " fmt
@ -40,6 +30,7 @@
#endif
static DEFINE_MUTEX(dvbdev_mutex);
static LIST_HEAD(dvbdevfops_list);
static int dvbdev_debug;
module_param(dvbdev_debug, int, 0644);
@ -93,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;
@ -118,7 +109,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
new_fops = fops_get(dvbdev->fops);
if (!new_fops)
goto fail;
file->private_data = dvbdev;
file->private_data = dvb_device_get(dvbdev);
replace_fops(file, new_fops);
if (file->f_op->open)
err = file->f_op->open(inode, file);
@ -132,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,
@ -145,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;
@ -175,18 +173,21 @@ 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);
return 0;
}
EXPORT_SYMBOL(dvb_generic_release);
long dvb_generic_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
@ -202,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;
@ -262,9 +263,9 @@ 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, ret = 0;
int i;
dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads),
GFP_KERNEL);
@ -281,6 +282,7 @@ static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
for (i = 0; i < npads; i++) {
struct media_pad *pads = &dvbdev->tsout_pads[i];
struct media_entity *entity = &dvbdev->tsout_entity[i];
int ret;
entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
if (!entity->name)
@ -353,6 +355,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
GFP_KERNEL);
if (!dvbdev->pads) {
kfree(dvbdev->entity);
dvbdev->entity = NULL;
return -ENOMEM;
}
}
@ -402,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;
@ -469,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__);
@ -484,41 +489,69 @@ 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));
kref_init(&dvbdev->ref);
dvbdev->type = type;
dvbdev->id = id;
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);
@ -527,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] = dvbdev;
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)
@ -574,36 +612,44 @@ void dvb_remove_device(struct dvb_device *dvbdev)
down_write(&minor_rwsem);
dvb_minors[dvbdev->minor] = NULL;
dvb_device_put(dvbdev);
up_write(&minor_rwsem);
dvb_media_device_free(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);
void dvb_free_device(struct dvb_device *dvbdev)
static void dvb_free_device(struct kref *ref)
{
if (!dvbdev)
return;
struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
kfree (dvbdev->fops);
kfree (dvbdev);
kfree(dvbdev);
}
EXPORT_SYMBOL(dvb_free_device);
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
{
kref_get(&dvbdev->ref);
return 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);
dvb_free_device(dvbdev);
dvb_device_put(dvbdev);
}
EXPORT_SYMBOL(dvb_unregister_device);
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
static int dvb_create_io_intf_links(struct dvb_adapter *adap,
@ -636,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";
@ -709,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;
@ -731,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;
@ -771,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;
}
@ -840,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;
@ -849,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;
@ -862,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)
@ -889,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);
@ -900,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);
@ -914,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;
@ -946,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:
@ -956,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;
}
@ -968,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)))
@ -988,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))
@ -1041,9 +1088,13 @@ EXPORT_SYMBOL_GPL(dvb_module_release);
#endif
#endif
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
#else
static int dvb_uevent(const struct device *dev, struct kobj_uevent_env *env)
#endif
{
struct dvb_device *dvbdev = dev_get_drvdata(dev);
const struct dvb_device *dvbdev = dev_get_drvdata(dev);
add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
@ -1051,9 +1102,13 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
static char *dvb_devnode(struct device *dev, umode_t *mode)
#else
static char *dvb_devnode(const struct device *dev, umode_t *mode)
#endif
{
struct dvb_device *dvbdev = dev_get_drvdata(dev);
const struct dvb_device *dvbdev = dev_get_drvdata(dev);
return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
@ -1065,18 +1120,24 @@ 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;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0))
dvb_class = class_create(THIS_MODULE, "dvb");
#else
dvb_class = class_create("dvb");
#endif
if (IS_ERR(dvb_class)) {
retval = PTR_ERR(dvb_class);
goto error;
@ -1091,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

@ -1,3 +1,11 @@
#include <linux/version.h>
#if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE)
#define __devexit
#define __devinit
#define __devinitconst
#endif
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
@ -13,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

@ -7,21 +7,6 @@
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Lesser 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 _DVBAUDIO_H_
@ -54,7 +39,7 @@ typedef enum {
typedef struct audio_mixer {
unsigned int volume_left;
unsigned int volume_right;
/* what else do we need? bass, pass-through, ... */
/* what else do we need? bass, pass-through, ... */
} audio_mixer_t;

View File

@ -5,21 +5,6 @@
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Lesser 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 _DVBCA_H_
@ -132,11 +117,6 @@ struct ca_descr {
unsigned char cw[8];
};
struct ca_pid {
unsigned int pid;
int index;/* -1 == disable*/
};
#define CA_RESET _IO('o', 128)
#define CA_GET_CAP _IOR('o', 129, struct ca_caps)
#define CA_GET_SLOT_INFO _IOR('o', 130, struct ca_slot_info)
@ -144,7 +124,6 @@ struct ca_pid {
#define CA_GET_MSG _IOR('o', 132, struct ca_msg)
#define CA_SEND_MSG _IOW('o', 133, struct ca_msg)
#define CA_SET_DESCR _IOW('o', 134, struct ca_descr)
#define CA_SET_PID _IOW('o', 135, struct ca_pid)
#if !defined(__KERNEL__)
@ -154,7 +133,6 @@ typedef struct ca_descr_info ca_descr_info_t;
typedef struct ca_caps ca_caps_t;
typedef struct ca_msg ca_msg_t;
typedef struct ca_descr ca_descr_t;
typedef struct ca_pid ca_pid_t;
#endif

View File

@ -5,21 +5,6 @@
* Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
* & Ralph Metzler <ralph@convergence.de>
* for convergence integrated media 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 _UAPI_DVBDMX_H_

View File

@ -7,21 +7,6 @@
* Holger Waechtler <holger@convergence.de>
* Andre Draszik <ad@convergence.de>
* for convergence integrated media 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 _DVBFRONTEND_H_
@ -282,7 +267,6 @@ enum fe_spectral_inversion {
/**
* enum fe_code_rate - Type of Forward Error Correction (FEC)
*
*
* @FEC_NONE: No Forward Error Correction Code
* @FEC_1_2: Forward Error Correction Code 1/2
* @FEC_2_3: Forward Error Correction Code 2/3
@ -296,6 +280,28 @@ enum fe_spectral_inversion {
* @FEC_3_5: Forward Error Correction Code 3/5
* @FEC_9_10: Forward Error Correction Code 9/10
* @FEC_2_5: Forward Error Correction Code 2/5
* @FEC_1_3: Forward Error Correction Code 1/3
* @FEC_1_4: Forward Error Correction Code 1/4
* @FEC_5_9: Forward Error Correction Code 5/9
* @FEC_7_9: Forward Error Correction Code 7/9
* @FEC_8_15: Forward Error Correction Code 8/15
* @FEC_11_15: Forward Error Correction Code 11/15
* @FEC_13_18: Forward Error Correction Code 13/18
* @FEC_9_20: Forward Error Correction Code 9/20
* @FEC_11_20: Forward Error Correction Code 11/20
* @FEC_23_36: Forward Error Correction Code 23/36
* @FEC_25_36: Forward Error Correction Code 25/36
* @FEC_13_45: Forward Error Correction Code 13/45
* @FEC_26_45: Forward Error Correction Code 26/45
* @FEC_28_45: Forward Error Correction Code 28/45
* @FEC_32_45: Forward Error Correction Code 32/45
* @FEC_77_90: Forward Error Correction Code 77/90
* @FEC_11_45: Forward Error Correction Code 11/45
* @FEC_4_15: Forward Error Correction Code 4/15
* @FEC_14_45: Forward Error Correction Code 14/45
* @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.
*/
@ -313,8 +319,28 @@ enum fe_code_rate {
FEC_3_5,
FEC_9_10,
FEC_2_5,
FEC_1_4,
FEC_1_3,
FEC_1_4,
FEC_5_9,
FEC_7_9,
FEC_8_15,
FEC_11_15,
FEC_13_18,
FEC_9_20,
FEC_11_20,
FEC_23_36,
FEC_25_36,
FEC_13_45,
FEC_26_45,
FEC_28_45,
FEC_32_45,
FEC_77_90,
FEC_11_45,
FEC_4_15,
FEC_14_45,
FEC_7_15,
FEC_29_45,
FEC_31_45,
};
/**
@ -333,6 +359,16 @@ enum fe_code_rate {
* @APSK_32: 32-APSK modulation
* @DQPSK: DQPSK modulation
* @QAM_4_NR: 4-QAM-NR modulation
* @QAM_1024: 1024-QAM modulation
* @QAM_4096: 4096-QAM modulation
* @APSK_8_L: 8APSK-L modulation
* @APSK_16_L: 16APSK-L modulation
* @APSK_32_L: 32APSK-L modulation
* @APSK_64: 64APSK modulation
* @APSK_64_L: 64APSK-L modulation
* @APSK_128: 128APSK modulation
* @APSK_256: 256APSK modulation
* @APSK_256_L: 256APSK-L modulation
*
* Please note that not all modulations are supported by a given standard.
*
@ -352,9 +388,16 @@ enum fe_modulation {
APSK_32,
DQPSK,
QAM_4_NR,
QAM_1024,
QAM_4096,
APSK_8_L,
APSK_16_L,
APSK_32_L,
APSK_64,
APSK_64_L,
APSK_128,
APSK_256,
APSK_256_L,
};
/**
@ -409,6 +452,7 @@ enum fe_transmit_mode {
* @GUARD_INTERVAL_PN420: PN length 420 (1/4)
* @GUARD_INTERVAL_PN595: PN length 595 (1/6)
* @GUARD_INTERVAL_PN945: PN length 945 (1/9)
* @GUARD_INTERVAL_1_64: Guard interval 1/64
*
* Please note that not all guard intervals are supported by a given standard.
*/
@ -424,6 +468,7 @@ enum fe_guard_interval {
GUARD_INTERVAL_PN420,
GUARD_INTERVAL_PN595,
GUARD_INTERVAL_PN945,
GUARD_INTERVAL_1_64,
};
/**
@ -553,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
@ -577,6 +622,9 @@ enum fe_pilot {
* @ROLLOFF_20: Roloff factor: α=20%
* @ROLLOFF_25: Roloff factor: α=25%
* @ROLLOFF_AUTO: Auto-detect the roloff factor.
* @ROLLOFF_15: Rolloff factor: α=15%
* @ROLLOFF_10: Rolloff factor: α=10%
* @ROLLOFF_5: Rolloff factor: α=5%
*
* .. note:
*
@ -603,6 +651,8 @@ enum fe_rolloff {
* Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM)
* @SYS_DVBC_ANNEX_C:
* Cable TV: DVB-C following ITU-T J.83 Annex C spec
* @SYS_DVBC2:
* Cable TV: DVB-C2
* @SYS_ISDBC:
* Cable TV: ISDB-C (no drivers yet)
* @SYS_DVBT:
@ -620,7 +670,7 @@ enum fe_rolloff {
* @SYS_DVBS:
* Satellite TV: DVB-S
* @SYS_DVBS2:
* Satellite TV: DVB-S2
* Satellite TV: DVB-S2 and DVB-S2X
* @SYS_TURBO:
* Satellite TV: DVB-S Turbo
* @SYS_ISDBS:
@ -730,7 +780,7 @@ enum atscmh_rs_frame_mode {
};
/**
* enum atscmh_rs_code_mode
* enum atscmh_rs_code_mode - ATSC-M/H Reed Solomon modes
* @ATSCMH_RSCODE_211_187: Reed Solomon code (211,187).
* @ATSCMH_RSCODE_223_187: Reed Solomon code (223,187).
* @ATSCMH_RSCODE_235_187: Reed Solomon code (235,187).
@ -771,8 +821,8 @@ enum fecap_scale_params {
* struct dtv_stats - Used for reading a DTV status property
*
* @scale:
* Filled with enum fecap_scale_params - the scale in usage
* for that parameter
* Filled with enum fecap_scale_params - the scale in usage
* for that parameter
*
* @svalue:
* integer value of the measure, for %FE_SCALE_DECIBEL,
@ -841,18 +891,18 @@ struct dtv_fe_stats {
/**
* struct dtv_property - store one of frontend command and its value
*
* @cmd: Digital TV command.
* @reserved: Not used.
* @u: Union with the values for the command.
* @u.data: A unsigned 32 bits integer with command value.
* @u.buffer: Struct to store bigger properties.
* Currently unused.
* @u.buffer.data: an unsigned 32-bits array.
* @u.buffer.len: number of elements of the buffer.
* @u.buffer.reserved1: Reserved.
* @u.buffer.reserved2: Reserved.
* @u.st: a &struct dtv_fe_stats array of statistics.
* @result: Currently unused.
* @cmd: Digital TV command.
* @reserved: Not used.
* @u: Union with the values for the command.
* @u.data: A unsigned 32 bits integer with command value.
* @u.buffer: Struct to store bigger properties.
* Currently unused.
* @u.buffer.data: an unsigned 32-bits array.
* @u.buffer.len: number of elements of the buffer.
* @u.buffer.reserved1: Reserved.
* @u.buffer.reserved2: Reserved.
* @u.st: a &struct dtv_fe_stats array of statistics.
* @result: Currently unused.
*
*/
struct dtv_property {

View File

@ -5,21 +5,6 @@
* Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
* & Ralph Metzler <ralph@convergence.de>
* for convergence integrated media 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 _DVBNET_H_

View File

@ -7,21 +7,6 @@
* Copyright (C) 2001 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Lesser 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 _DVBOSD_H_

View File

@ -4,27 +4,12 @@
*
* Copyright (C) 2000 Holger Waechtler <holger@convergence.de>
* for convergence integrated media 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 _DVBVERSION_H_
#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

@ -7,21 +7,6 @@
* Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
* & Ralph Metzler <ralph@convergence.de>
* for convergence integrated media 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 _UAPI_DVBVIDEO_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

@ -369,6 +369,10 @@ struct dvb_frontend_internal_info {
* allocated by the driver.
* @init: callback function used to initialize the tuner device.
* @sleep: callback function used to put the tuner to sleep.
* @suspend: callback function used to inform that the Kernel will
* suspend.
* @resume: callback function used to inform that the Kernel is
* resuming from suspend.
* @write: callback function used by some demod legacy drivers to
* allow other drivers to write data into their registers.
* Should not be used on new drivers.
@ -438,7 +442,6 @@ struct dvb_frontend_internal_info {
* @analog_ops: pointer to &struct analog_demod_ops
*/
struct dvb_frontend_ops {
struct dvb_frontend_internal_info info;
u8 delsys[MAX_DELSYS];
@ -449,6 +452,8 @@ struct dvb_frontend_ops {
int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe);
int (*suspend)(struct dvb_frontend *fe);
int (*resume)(struct dvb_frontend *fe);
int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
@ -765,7 +770,8 @@ void dvb_frontend_detach(struct dvb_frontend *fe);
* &dvb_frontend_ops.tuner_ops.suspend\(\) is available, it calls it. Otherwise,
* it will call &dvb_frontend_ops.tuner_ops.sleep\(\), if available.
*
* It will also call &dvb_frontend_ops.sleep\(\) to put the demod to suspend.
* It will also call &dvb_frontend_ops.suspend\(\) to put the demod to suspend,
* if available. Otherwise it will call &dvb_frontend_ops.sleep\(\).
*
* The drivers should also call dvb_frontend_suspend\(\) as part of their
* handler for the &device_driver.suspend\(\).
@ -779,7 +785,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe);
*
* This function resumes the usual operation of the tuner after resume.
*
* In order to resume the frontend, it calls the demod &dvb_frontend_ops.init\(\).
* In order to resume the frontend, it calls the demod
* &dvb_frontend_ops.resume\(\) if available. Otherwise it calls demod
* &dvb_frontend_ops.init\(\).
*
* If &dvb_frontend_ops.tuner_ops.resume\(\) is available, It, it calls it.
* Otherwise,t will call &dvb_frontend_ops.tuner_ops.init\(\), if available.

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

@ -214,7 +214,7 @@ extern ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
* @buf: Buffer to write.
* @len: Length of buffer (currently limited to 65535 bytes max).
*
* Return: Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
* Return: Number of bytes written, or -EFAULT, -ENOMEM, -EINVAL.
*/
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf,
size_t len);

View File

@ -35,7 +35,7 @@
#endif
#endif
#define DVB_MAX_ADAPTERS 64
#define DVB_MAX_ADAPTERS 64
#define DVB_UNSET (-1)
@ -96,7 +96,11 @@ struct dvb_frontend;
* @device: pointer to struct device
* @module: pointer to struct module
* @mfe_shared: indicates mutually exclusive frontends.
* Use of this flag is currently deprecated.
* 1 = legacy exclusion behavior: blocking any open() call
* 2 = enhanced exclusion behavior, emulating the standard
* behavior of busy frontends: allowing read-only sharing
* and otherwise returning immediately with -EBUSY when any
* of the frontends is already opened with write access.
* @mfe_dvbdev: Frontend device in use, in the case of MFE
* @mfe_lock: Lock to prevent using the other frontends when MFE is
* used.
@ -135,6 +139,7 @@ struct dvb_adapter {
* struct dvb_device - represents a DVB device node
*
* @list_head: List head with all DVB devices
* @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.
@ -165,6 +170,7 @@ struct dvb_adapter {
*/
struct dvb_device {
struct list_head list_head;
struct kref ref;
const struct file_operations *fops;
struct dvb_adapter *adapter;
enum dvb_device_type type;
@ -176,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 */
@ -196,6 +203,35 @@ 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
*
* @dvbdev: pointer to struct dvb_device
*/
struct dvb_device *dvb_device_get(struct dvb_device *dvbdev);
/**
* dvb_device_put - Decrease dvb_device reference
*
* @dvbdev: pointer to struct dvb_device
*/
void dvb_device_put(struct dvb_device *dvbdev);
/**
* dvb_register_adapter - Registers a new DVB adapter
*
@ -240,29 +276,16 @@ int dvb_register_device(struct dvb_adapter *adap,
/**
* dvb_remove_device - Remove a registered DVB device
*
* This does not free memory. To do that, call dvb_free_device().
*
* @dvbdev: pointer to struct dvb_device
*
* This does not free memory. dvb_free_device() will do that when
* reference counter is empty
*/
void dvb_remove_device(struct dvb_device *dvbdev);
/**
* dvb_free_device - Free memory occupied by a DVB device.
*
* Call dvb_unregister_device() before calling this function.
*
* @dvbdev: pointer to struct dvb_device
*/
void dvb_free_device(struct dvb_device *dvbdev);
/**
* dvb_unregister_device - Unregisters a DVB device
*
* This is a combination of dvb_remove_device() and dvb_free_device().
* Using this function is usually a mistake, and is often an indicator
* for a use-after-free bug (when a userspace process keeps a file
* handle to a detached device).
*
* @dvbdev: pointer to struct dvb_device
*/
void dvb_unregister_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':
@ -391,6 +518,10 @@ int main(int argc, char **argv)
printf("unknown mtype %s\n", optarg);
break;
case 'd':
if (!strcmp(optarg, "C2"))
delsys = SYS_DVBC2;
if (!strcmp(optarg, "DVBC2"))
delsys = SYS_DVBC2;
if (!strcmp(optarg, "C"))
delsys = SYS_DVBC_ANNEX_A;
if (!strcmp(optarg, "DVBC"))
@ -419,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"))
@ -442,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"
@ -452,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");
@ -472,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)
@ -480,7 +630,7 @@ int main(int argc, char **argv)
else
fe = dddvb_fe_alloc(dd, delsys);
if (!fe) {
fprintf(fout,"dddvb_fe_alloc failed\n");
fprintf(fout,"dddvb_fe_alloc failed\n");
exit(-1);
}
dddvb_param_init(&p);
@ -495,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;
@ -519,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;
@ -567,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,23 +184,22 @@ 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)
@ -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,9 +291,27 @@ 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) {
@ -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;
@ -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;
@ -639,10 +692,13 @@ static int init_ca(struct dddvb *dd, int a, int f, int fd)
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,6 +710,15 @@ 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

@ -30,7 +30,7 @@ LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc_num(struct dddvb *dd, uint32_t
pthread_mutex_unlock(&dd->lock);
if (dddvb_fe_start(fe) < 0) {
dbgprintf(DEBUG_SYS, "fe %d busy\n", fe->nr);
return 0;
return NULL;
}
dbgprintf(DEBUG_SYS, "Allocated fe %d = %d/%d, fd=%d\n",
fe->nr, fe->anum, fe->fnum, fe->fd);
@ -40,22 +40,25 @@ LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc_num(struct dddvb *dd, uint32_t
LIBDDDVB_EXPORTED struct dddvb_fe *dddvb_fe_alloc(struct dddvb *dd, uint32_t type)
{
int i;
struct dddvb_fe *fe = NULL;
struct dddvb_fe *fe = NULL, *tfe;
pthread_mutex_lock(&dd->lock);
dbgprintf(DEBUG_SYS, "alloc_fe type %u\n", type);
for (i = 0; i < dd->dvbfe_num; i++) {
fe = &dd->dvbfe[i];
if (fe->state == 0 &&
(fe->type & (1UL << type))) {
tfe = &dd->dvbfe[i];
if (tfe->state == 0 &&
(tfe->type & (1UL << type))) {
fe = dddvb_fe_alloc_num(dd, type, i);
if (fe)
break;
}
}
pthread_mutex_unlock(&dd->lock);
if (!fe)
dbgprintf(DEBUG_SYS, "alloc_fe type %u\n failed!", type);
else
dbgprintf(DEBUG_SYS, "alloc_fe type %u success!\n", type);
return fe;
}
LIBDDDVB_EXPORTED int dddvb_dvb_tune(struct dddvb_fe *fe, struct dddvb_params *p)
@ -68,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) {
@ -87,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)
@ -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

@ -329,14 +329,12 @@ static void calc_lq(struct dddvb_fe *fe)
{
struct dtv_fe_stats st;
int64_t str, snr;
uint32_t mod, fec, ber_num, ber_den, trans, pilot = 0, quality = 0, freq;
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,17 +358,25 @@ 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);
get_property(fe->fd, DTV_SYMBOL_RATE, &rate);
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_FREQUENCY, &freq);
dbgprintf(DEBUG_DVB, "fe%d: actual frequency=%u\n", fe->nr, freq);
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_FREQUENCY, &freq);
dbgprintf(DEBUG_DVB, "fe%d: actual frequency=%u\n", fe->nr, freq);
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: