Compare commits

..

302 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
internal
e0539d5074 Merge branch 'internal' 2022-05-02 21:41:27 +02:00
internal
457cb550bb do not use diseqc for scif type 3 2022-05-02 21:38:43 +02:00
internal
d0793274d2 Merge branch 'internal' 2022-03-22 15:23:26 +01:00
internal
ffe8764c01 support bigger Winbond flashs. 2022-03-22 15:22:43 +01:00
internal
fb4f263aa3 Merge branch 'internal' 2022-03-21 17:40:59 +01:00
internal
0892a225d2 support bigger Winbond flashs. 2022-03-21 17:40:11 +01:00
drmocm
431dd4f5ee more examples 2022-03-14 18:46:05 +01:00
rjkm
e9ccab3578 Merge branch 'internal' 2022-02-20 23:22:36 +01:00
rjkm
cdc5395996 translate old attenuator propert to new MCI API 2022-02-20 23:16:52 +01:00
rjkm
a5f3b75d0a Merge branch 'internal' 2022-02-16 15:55:04 +01:00
rjkm
69fcf5d649 disable dumps 2022-02-16 15:53:20 +01:00
rjkm
d5d63ea2ef prepare new init for revision 1 FSM but do not use it for now 2022-02-16 15:52:53 +01:00
rjkm
4b69ae5399 cleanup defines, add license commands 2022-02-15 14:43:32 +01:00
rjkm
1cf0526b24 license register is different for revision 1 (MCI) cards 2022-02-15 14:42:37 +01:00
rjkm
73e8b9943e cleanup tables and add license dump 2022-02-15 14:41:25 +01:00
rjkm
4b09ad7e42 forgot to reenable disseqc 2022-02-15 14:40:32 +01:00
rjkm
c39b234fd6 add support for DVBC 2022-02-12 16:40:27 +01:00
rjkm
c2f86b6438 add MCI ioctl to be used through modX devices 2022-02-12 16:39:01 +01:00
rjkm
6a3ef9873d data64 is not definde in kernel version 2022-02-12 16:37:50 +01:00
rjkm
98b466a2d3 remove debug info 2022-02-12 16:37:00 +01:00
rjkm
78d30ff6ff remove unused function 2022-02-12 16:35:57 +01:00
rjkm
d849abd626 move device info output 2022-02-12 15:49:53 +01:00
rjkm
9517d698dc update modulator defines and structs 2022-02-12 15:47:09 +01:00
rjkm
75821a6e3c properly round SCR frequencies 2022-02-12 15:37:49 +01:00
rjkm
2194f8e03a correct ddB 2022-02-12 15:37:04 +01:00
rjkm
d9a846d199 use MCI interface for modulators with revision 1 2022-02-12 15:28:05 +01:00
rjkm
31a781c2e3 remove non-static definition of mci card configs 2022-02-12 15:19:05 +01:00
rjkm
9b458a72de allow compilation against kerne dvb_core if KERNEL_DVB_CORE defined 2022-02-12 15:14:44 +01:00
rjkm
e0fd8a0f35 snr define was deleted by mistake 2022-02-12 15:09:36 +01:00
rjkm
1b49bfb8f1 use dd_compat file and adjust fallthroughs 2022-02-12 15:07:59 +01:00
rjkm
4ce76407e2 add mci irq for fsm cards 2022-02-11 21:37:06 +01:00
rjkm
a6c53f5ece add backwards compatibility include 2022-02-11 16:08:50 +01:00
rjkm
86579d353e add SNR reading for XO2 CI and use correct I2C device 2022-02-07 19:55:31 +01:00
rjkm
63df691561 add type name for second input of dual CI 2022-02-07 19:15:45 +01:00
rjkm
4aa7a68e21 set roll-off to auto or dvb-core will select default
Signed-off-by: rjkm <none>
2022-01-14 20:23:32 +01:00
rjkm
b6d2a37ac2 adapt to latest mainline dvb-core 2022-01-14 20:23:32 +01:00
rjkm
90e6d4806b allow setting CMDREG_SW during init (disabled for now) 2022-01-14 20:23:32 +01:00
rjkm
d995849fdb add comment about IOMMU 2022-01-14 20:23:32 +01:00
rjkm
b5bb500106 move ns.h to ddbridge directory 2022-01-14 20:23:32 +01:00
rjkm
24b7f979c4 process output_start fails (input cannot fail) 2022-01-14 20:23:32 +01:00
rjkm
be19cdb31d define macro for older kernels 2022-01-14 20:23:32 +01:00
rjkm
56afb2acc1 style cleanup 2022-01-14 20:23:32 +01:00
rjkm
08b3218e5a use already resolved link and info 2022-01-14 20:23:32 +01:00
rjkm
e17abdbbb9 return start error 2022-01-14 20:23:32 +01:00
rjkm
811bea8010 show bb header info 2022-01-14 20:23:32 +01:00
drmocm
e89a868ad5 fixed pam and continuity options 2021-12-10 13:56:05 +01:00
rjkm
f02b135bdb Merge branch 'internal' 2021-12-06 15:15:18 +01:00
rjkm
8bda007f05 add MCI registers for FSM 2021-12-06 14:54:51 +01:00
rjkm
ec655e1438 Merge branch 'internal' 2021-09-23 15:07:58 +02:00
rjkm
b606a7b2b2 increase wit time after powerup and before reset to 300ms
Signed-off-by: rjkm <none>
2021-09-23 15:07:00 +02:00
rjkm
81793729e6 Merge branch 'internal' 2021-09-19 19:06:35 +02:00
rjkm
3757c4671e change printfs to debugging messages 2021-09-19 19:05:50 +02:00
rjkm
719ac4d231 remove workqueue and threaded interrupt modes, they are too laggy 2021-09-19 19:05:05 +02:00
root
a3c6b5acc1 use inttypes 2021-09-07 18:08:58 +02:00
rjkm
8986494cd3 Merge branch 'internal' 2021-08-20 14:36:46 +02:00
rjkm
eeb013e0fa always allocate 64 adapters
this is for people who do not want to change the config by hand
it is preferred to use adapter_alloc=3 to have one adapter for
each physical DVB card
2021-08-20 14:29:29 +02:00
rjkm
7f40a54b39 standard is 1 for DVB-S, 0 or 2 otherwise 2021-08-20 14:28:28 +02:00
rjkm
1518ba54a4 hexdump complete BIST info for debugging 2021-08-20 14:27:36 +02:00
rjkm
a97787c3b6 add entries for more frontends (there is overlap but it is only for testing) 2021-08-20 14:26:04 +02:00
rjkm
d676919e72 provide kernel version when calling depmod 2021-08-20 14:24:29 +02:00
rjkm
fbc39f71f4 Merge branch 'internal' 2021-08-09 09:04:33 +02:00
rjkm
19eea5d42d add getiq to get IQ values from MCI cards 2021-08-09 09:03:02 +02:00
rjkm
b23187a049 Add module paramaters for SX8 tuner flags and gain. 2021-08-08 22:14:42 +02:00
rjkm
0165538f13 prepare to get roll off for SDR mode from parameters but use fixed one
for now
2021-08-07 23:00:29 +02:00
rjkm
0b9d3ffa6b move lut for use in other functions 2021-08-07 22:57:40 +02:00
rjkm
61fd25836f report proper frontend number 2021-08-07 22:49:43 +02:00
rjkm
d4aa1c634e style fix 2021-08-07 22:49:03 +02:00
rjkm
5bb0a95b02 remove obsolete debugging line 2021-08-07 22:36:10 +02:00
rjkm
0a5fb7d6b9 add debugging output for actually tuned frequency 2021-08-07 22:35:22 +02:00
rjkm
fd21dbbd5e add more documentation for use of stream number in SDR modes 2021-08-07 22:32:41 +02:00
rjkm
f7fcc1511d add extended stats 2021-08-07 22:30:10 +02:00
rjkm
37ae102d57 use correct u8 type 2021-08-07 22:30:01 +02:00
rjkm
66b1cf3623 new signal loss counter field 2021-08-07 22:29:17 +02:00
rjkm
7f002f1356 add 7/8 to offset 4 2021-08-07 22:28:42 +02:00
rjkm
418bd83b40 only set tuner flags once 2021-07-05 18:42:05 +02:00
108 changed files with 5392 additions and 3210 deletions

8
.gitignore vendored
View File

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

6
Kbuild
View File

@ -2,6 +2,12 @@
# Makefile for the kernel multimedia device drivers. # Makefile for the kernel multimedia device drivers.
# #
ifeq ($(KERNEL_DVB_CORE),y)
obj-y := ddbridge/ \
frontends/
else
obj-y := dvb-core/ \ obj-y := dvb-core/ \
ddbridge/ \ ddbridge/ \
frontends/ frontends/
endif

View File

@ -1,13 +1,18 @@
kernelver ?= $(shell uname -r) kernelver ?= $(shell uname -r)
MDIR ?=
KDIR ?= /lib/modules/$(kernelver)/build KDIR ?= /lib/modules/$(kernelver)/build
PWD := $(shell pwd) 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) KBUILD_EXTMOD = $(PWD)
DDDVB_INC = "-I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux -I$(KBUILD_EXTMOD)/frontends" 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
all: all:
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) $(MODDEFS) modules NOSTDINC_FLAGS=$(DDDVB_INC) $(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) $(MODDEFS) modules NOSTDINC_FLAGS=$(DDDVB_INC)
@ -26,10 +31,11 @@ dep:
DIR=`pwd`; (cd $(TOPDIR); make KBUILD_EXTMOD=$$DIR dep) DIR=`pwd`; (cd $(TOPDIR); make KBUILD_EXTMOD=$$DIR dep)
install: all install: all
$(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) modules_install $(MAKE) -C $(KDIR) KBUILD_EXTMOD=$(PWD) INSTALL_MOD_PATH=$(MDIR) modules_install
depmod -a depmod $(kernelver)
clean: clean:
rm -rf */.*.o.d */*.o */*.ko */*.mod.c */.*.cmd .tmp_versions Module* modules* 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 # DDBridge Driver
Device driver for all Digital Devices DVB demodulator and modulator cards.
### Patches ### Patches
We can only accept patches which don't break compilation for older kernels (as far back as 2.6.37). 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: For installation instructions see:
http://support.digital-devices.eu/index.php?article=152 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 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 cit: cit.c
$(CC) -o cit cit.c -lpthread $(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 %: %.c
$(CC) $(CFLAGS) -I../ddbridge -I../include/ $< -o $@ $(CC) $(CFLAGS) -I../ddbridge -I../include/ $< -o $@
%.o: %.c %.o: %.c
$(CC) $(CFLAGS) -I../ddbridge -o $@ $< $(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 <sys/ioctl.h>
#include <pthread.h> #include <pthread.h>
#include <getopt.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, uint8_t fill[188]={0x47, 0x1f, 0xff, 0x10,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 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]; c=(buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7];
if (c!=*d) { if (c!=*d) {
printf("CONT ERROR: got %08x expected %08x\n", c, *d); printf("CONT ERROR: got %08x expected %08x\n", c, *d);
//if (!*d && (c+100) > 100)
// return;
*d=c; *d=c;
} else { } else {
if (memcmp(ts+8, buf+8, 180)) 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) int main(int argc, char **argv)
{ {
pthread_t th; pthread_t th;
@ -181,11 +212,12 @@ int main(int argc, char **argv)
{"device", required_argument, 0, 'd'}, {"device", required_argument, 0, 'd'},
{"snum", required_argument, 0, 's'}, {"snum", required_argument, 0, 's'},
{"rnum", required_argument, 0, 'r'}, {"rnum", required_argument, 0, 'r'},
{"reset", no_argument, 0, 'R'},
{"help", no_argument , 0, 'h'}, {"help", no_argument , 0, 'h'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, c = getopt_long(argc, argv,
"a:d:h", "a:d:hs:R",
long_options, &option_index); long_options, &option_index);
if (c==-1) if (c==-1)
break; break;
@ -203,6 +235,9 @@ int main(int argc, char **argv)
case 'r': case 'r':
rnum = strtoul(optarg, NULL, 10); rnum = strtoul(optarg, NULL, 10);
break; break;
case 'R':
do_reset = 1;
break;
case 'h': case 'h':
printf("cit -a<adapter> -d<device>\n"); printf("cit -a<adapter> -d<device>\n");
exit(-1); exit(-1);
@ -214,6 +249,11 @@ int main(int argc, char **argv)
if (optind < argc) { if (optind < argc) {
printf("Warning: unused arguments\n"); printf("Warning: unused arguments\n");
} }
if (do_reset) {
reset();
exit(0);
}
printf("adapter %d, device: %d\n", adapter, device); printf("adapter %d, device: %d\n", adapter, device);
memset(ts+8, 180, 0x5a); memset(ts+8, 180, 0x5a);
pthread_create(&th, NULL, get_ts, NULL); 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,6 +30,30 @@ char *Rolloff[8] = {
"rsvd", "rsvd",
}; };
void dump(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");
}
}
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) void print_temp(struct mci_result *res)
{ {
printf("Die temperature = %u\n", res->sx8_bist.temperature); printf("Die temperature = %u\n", res->sx8_bist.temperature);
@ -55,6 +79,9 @@ int temp_info(int dev, uint32_t link)
} }
print_temp(&msg.res); print_temp(&msg.res);
printf("BIST info dump: ");
dump((uint8_t *) &msg.res, 16);
return ret; return ret;
} }
@ -221,7 +248,31 @@ char* PunctureRates[32] = {
/* 0x07 */ "rsvd 7.0", /* 0x07 */ "rsvd 7.0",
}; };
void print_info(struct mci_result *res, uint8_t demod) int mci_bb(int dev, uint32_t link, uint8_t demod)
{
struct ddb_mci_msg msg = {
.link = link,
.cmd.command = MCI_CMD_GET_BBHEADER,
.cmd.demod = demod,
.cmd.get_bb_header.select = 0,
};
struct mci_result *res = &msg.res;
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
if (res->bb_header.valid) {
printf("MATYPE1: %02x\n", res->bb_header.matype_1);
printf("MATYPE2: %02x\n", res->bb_header.matype_2);
}
return ret;
}
void print_info(int dev, uint32_t link, uint8_t demod, struct mci_result *res)
{ {
if (res->status == MCI_DEMOD_STOPPED) { if (res->status == MCI_DEMOD_STOPPED) {
printf("\nDemod %u: stopped\n", demod); printf("\nDemod %u: stopped\n", demod);
@ -231,8 +282,9 @@ void print_info(struct mci_result *res, uint8_t demod)
printf("\nDemod %u:\n", demod); printf("\nDemod %u:\n", demod);
if (res->status == MCI_DEMOD_LOCKED) { if (res->status == MCI_DEMOD_LOCKED) {
switch (res->mode) { switch (res->mode) {
case M4_MODE_DVBSX: case 0:
if (res->dvbs2_signal_info.standard == 2) { case MX_MODE_DVBSX:
if (res->dvbs2_signal_info.standard != 1) {
int short_frame = 0, pilots = 0; int short_frame = 0, pilots = 0;
char *modcod = "unknown"; char *modcod = "unknown";
uint8_t pls = res->dvbs2_signal_info.pls_code; uint8_t pls = res->dvbs2_signal_info.pls_code;
@ -254,19 +306,22 @@ void print_info(struct mci_result *res, uint8_t demod)
short_frame = pls & 2; short_frame = pls & 2;
modcod = S2ModCods[pls / 4]; 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("Roll-Off: %s\n", Rolloff[res->dvbs2_signal_info.roll_off & 7]);
printf("Pilots: %s\n", pilots ? "On" : "Off"); printf("Pilots: %s\n", pilots ? "On" : "Off");
printf("Frame: %s\n", short_frame ? "Short" : "Long"); printf("Frame: %s\n", short_frame ? "Short" : "Normal");
} else { } else {
printf("Demod Locked: DVB-S\n"); printf("Demod Locked: DVB-S\n");
printf("PR: %s\n", printf("PR: %s\n",
PunctureRates[res->dvbs2_signal_info.pls_code & 0x07]); PunctureRates[res->dvbs2_signal_info.pls_code & 0x07]);
} }
printf("Inversion: %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off"); printf("Inversion: %s\n", (res->dvbs2_signal_info.roll_off & 0x80) ? "on": "off");
case M4_MODE_DVBT: break;
case MX_MODE_DVBT:
printf("Locked DVB-T\n"); printf("Locked DVB-T\n");
break; break;
case M4_MODE_DVBT2: case MX_MODE_DVBT2:
printf("Locked DVB-T2\n"); printf("Locked DVB-T2\n");
break; break;
} }
@ -298,17 +353,18 @@ int readreg(int dev, uint32_t reg, uint32_t link, uint32_t *val)
return 0; return 0;
} }
void mci_firmware(int dev, uint32_t link) void mci_firmware(int dev, uint32_t link, uint32_t base)
{ {
union { union {
uint32_t u[4]; uint32_t u[4];
char s[16]; char s[16];
} version; } version;
readreg(dev, MIC_INTERFACE_VER , link, &version.u[0]); base += 0xf0;
readreg(dev, MIC_INTERFACE_VER + 4, link, &version.u[1]); readreg(dev, base , link, &version.u[0]);
readreg(dev, MIC_INTERFACE_VER + 8, link, &version.u[2]); readreg(dev, base + 4, link, &version.u[1]);
readreg(dev, MIC_INTERFACE_VER + 12, link, &version.u[3]); 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]); printf("MCI firmware: %s.%d\n", &version.s, version.s[15]);
} }
@ -322,7 +378,6 @@ int mci_info(int dev, uint32_t link, uint8_t demod)
.cmd.demod = demod .cmd.demod = demod
}; };
int ret; int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) { if (ret < 0) {
@ -330,7 +385,36 @@ int mci_info(int dev, uint32_t link, uint8_t demod)
return ret; return ret;
} }
print_info(&msg.res, demod); print_info(dev, link, demod, &msg.res);
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; return ret;
} }
@ -370,6 +454,8 @@ static int get_id(int fd, int link, struct ddb_id *id)
static char *id2name(uint16_t id) static char *id2name(uint16_t id)
{ {
switch (id) { switch (id) {
case 0x210:
return "FSM";
case 0x222: case 0x222:
return "MOD"; return "MOD";
case 0x0009: case 0x0009:
@ -378,6 +464,8 @@ static char *id2name(uint16_t id)
return "MAX SX8 Basic"; return "MAX SX8 Basic";
case 0x000a: case 0x000a:
return "MAX M4"; return "MAX M4";
case 0x0014:
return "MAX CI M2";
default: default:
return " "; return " ";
} }
@ -387,7 +475,7 @@ static int card_info(int ddbnum, int demod)
{ {
char ddbname[80]; char ddbname[80];
struct ddb_id ddbid; struct ddb_id ddbid;
int ddb, ret, link, links = 1, i; int ddb, ret, link, links = 1, i, num=8;
struct ddb_id id; struct ddb_id id;
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum); sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
@ -420,24 +508,30 @@ static int card_info(int ddbnum, int demod)
id.hw, id.regmap, (id.hw & 0xff0000) >> 16, (id.hw & 0xffff)); id.hw, id.regmap, (id.hw & 0xff0000) >> 16, (id.hw & 0xffff));
switch (id.device) { switch (id.device) {
case 0x0009: case 0x0009:
mci_firmware(ddb, link); case 0x000b:
if (demod >= 0)
mci_info(ddb, link, demod);
else {
for (i = 0; i < 8; i++)
mci_info(ddb, link, i);
}
temp_info(ddb, link); temp_info(ddb, link);
break;
case 0x000a: 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) if (demod >= 0)
mci_info(ddb, link, demod); mci_info(ddb, link, demod);
else { else {
for (i = 0; i < 4; i++) for (i = 0; i < num; i++)
mci_info(ddb, link, i); mci_info(ddb, link, i);
} }
break; 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: default:
break; 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,289 +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:
err = FlashWritePageMode(ddb,FlashOffset,buffer,BufferSize,0x1C);
break;
}
if (err < 0)
printf("Programming Error\n");
else
printf("Programming Done\n");
free(buffer);
return 0;
}

100
apps/getiq.c Normal file
View File

@ -0,0 +1,100 @@
#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>
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"
void print_iq(struct mci_result *res, int fd)
{
dprintf(fd, "%d,%d\n", res->iq_symbol.i, res->iq_symbol.q);
}
int get_iq(int dev, uint32_t link, uint8_t demod, int fd)
{
struct ddb_mci_msg msg = {
.link = link,
.cmd.command = MCI_CMD_GET_IQSYMBOL,
.cmd.demod = demod,
.cmd.get_iq_symbol.tap = 0,
.cmd.get_iq_symbol.point = 0,
};
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
if (msg.res.status & 0x80) {
printf("MCI errror %02x\n", msg.res.status);
return ret;
}
print_iq(&msg.res, fd);
return ret;
}
#define SIZE_OF_ARRAY(a) (sizeof(a)/sizeof(a[0]))
int main(int argc, char*argv[])
{
char ddbname[80];
int fd = -1, all = 1, i, ret = 0, ddb;
char fn[128];
int32_t device = -1, demod = -1;
while (1) {
int cur_optind = optind ? optind : 1;
int option_index = 0;
int c;
static struct option long_options[] = {
{"device", required_argument, 0, 'd'},
{"demod", required_argument, 0, 'n'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "ad:n:",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'd':
device = strtoul(optarg, NULL, 0);
break;
case 'n':
demod = strtoul(optarg, NULL, 0);
break;
case 'a':
all = 1;
break;
default:
break;
}
}
if (optind < argc) {
printf("too many arguments\n");
exit(1);
}
sprintf(ddbname, "/dev/ddbridge/card%d", device);
ddb = open(ddbname, O_RDWR);
if (ddb < 0)
return -3;
for (i = 0; i < 20000; i++)
get_iq(ddb, 0, demod, 1);
}

View File

@ -24,12 +24,31 @@ struct mconf {
int set_output; int set_output;
int set_channels; int set_channels;
int fd; int fd;
int chanset;
struct mci_command channels; struct mci_command channels;
struct mci_command stream; struct mci_command stream;
struct mci_command output; 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) void strim(char *s)
{ {
int l = strlen(s); int l = strlen(s);
@ -39,13 +58,15 @@ void strim(char *s)
s[l] = 0; 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; char line[256], csec[80], par[80], val[80], *p;
FILE *f; FILE *f;
if ((f = fopen(fname, "r")) == NULL) if ((f = fopen(fname, "r")) == NULL) {
return; dprintf(2, "Could not open %s\n", fname);
return -1;
}
while ((p = fgets(line, sizeof(line), f))) { while ((p = fgets(line, sizeof(line), f))) {
if (*p == '\r' || *p == '\n' || *p == '#') if (*p == '\r' || *p == '\n' || *p == '#')
continue; continue;
@ -75,6 +96,7 @@ void parse(char *fname, char *sec, void *priv, void (*cb)(void *, char *, char *
if (!strcmp(sec, csec) && cb) if (!strcmp(sec, csec) && cb)
cb(priv, NULL, NULL); cb(priv, NULL, NULL);
fclose(f); fclose(f);
return 0;
} }
struct param_table_entry { struct param_table_entry {
@ -83,89 +105,169 @@ struct param_table_entry {
}; };
struct param_table_entry mod_standard_table[] = { struct param_table_entry mod_standard_table[] = {
{ .name = "GENERIC", .value = MOD_STANDARD_GENERIC },
{ .name = "DVBT_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "DVBT2_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT2_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT2_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT2_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "0", .value = MOD_STANDARD_GENERIC }, { .name = "0", .value = MOD_STANDARD_GENERIC },
{ .name = "GENERIC", .value = MOD_STANDARD_GENERIC },
{ .name = "1", .value = MOD_STANDARD_DVBT_8 }, { .name = "1", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "DVBT2_8", .value = MOD_STANDARD_DVBT_8 },
{ .name = "2", .value = MOD_STANDARD_DVBT_7 }, { .name = "2", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "DVBT2_7", .value = MOD_STANDARD_DVBT_7 },
{ .name = "3", .value = MOD_STANDARD_DVBT_6 }, { .name = "3", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "DVBT2_6", .value = MOD_STANDARD_DVBT_6 },
{ .name = "4", .value = MOD_STANDARD_DVBT_5 }, { .name = "4", .value = MOD_STANDARD_DVBT_5 },
{ .name = "DVBT_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "DVBT2_5", .value = MOD_STANDARD_DVBT_5 },
{ .name = "8", .value = MOD_STANDARD_DVBC_8 },
{ .name = "DVBC_8", .value = MOD_STANDARD_DVBC_8 },
{ .name = "9", .value = MOD_STANDARD_DVBC_7 },
{ .name = "DVBC_7", .value = MOD_STANDARD_DVBC_7 },
{ .name = "10", .value = MOD_STANDARD_DVBC_6 },
{ .name = "DVBC_6", .value = MOD_STANDARD_DVBC_6 },
{ .name = "11", .value = MOD_STANDARD_J83B_QAM64 },
{ .name = "J83B_QAM64", .value = MOD_STANDARD_J83B_QAM64 },
{ .name = "12", .value = MOD_STANDARD_J83B_QAM256 },
{ .name = "J83B_QAM256", .value = MOD_STANDARD_J83B_QAM256 },
{ .name = "13", .value = MOD_STANDARD_ISDBC_QAM64 },
{ .name = "ISDBC_QAM64", .value = MOD_STANDARD_ISDBC_QAM64 },
{ .name = "J83C_QAM64", .value = MOD_STANDARD_ISDBC_QAM64 },
{ .name = "14", .value = MOD_STANDARD_ISDBC_QAM256 },
{ .name = "ISDBC_QAM256", .value = MOD_STANDARD_ISDBC_QAM256 },
{ .name = "J83C_QAM256", .value = MOD_STANDARD_ISDBC_QAM256 },
{ .name = NULL, .value = 0 } { .name = NULL, .value = 0 }
}; };
struct param_table_entry stream_format_table[] = { struct param_table_entry stream_format_table[] = {
{ .name = "default", .value = MOD_FORMAT_DEFAULT },
{ .name = "IQ16", .value = MOD_FORMAT_IQ16 },
{ .name = "IQ8", .value = MOD_FORMAT_IQ8 },
{ .name = "IDX8", .value = MOD_FORMAT_IDX8 },
{ .name = "TS", .value = MOD_FORMAT_TS },
{ .name = "0", .value = MOD_FORMAT_DEFAULT }, { .name = "0", .value = MOD_FORMAT_DEFAULT },
{ .name = "default", .value = MOD_FORMAT_DEFAULT },
{ .name = "1", .value = MOD_FORMAT_IQ16 }, { .name = "1", .value = MOD_FORMAT_IQ16 },
{ .name = "IQ16", .value = MOD_FORMAT_IQ16 },
{ .name = "2", .value = MOD_FORMAT_IQ8 }, { .name = "2", .value = MOD_FORMAT_IQ8 },
{ .name = "IQ8", .value = MOD_FORMAT_IQ8 },
{ .name = "3", .value = MOD_FORMAT_IDX8 }, { .name = "3", .value = MOD_FORMAT_IDX8 },
{ .name = "IDX8", .value = MOD_FORMAT_IDX8 },
{ .name = "4", .value = MOD_FORMAT_TS }, { .name = "4", .value = MOD_FORMAT_TS },
{ .name = "TS", .value = MOD_FORMAT_TS },
{ .name = NULL, .value = 0 } { .name = NULL, .value = 0 }
}; };
struct param_table_entry guard_interval_table[] = { struct param_table_entry guard_interval_table[] = {
{ .name = "1/32", .value = MOD_DVBT_GI_1_32 },
{ .name = "1/16", .value = MOD_DVBT_GI_1_16 },
{ .name = "1/8", .value = MOD_DVBT_GI_1_8 },
{ .name = "1/4", .value = MOD_DVBT_GI_1_4 },
{ .name = "0", .value = MOD_DVBT_GI_1_32 }, { .name = "0", .value = MOD_DVBT_GI_1_32 },
{ .name = "1/32", .value = MOD_DVBT_GI_1_32 },
{ .name = "1", .value = MOD_DVBT_GI_1_16 }, { .name = "1", .value = MOD_DVBT_GI_1_16 },
{ .name = "1/16", .value = MOD_DVBT_GI_1_16 },
{ .name = "2", .value = MOD_DVBT_GI_1_8 }, { .name = "2", .value = MOD_DVBT_GI_1_8 },
{ .name = "1/8", .value = MOD_DVBT_GI_1_8 },
{ .name = "3", .value = MOD_DVBT_GI_1_4 }, { .name = "3", .value = MOD_DVBT_GI_1_4 },
{ .name = "1/4", .value = MOD_DVBT_GI_1_4 },
{ .name = NULL, .value = 0 } { .name = NULL, .value = 0 }
}; };
struct param_table_entry puncture_rate_table[] = { struct param_table_entry puncture_rate_table[] = {
{ .name = "1/2", .value = MOD_DVBT_PR_1_2 },
{ .name = "2/3", .value = MOD_DVBT_PR_2_3 },
{ .name = "3/4", .value = MOD_DVBT_PR_3_4 },
{ .name = "5/6", .value = MOD_DVBT_PR_5_6 },
{ .name = "7/8", .value = MOD_DVBT_PR_7_8 },
{ .name = "1", .value = MOD_DVBT_PR_1_2 }, { .name = "1", .value = MOD_DVBT_PR_1_2 },
{ .name = "1/2", .value = MOD_DVBT_PR_1_2 },
{ .name = "2", .value = MOD_DVBT_PR_2_3 }, { .name = "2", .value = MOD_DVBT_PR_2_3 },
{ .name = "2/3", .value = MOD_DVBT_PR_2_3 },
{ .name = "3", .value = MOD_DVBT_PR_3_4 }, { .name = "3", .value = MOD_DVBT_PR_3_4 },
{ .name = "3/4", .value = MOD_DVBT_PR_3_4 },
{ .name = "5", .value = MOD_DVBT_PR_5_6 }, { .name = "5", .value = MOD_DVBT_PR_5_6 },
{ .name = "5/6", .value = MOD_DVBT_PR_5_6 },
{ .name = "7", .value = MOD_DVBT_PR_7_8 }, { .name = "7", .value = MOD_DVBT_PR_7_8 },
{ .name = "7/8", .value = MOD_DVBT_PR_7_8 },
{ .name = NULL, .value = 0 } { .name = NULL, .value = 0 }
}; };
struct param_table_entry dvbt_constellation_table[] = { struct param_table_entry dvbt_constellation_table[] = {
{ .name = "0", .value = MOD_DVBT_QPSK }, { .name = "0", .value = MOD_DVBT_QPSK },
{ .name = "qpsk", .value = MOD_DVBT_QPSK }, { .name = "qpsk", .value = MOD_DVBT_QPSK },
{ .name = "1", .value = MOD_DVBT_16QAM }, { .name = "1", .value = MOD_DVBT_16QAM },
{ .name = "16qam", .value = MOD_DVBT_16QAM }, { .name = "16qam", .value = MOD_DVBT_16QAM },
{ .name = "qam16", .value = MOD_DVBT_16QAM }, { .name = "qam16", .value = MOD_DVBT_16QAM },
{ .name = "2", .value = MOD_DVBT_64QAM }, { .name = "2", .value = MOD_DVBT_64QAM },
{ .name = "64qam", .value = MOD_DVBT_64QAM }, { .name = "64qam", .value = MOD_DVBT_64QAM },
{ .name = "qam64", .value = MOD_DVBT_64QAM }, { .name = "qam64", .value = MOD_DVBT_64QAM },
{ .name = NULL, .value = 0 } { .name = NULL, .value = 0 }
}; };
int parse_param(char *val,struct param_table_entry *table, int *value) { struct param_table_entry qam_modulation_table[] = {
{ .name = "0", .value = MOD_QAM_DVBC_16 },
{ .name = "qam_dvbc_16", .value = MOD_QAM_DVBC_16 },
{ .name = "1", .value = MOD_QAM_DVBC_32 },
{ .name = "qam_dvbc_32", .value = MOD_QAM_DVBC_32 },
{ .name = "2", .value = MOD_QAM_DVBC_64 },
{ .name = "qam_dvbc_64", .value = MOD_QAM_DVBC_64 },
{ .name = "3", .value = MOD_QAM_DVBC_128 },
{ .name = "qam_dvbc_128", .value = MOD_QAM_DVBC_128 },
{ .name = "4", .value = MOD_QAM_DVBC_256 },
{ .name = "qam_dvbc_256", .value = MOD_QAM_DVBC_256 },
{ .name = "5", .value = MOD_QAM_J83B_64 },
{ .name = "qam_j83b_64", .value = MOD_QAM_J83B_64 },
{ .name = "6", .value = MOD_QAM_DVBC_256 },
{ .name = "qam_j83b_256", .value = MOD_QAM_J83B_256 },
{ .name = "7", .value = MOD_QAM_GENERIC },
{ .name = "qam_generic", .value = MOD_QAM_GENERIC },
{ .name = "8", .value = MOD_QAM_ISDBC_64 },
{ .name = "qam_isdbc_64", .value = MOD_QAM_ISDBC_64 },
{ .name = "9", .value = MOD_QAM_ISDBC_256 },
{ .name = "qam_isdbc_256", .value = MOD_QAM_ISDBC_256 },
{ .name = NULL, .value = 0 }
};
int parse_param(char *val, struct param_table_entry *table, int *value) {
if (value) { if (value) {
*value = 0; *value = 0;
if (table) { if (table) {
while (table->name) { while (table->name) {
if( !strcasecmp(val,table->name)) { if( !strcasecmp(val,table->name)) {
*value = table->value; *value = table->value;
printf("%s=%u\n", val, *value);
return 0; return 0;
} }
table++; table++;
} }
} }
} }
printf("unknown value %s\n", val);
return -1; return -1;
} }
@ -175,11 +277,13 @@ int mci_cmd(int dev, struct mci_command *cmd)
struct ddb_mci_msg msg; struct ddb_mci_msg msg;
uint8_t status; uint8_t status;
memset(&msg, 0, sizeof(msg));
msg.link = 0; msg.link = 0;
memcpy(&msg.cmd, cmd, sizeof(msg.cmd)); memcpy(&msg.cmd, cmd, sizeof(msg.cmd));
dump((uint8_t *) &msg.cmd, sizeof(msg.cmd));
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) { if (ret < 0) {
dprintf(2, "mci_cmd error %d\n", errno); dprintf(2, "mci_cmd error %d (%s)\n", errno, strerror(errno));
return ret; return ret;
} }
status = msg.res.status; status = msg.res.status;
@ -201,7 +305,7 @@ struct mci_command msg_channels = {
.mod_channel = 0, .mod_channel = 0,
.mod_stream = 0, .mod_stream = 0,
.mod_setup_channels[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, .standard = MOD_STANDARD_DVBT_8,
.num_channels = 25, .num_channels = 25,
.frequency = 474000000, .frequency = 474000000,
@ -210,12 +314,10 @@ struct mci_command msg_channels = {
struct mci_command msg_stream = { struct mci_command msg_stream = {
.mod_command = MOD_SETUP_STREAM, .mod_command = MOD_SETUP_STREAM,
.mod_channel = 1, .mod_channel = 0,
.mod_stream = 0, .mod_stream = 0,
.mod_setup_stream = { .mod_setup_stream = {
.standard = MOD_STANDARD_DVBT_8, .standard = MOD_STANDARD_DVBC_8,
.fft_size = 1,
.guard_interval = 0,
}, },
}; };
@ -252,7 +354,7 @@ void output_cb(void *priv, char *par, char *val)
mc->output.mod_setup_output.channel_power = (int16_t) (strtod(val, NULL) * 100.0); mc->output.mod_setup_output.channel_power = (int16_t) (strtod(val, NULL) * 100.0);
} else if (!strcasecmp(par, "channels")) { } else if (!strcasecmp(par, "channels")) {
mc->output.mod_setup_output.num_channels = strtol(val, NULL, 10); mc->output.mod_setup_output.num_channels = strtol(val, NULL, 10);
}else if (!strcasecmp(par, "unit")) { } else if (!strcasecmp(par, "unit")) {
if (!strcasecmp(val, "DBUV")) { if (!strcasecmp(val, "DBUV")) {
mc->output.mod_setup_output.unit = MOD_UNIT_DBUV; mc->output.mod_setup_output.unit = MOD_UNIT_DBUV;
} else if (!strcasecmp(val, "DBM")) { } else if (!strcasecmp(val, "DBM")) {
@ -273,21 +375,29 @@ void channels_cb(void *priv, char *par, char *val)
return; return;
} }
if (!strcasecmp(par, "frequency")) { if (!strcasecmp(par, "frequency")) {
mc->channels.mod_setup_channels[0].frequency = (uint32_t) (strtod(val, NULL) * 1000000.0); mc->chanset++;
printf("frequency = %u\n", mc->channels.mod_setup_channels[0].frequency); if (mc->chanset > 3)
} else if (!strcasecmp(par, "channels")) { return;
mc->channels.mod_setup_channels[0].num_channels = strtol(val, NULL, 10); 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")) { } else if (!strcasecmp(par, "standard")) {
if (!parse_param(val,mod_standard_table,&value)) if (!parse_param(val,mod_standard_table, &value))
mc->stream.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")) { } 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")) { } else if (!strcasecmp(par, "bandwidth")) {
mc->channels.mod_setup_channels[0].bandwidth = (uint32_t) (strtod(val, NULL) * 1000000.0); mc->channels.mod_setup_channels[mc->chanset].bandwidth = (uint32_t) (strtod(val, NULL) * 1000000.0);
mc->channels.mod_setup_channels[0].offset = mc->channels.mod_setup_channels[mc->chanset].offset =
mc->channels.mod_setup_channels[0].bandwidth / 2; mc->channels.mod_setup_channels[mc->chanset].bandwidth / 2;
} else } else
printf("invalid channels parameter: %s\n", par); printf("invalid channels parameter: %s\n", par);
}
} }
void streams_cb(void *priv, char *par, char *val) void streams_cb(void *priv, char *par, char *val)
@ -299,18 +409,23 @@ void streams_cb(void *priv, char *par, char *val)
return; return;
} }
if (!strcasecmp(par, "fft_size")) { if (!strcasecmp(par, "fft_size")) {
mc->stream.mod_setup_stream.fft_size = strtol(val, NULL, 10); mc->stream.mod_setup_stream.ofdm.fft_size = strtol(val, NULL, 10);
} else if (!strcasecmp(par, "guard_interval")) { } else if (!strcasecmp(par, "guard_interval")) {
if (!parse_param(val,guard_interval_table,&value)) if (!parse_param(val, guard_interval_table, &value))
mc->stream.mod_setup_stream.guard_interval = value; mc->stream.mod_setup_stream.ofdm.guard_interval = value;
} else if (!strcasecmp(par, "puncture_rate")) { } else if (!strcasecmp(par, "puncture_rate")) {
if (!parse_param(val,puncture_rate_table,&value)) if (!parse_param(val, puncture_rate_table, &value))
mc->stream.mod_setup_stream.puncture_rate = value; mc->stream.mod_setup_stream.ofdm.puncture_rate = value;
} else if (!strcasecmp(par, "constellation")) { } else if (!strcasecmp(par, "constellation")) {
if (!parse_param(val,dvbt_constellation_table,&value)) if (!parse_param(val,dvbt_constellation_table,&value))
mc->stream.mod_setup_stream.constellation = value; mc->stream.mod_setup_stream.ofdm.constellation = value;
} else if (!strcasecmp(par, "cell_identifier")) { } else if (!strcasecmp(par, "cell_identifier")) {
mc->stream.mod_setup_stream.cell_identifier = strtol(val, NULL, 0); mc->stream.mod_setup_stream.ofdm.cell_identifier = strtol(val, NULL, 0);
} else if (!strcasecmp(par, "modulation")) {
if (!parse_param(val, qam_modulation_table, &value))
mc->stream.mod_setup_stream.qam.modulation = value;
} else if (!strcasecmp(par, "rolloff")) {
mc->stream.mod_setup_stream.qam.rolloff = strtol(val, NULL, 0);
} else if (!strcasecmp(par, "standard")) { } else if (!strcasecmp(par, "standard")) {
if (!parse_param(val,mod_standard_table,&value)) if (!parse_param(val,mod_standard_table,&value))
mc->stream.mod_setup_stream.standard = value; mc->stream.mod_setup_stream.standard = value;
@ -324,17 +439,48 @@ void streams_cb(void *priv, char *par, char *val)
} else if (!strcasecmp(par, "stream")) { } else if (!strcasecmp(par, "stream")) {
mc->stream.mod_stream = strtol(val, NULL, 10); 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("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); mci_cmd(mc->fd, &mc->stream);
} else } else
printf("invalid streams parameter: %s = %s\n", par, val); printf("invalid streams parameter: %s = %s\n", par, val);
} }
int mci_lic(int dev)
{
struct ddb_mci_msg msg = {
.cmd.command = CMD_EXPORT_LICENSE,
.cmd.get_bb_header.select = 0,
};
struct mci_result *res = &msg.res;
int ret;
int i;
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
if (ret < 0) {
printf("Error: %d %d\n", ret, errno);
return ret;
}
if (res->bb_header.valid) {
printf("MATYPE1: %02x\n", res->bb_header.matype_1);
printf("MATYPE2: %02x\n", res->bb_header.matype_2);
}
//dump((const uint8_t *)&res->license, sizeof(res->license));
return ret;
}
int main(int argc, char*argv[]) int main(int argc, char*argv[])
{ {
int fd = -1; int fd = -1;
char fn[128]; char fn[128];
uint32_t device = 0; uint32_t device = 0;
uint32_t frequency = 0;
char *configname = "modulator.conf"; char *configname = "modulator.conf";
struct mconf mc; struct mconf mc;
@ -342,6 +488,7 @@ int main(int argc, char*argv[])
mc.channels = msg_channels; mc.channels = msg_channels;
mc.stream = msg_stream; mc.stream = msg_stream;
mc.output = msg_output; mc.output = msg_output;
mc.chanset = -1;
while (1) { while (1) {
int cur_optind = optind ? optind : 1; int cur_optind = optind ? optind : 1;
@ -375,18 +522,29 @@ int main(int argc, char*argv[])
printf("too many arguments\n"); printf("too many arguments\n");
exit(1); exit(1);
} }
snprintf(fn, 127, "/dev/ddbridge/card%u", device); //snprintf(fn, 127, "/dev/ddbridge/card%u", device);
snprintf(fn, 127, "/dev/dvb/adapter%u/mod0", device);
fd = open(fn, O_RDWR); fd = open(fn, O_RDWR);
if (fd < 0) { if (fd < 0) {
dprintf(2, "Could not open %s\n", fn); dprintf(2, "Could not open %s\n", fn);
return -1; return -1;
} }
//mci_lic(fd);
mc.fd = fd; mc.fd = fd;
parse(configname, "channels", (void *) &mc, channels_cb); if (parse(configname, "channels", (void *) &mc, channels_cb))
if (mc.set_channels) exit(-1);
if (mc.set_channels) {
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); mci_cmd(fd, &mc.channels);
}
parse(configname, "streams", (void *) &mc, streams_cb); parse(configname, "streams", (void *) &mc, streams_cb);
parse(configname, "output", (void *) &mc, output_cb); parse(configname, "output", (void *) &mc, output_cb);
if (mc.set_output) if (mc.set_output) {
printf("setting output.\n");
mci_cmd(fd, &mc.output); mci_cmd(fd, &mc.output);
}
} }

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

View File

@ -405,6 +405,9 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags)
case SPANSION_S25FL132K: SectorSize = 4096; FlashSize = 0x400000; break; case SPANSION_S25FL132K: SectorSize = 4096; FlashSize = 0x400000; break;
case SPANSION_S25FL164K: SectorSize = 4096; FlashSize = 0x800000; break; case SPANSION_S25FL164K: SectorSize = 4096; FlashSize = 0x800000; break;
case WINBOND_W25Q16JV: SectorSize = 4096; FlashSize = 0x200000; break; case WINBOND_W25Q16JV: SectorSize = 4096; FlashSize = 0x200000; break;
case WINBOND_W25Q32JV: SectorSize = 4096; FlashSize = 0x400000; break;
case WINBOND_W25Q64JV: SectorSize = 4096; FlashSize = 0x800000; break;
case WINBOND_W25Q128JV: SectorSize = 4096; FlashSize = 0x1000000; break;
} }
if (SectorSize == 0) if (SectorSize == 0)
return 0; return 0;
@ -575,6 +578,9 @@ int FlashProg(int dev,int argc, char* argv[],uint32_t Flags)
case SPANSION_S25FL132K: case SPANSION_S25FL132K:
case SPANSION_S25FL164K: case SPANSION_S25FL164K:
case WINBOND_W25Q16JV: case WINBOND_W25Q16JV:
case WINBOND_W25Q32JV:
case WINBOND_W25Q64JV:
case WINBOND_W25Q128JV:
err = FlashWritePageMode(dev,FlashOffset,Buffer,BufferSize,0x1C); break; err = FlashWritePageMode(dev,FlashOffset,Buffer,BufferSize,0x1C); break;
} }
@ -1331,6 +1337,9 @@ int read_id(int dev, int argc, char* argv[], uint32_t Flags)
switch(Flash) { switch(Flash) {
case WINBOND_W25Q16JV: case WINBOND_W25Q16JV:
case WINBOND_W25Q32JV:
case WINBOND_W25Q64JV:
case WINBOND_W25Q128JV:
read_winbd(dev, Id); read_winbd(dev, Id);
len = 8; len = 8;
break; break;
@ -1353,7 +1362,7 @@ int read_id(int dev, int argc, char* argv[], uint32_t Flags)
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
printf("%02x ", Id[i]); printf("%02x ", Id[i]);
printf("\n"); printf("\n");
return 0;
} }
int i2cread(int dev, int argc, char* argv[], uint32_t Flags) 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; char *fname, *default_fname;
int res, stat = 0; int res, stat = 0;
char *name = 0, *dname; char *name = 0, *dname;
uint32_t imgadr = 0x10000;
switch (ddf->id.device) { switch (ddf->id.device) {
case 0x300: case 0x300:
@ -109,6 +110,14 @@ static int update_flash(struct ddflash *ddf)
return stat; return stat;
break; break;
default: 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; fname = ddf->fname;
default_fname = devid2fname(ddf->id.device, &name); default_fname = devid2fname(ddf->id.device, &name);
if (!fname) if (!fname)
@ -119,7 +128,8 @@ static int update_flash(struct ddflash *ddf)
printf("Flash: %s\n", ddf->flash_name); printf("Flash: %s\n", ddf->flash_name);
printf("Version: %08x\n", ddf->id.hw); printf("Version: %08x\n", ddf->id.hw);
printf("REGMAP : %08x\n", ddf->id.regmap); 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; stat |= 1;
return stat; 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 #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; int i, j;
uint8_t buf[32]; uint8_t buf[32];
@ -630,13 +630,14 @@ int flashwrite_pagemode(struct ddflash *ddf, int dev, uint32_t FlashOffset,
uint8_t cmd[260]; uint8_t cmd[260];
int i, j; int i, j;
uint32_t flen, blen; uint32_t flen, blen;
int blockerase = be && ((FlashOffset & 0xFFFF) == 0 ) && (flen >= 0x10000); int blockerase;
blen = flen = lseek(dev, 0, SEEK_END) - fw_off; blen = flen = lseek(dev, 0, SEEK_END) - fw_off;
if (blen % 0xff) if (blen % 0xff)
blen = (blen + 0xff) & 0xffffff00; blen = (blen + 0xff) & 0xffffff00;
//printf("blen = %u, flen = %u\n", blen, flen); //printf("blen = %u, flen = %u\n", blen, flen);
setbuf(stdout, NULL); setbuf(stdout, NULL);
blockerase = be && ((FlashOffset & 0xFFFF) == 0 ) && (flen >= 0x10000);
cmd[0] = 0x50; // EWSR cmd[0] = 0x50; // EWSR
err = flashio(ddf->fd, ddf->link, cmd, 1, NULL, 0); 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(0x0011, "Octopus CI", "DVBBridgeV2B_DD01_0011.fpga"),
DEV(0x0012, "Octopus CI", "DVBBridgeV2B_DD01_0012_STD.fpga"), DEV(0x0012, "Octopus CI", "DVBBridgeV2B_DD01_0012_STD.fpga"),
DEV(0x0013, "Octopus PRO", "DVBBridgeV2B_DD01_0013_PRO.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(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(0x0201, "Modulator", "DVBModulatorV1B_DVBModulatorV1B.bit"),
DEV(0x0203, "Modulator Test", "DVBModulatorV1B_DD01_0203.fpga"), DEV(0x0203, "Modulator Test", "DVBModulatorV1B_DD01_0203.fpga"),
DEV(0x0210, "Modulator V2", "DVBModulatorV2A_DD01_0210.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); close(fd);
for (p = 0; p < fsize && buf[p]; p++) { 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++) { for (; p < fsize && buf[p] != 0x0a; p++) {
if (buf[p] == ':') { if (buf[p] == ':') {
buf[p] = 0; buf[p] = 0;
val = &buf[p + 1]; val = (char *) &buf[p + 1];
} }
} }
if (val == NULL || p == fsize) 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 <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <pthread.h> #include <pthread.h>
#include <getopt.h>
#include <linux/dvb/mod.h> #include <linux/dvb/mod.h>
@ -31,17 +32,134 @@ static int set_property(int fd, uint32_t cmd, uint32_t data)
return 0; 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; int fd;
struct dvb_mod_params mp; struct dvb_mod_params mp;
struct dvb_mod_channel_params mc; 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); switch (c) {
set_property(fd, MODULATOR_SYMBOL_RATE, 6900000); case 'a':
set_property(fd, MODULATOR_FREQUENCY, 114000000); 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); 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,14 @@
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 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-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
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o #mci.o ifneq ($(KERNEL_DVB_CORE),y)
obj-$(CONFIG_DVB_OCTONET) += octonet.o obj-$(CONFIG_DVB_OCTONET) += octonet.o
endif
#EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends #EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -Idrivers/media/dvb-frontends
#EXTRA_CFLAGS += -Idrivers/media/common/tuners #EXTRA_CFLAGS += -Idrivers/media/common/tuners

View File

@ -1,15 +1,13 @@
# #
# Makefile for the ddbridge device driver # 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 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-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_DDBRIDGE) += ddbridge.o
obj-$(CONFIG_DVB_OCTONET) += octonet.o obj-$(CONFIG_DVB_OCTONET) += octonet.o
#ccflags-y += -Idrivers/media/include/linux/ ccflags-y += -Idrivers/media/dvb-frontends/
#ccflags-y += -Idrivers/media/dvb-frontends/ ccflags-y += -Idrivers/media/tuners/
#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 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_DDBRIDGE) += ddbridge.o
obj-$(CONFIG_DVB_OCTONET) += octonet.o obj-$(CONFIG_DVB_OCTONET) += octonet.o
@ -11,4 +11,5 @@ obj-$(CONFIG_DVB_OCTONET) += octonet.o
ccflags-y += -Idrivers/media/dvb-core/ ccflags-y += -Idrivers/media/dvb-core/
ccflags-y += -Idrivers/media/dvb-frontends/ ccflags-y += -Idrivers/media/dvb-frontends/
ccflags-y += -Idrivers/media/tuners/ ccflags-y += -Idrivers/media/tuners/
ccflags-y += --include=dd_compat.h

View File

@ -32,7 +32,7 @@ static int wait_ci_ready(struct ddb_ci *ci)
ndelay(500); ndelay(500);
do { do {
if (ddbreadl(ci->port->dev, if (ddbreadl(ci->port->dev,
CI_CONTROL(ci->nr)) & CI_READY) CI_CONTROL(ci)) & CI_READY)
break; break;
usleep_range(1, 2); usleep_range(1, 2);
if ((--count) == 0) if ((--count) == 0)
@ -45,14 +45,15 @@ static int read_attribute_mem(struct dvb_ca_en50221 *ca,
int slot, int address) int slot, int address)
{ {
struct ddb_ci *ci = ca->data; 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) if (address > CI_BUFFER_SIZE)
return -1; return -1;
ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, 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); 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; return val;
} }
@ -62,7 +63,7 @@ static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
struct ddb_ci *ci = ca->data; struct ddb_ci *ci = ca->data;
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, 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); wait_ci_ready(ci);
return 0; return 0;
} }
@ -75,10 +76,10 @@ static int read_cam_control(struct dvb_ca_en50221 *ca,
u32 res; u32 res;
ddbwritel(ci->port->dev, CI_READ_CMD | address, ddbwritel(ci->port->dev, CI_READ_CMD | address,
CI_DO_IO_RW(ci->nr)); CI_DO_IO_RW(ci));
ndelay(500); ndelay(500);
do { do {
res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); res = ddbreadl(ci->port->dev, CI_READDATA(ci));
if (res & CI_READY) if (res & CI_READY)
break; break;
usleep_range(1, 2); 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; struct ddb_ci *ci = ca->data;
ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, 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); wait_ci_ready(ci);
return 0; return 0;
} }
@ -104,15 +105,15 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
struct ddb_ci *ci = ca->data; struct ddb_ci *ci = ca->data;
ddbwritel(ci->port->dev, CI_POWER_ON, ddbwritel(ci->port->dev, CI_POWER_ON,
CI_CONTROL(ci->nr)); CI_CONTROL(ci));
msleep(100); msleep(300);
ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, 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, ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
CI_CONTROL(ci->nr)); CI_CONTROL(ci));
usleep_range(20, 25); msleep(20);
ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
CI_CONTROL(ci->nr)); CI_CONTROL(ci));
return 0; return 0;
} }
@ -120,7 +121,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
{ {
struct ddb_ci *ci = ca->data; 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); msleep(300);
return 0; 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) static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
{ {
struct ddb_ci *ci = ca->data; 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, ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
CI_CONTROL(ci->nr)); CI_CONTROL(ci));
return 0; return 0;
} }
static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
{ {
struct ddb_ci *ci = ca->data; 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; int stat = 0;
if (val & CI_CAM_DETECT) if (val & CI_CAM_DETECT)
@ -162,6 +163,8 @@ static struct dvb_ca_en50221 en_templ = {
static void ci_attach(struct ddb_port *port) static void ci_attach(struct ddb_port *port)
{ {
struct ddb_ci *ci; 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); ci = kzalloc(sizeof(*ci), GFP_KERNEL);
if (!ci) if (!ci)
@ -171,6 +174,7 @@ static void ci_attach(struct ddb_port *port)
port->en = &ci->en; port->en = &ci->en;
ci->port = port; ci->port = port;
ci->nr = port->nr - 2; ci->nr = port->nr - 2;
ci->regs = DDB_LINK_TAG(port->lnr) | (off + 32 * ci->nr);
} }
/* DuoFlex Dual CI support */ /* DuoFlex Dual CI support */
@ -234,9 +238,11 @@ static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot)
{ {
struct ddb_ci *ci = ca->data; struct ddb_ci *ci = ca->data;
write_creg(ci, 0x00, 0x01);
msleep(300);
write_creg(ci, 0x01, 0x01); write_creg(ci, 0x01, 0x01);
write_creg(ci, 0x04, 0x04); write_creg(ci, 0x04, 0x04);
msleep(20); msleep(300);
write_creg(ci, 0x02, 0x02); write_creg(ci, 0x02, 0x02);
write_creg(ci, 0x00, 0x04); write_creg(ci, 0x00, 0x04);
write_creg(ci, 0x18, 0x18); write_creg(ci, 0x18, 0x18);

File diff suppressed because it is too large Load Diff

View File

@ -246,7 +246,6 @@ static const struct ddb_regmap octopus_map = {
.odma = &octopus_odma, .odma = &octopus_odma,
.odma_buf = &octopus_odma_buf, .odma_buf = &octopus_odma_buf,
.input = &octopus_input, .input = &octopus_input,
.output = &octopus_output, .output = &octopus_output,
}; };
@ -315,10 +314,14 @@ static const struct ddb_regmap octopus_mod_2_map = {
.irq_version = 2, .irq_version = 2,
.irq_base_odma = 64, .irq_base_odma = 64,
.irq_base_rate = 32, .irq_base_rate = 32,
.irq_base_mci = 10,
.output = &octopus_output, .output = &octopus_output,
.odma = &octopus_mod_2_odma, .odma = &octopus_mod_2_odma,
.odma_buf = &octopus_mod_2_odma_buf, .odma_buf = &octopus_mod_2_odma_buf,
.channel = &octopus_mod_2_channel, .channel = &octopus_mod_2_channel,
.mci = &sdr_mci,
.mci_buf = &sdr_mci_buf,
}; };
static const struct ddb_regmap octopus_sdr_map = { static const struct ddb_regmap octopus_sdr_map = {
@ -459,23 +462,25 @@ static const struct ddb_info ddb_satixs2v3 = {
}; };
static const struct ddb_info ddb_ci = { static const struct ddb_info ddb_ci = {
.type = DDB_OCTOPUS_CI, .type = DDB_OCTOPUS,
.name = "Digital Devices Octopus CI", .name = "Digital Devices Octopus CI",
.regmap = &octopus_map, .regmap = &octopus_map,
.port_num = 4, .port_num = 4,
.i2c_mask = 0x03, .i2c_mask = 0x03,
.ci_mask = 0x0c,
}; };
static const struct ddb_info ddb_cis = { static const struct ddb_info ddb_cis = {
.type = DDB_OCTOPUS_CI, .type = DDB_OCTOPUS,
.name = "Digital Devices Octopus CI single", .name = "Digital Devices Octopus CI single",
.regmap = &octopus_map, .regmap = &octopus_map,
.port_num = 3, .port_num = 3,
.i2c_mask = 0x03, .i2c_mask = 0x03,
.ci_mask = 0x04,
}; };
static const struct ddb_info ddb_ci_s2_pro = { static const struct ddb_info ddb_ci_s2_pro = {
.type = DDB_OCTOPUS_CI, .type = DDB_OCTOPUS,
.name = "Digital Devices Octopus CI S2 Pro", .name = "Digital Devices Octopus CI S2 Pro",
.regmap = &octopus_map, .regmap = &octopus_map,
.port_num = 4, .port_num = 4,
@ -483,10 +488,11 @@ static const struct ddb_info ddb_ci_s2_pro = {
.board_control = 2, .board_control = 2,
.board_control_2 = 4, .board_control_2 = 4,
.hw_min = 0x010007, .hw_min = 0x010007,
.ci_mask = 0x0c,
}; };
static const struct ddb_info ddb_ci_s2_pro_a = { 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", .name = "Digital Devices Octopus CI S2 Pro Advanced",
.regmap = &octopus_map, .regmap = &octopus_map,
.port_num = 4, .port_num = 4,
@ -494,6 +500,7 @@ static const struct ddb_info ddb_ci_s2_pro_a = {
.board_control = 2, .board_control = 2,
.board_control_2 = 4, .board_control_2 = 4,
.hw_min = 0x010007, .hw_min = 0x010007,
.ci_mask = 0x0c,
}; };
static const struct ddb_info ddb_dvbct = { static const struct ddb_info ddb_dvbct = {
@ -566,6 +573,17 @@ static const struct ddb_info ddb_mod_fsm_4 = {
.lostlock_irq = 9, .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 = { static const struct ddb_info ddb_sdr_atv = {
.type = DDB_MOD, .type = DDB_MOD,
.name = "Digital Devices SDR ATV", .name = "Digital Devices SDR ATV",
@ -601,27 +619,19 @@ static const struct ddb_info ddb_sdr_dvbt = {
.name = "Digital Devices DVBT", .name = "Digital Devices DVBT",
.version = 18, .version = 18,
.regmap = &octopus_sdr_map, .regmap = &octopus_sdr_map,
.port_num = 16, .port_num = 14,
.temp_num = 1, .temp_num = 1,
.tempmon_irq = 8, .tempmon_irq = 8,
}; };
static const struct ddb_info ddb_octopro_hdin = { static const struct ddb_info ddb_sdr_dvbt_16 = {
.type = DDB_OCTOPRO_HDIN, .type = DDB_MOD,
.name = "Digital Devices OctopusNet Pro HDIN", .name = "Digital Devices DVBT",
.regmap = &octopro_hdin_map, .version = 18,
.port_num = 10, .regmap = &octopus_sdr_map,
.i2c_mask = 0x3ff, .port_num = 16,
.mdio_base = 0x10020, .temp_num = 1,
}; .tempmon_irq = 8,
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_s2_48 = { static const struct ddb_info ddb_s2_48 = {
@ -632,6 +642,7 @@ static const struct ddb_info ddb_s2_48 = {
.i2c_mask = 0x01, .i2c_mask = 0x01,
.board_control = 1, .board_control = 1,
.tempmon_irq = 24, .tempmon_irq = 24,
.lnb_base = 0x400,
}; };
static const struct ddb_info ddb_ct2_8 = { static const struct ddb_info ddb_ct2_8 = {
@ -704,8 +715,9 @@ static const struct ddb_info ddb_s2x_48 = {
.i2c_mask = 0x00, .i2c_mask = 0x00,
.tempmon_irq = 24, .tempmon_irq = 24,
.mci_ports = 4, .mci_ports = 4,
.mci_type = 0, .mci_type = DDB_TUNER_MCI_SX8,
.temp_num = 1, .temp_num = 1,
.lnb_base = 0x400,
}; };
static const struct ddb_info ddb_s2x_48_b = { static const struct ddb_info ddb_s2x_48_b = {
@ -716,8 +728,9 @@ static const struct ddb_info ddb_s2x_48_b = {
.i2c_mask = 0x00, .i2c_mask = 0x00,
.tempmon_irq = 24, .tempmon_irq = 24,
.mci_ports = 4, .mci_ports = 4,
.mci_type = 0, .mci_type = DDB_TUNER_MCI_SX8,
.temp_num = 1, .temp_num = 1,
.lnb_base = 0x400,
}; };
static const struct ddb_info ddb_m4 = { static const struct ddb_info ddb_m4 = {
@ -728,8 +741,72 @@ static const struct ddb_info ddb_m4 = {
.i2c_mask = 0x00, .i2c_mask = 0x00,
.tempmon_irq = 24, .tempmon_irq = 24,
.mci_ports = 2, .mci_ports = 2,
.mci_type = 1, .mci_type = DDB_TUNER_MCI_M4,
.temp_num = 1, .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,
}; };
/****************************************************************************/ /****************************************************************************/
@ -862,13 +939,19 @@ static const struct ddb_device_id ddb_device_ids[] = {
DDB_DEVID(0x0012, 0x0042, ddb_ci), DDB_DEVID(0x0012, 0x0042, ddb_ci),
DDB_DEVID(0x0013, 0x0043, ddb_ci_s2_pro), DDB_DEVID(0x0013, 0x0043, ddb_ci_s2_pro),
DDB_DEVID(0x0013, 0x0044, ddb_ci_s2_pro_a), 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(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 */ /* Modulators */
DDB_DEVID(0x0201, 0x0001, ddb_mod), DDB_DEVID(0x0201, 0x0001, ddb_mod),
DDB_DEVID(0x0201, 0x0002, ddb_mod), DDB_DEVID(0x0201, 0x0002, ddb_mod),
DDB_DEVID(0x0201, 0x0004, ddb_mod_4), /* dummy entry ! */ DDB_DEVID(0x0201, 0x0004, ddb_mod_4), /* dummy entry ! */
DDB_DEVID(0x0203, 0x0001, ddb_mod), 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, 0x0000, ddb_mod_fsm_4), /* dummy entry ! */
DDB_DEVID(0x0210, 0x0001, ddb_mod_fsm_24), DDB_DEVID(0x0210, 0x0001, ddb_mod_fsm_24),
DDB_DEVID(0x0210, 0x0002, ddb_mod_fsm_16), DDB_DEVID(0x0210, 0x0002, ddb_mod_fsm_16),
@ -876,16 +959,8 @@ static const struct ddb_device_id ddb_device_ids[] = {
DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv), DDB_DEVID(0x0220, 0x0001, ddb_sdr_atv),
DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq), DDB_DEVID(0x0221, 0x0001, ddb_sdr_iq),
DDB_DEVID(0x0222, 0x0001, ddb_sdr_dvbt), 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(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), 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.retry = 0;
cmd.dvbs2_search.frequency = p->frequency * 1000; cmd.dvbs2_search.frequency = p->frequency * 1000;
cmd.dvbs2_search.symbol_rate = p->symbol_rate; 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) if (p->stream_id != NO_STREAM_ID_FILTER)
cmd.dvbs2_search.input_stream_id = p->stream_id; cmd.dvbs2_search.input_stream_id = p->stream_id;
cmd.tuner = state->mci.nr; cmd.tuner = state->mci.tuner;
cmd.demod = state->mci.tuner; cmd.demod = state->mci.demod;
cmd.output = state->mci.nr; cmd.output = state->mci.nr;
stat = ddb_mci_cmd(&state->mci, &cmd, NULL); 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); ddb_mci_get_strength(fe);
if (res.status == MCI_DEMOD_WAIT_SIGNAL) if (res.status == MCI_DEMOD_WAIT_SIGNAL)
*status = 0x01; *status = 0x01;
else if (res.status == M4_DEMOD_WAIT_TS) else if (res.status == MX_DEMOD_WAIT_TS)
*status = 0x03; *status = 0x03;
else if (res.status == MCI_DEMOD_TIMEOUT) else if (res.status == MCI_DEMOD_TIMEOUT)
*status = FE_TIMEDOUT; *status = FE_TIMEDOUT;
@ -456,6 +457,9 @@ static void release(struct dvb_frontend *fe)
kfree(mci_base); kfree(mci_base);
} }
kfree(state); kfree(state);
#ifdef CONFIG_MEDIA_ATTACH
__module_get(THIS_MODULE);
#endif
} }
static enum dvbfe_algo get_algo(struct dvb_frontend *fe) 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 = { static struct dvb_frontend_ops m4_ops = {
.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C, .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_C,
SYS_ISDBC, SYS_DVBC2, SYS_DVBC2, SYS_DVBT, SYS_DVBT2, SYS_DVBS, SYS_DVBS2,
SYS_DVBT, SYS_DVBT2, SYS_ISDBT, #ifndef KERNEL_DVB_CORE
SYS_DVBS, SYS_DVBS2, SYS_ISDBS, }, SYS_ISDBC, SYS_ISDBS, SYS_ISDBT,
#endif
},
.info = { .info = {
.name = "M4", .name = "M4",
.frequency_min_hz = 47125000, /* DVB-T: 47125000 */ .frequency_min_hz = 47125000, /* DVB-T: 47125000 */
@ -516,7 +522,7 @@ static int base_init(struct mci_base *mci_base)
return 0; return 0;
} }
struct mci_cfg ddb_max_m4_cfg = { static struct mci_cfg ddb_max_m4_cfg = {
.type = 0, .type = 0,
.fe_ops = &m4_ops, .fe_ops = &m4_ops,
.base_size = sizeof(struct m4_base), .base_size = sizeof(struct m4_base),
@ -524,3 +530,137 @@ struct mci_cfg ddb_max_m4_cfg = {
.init = init, .init = init,
.base_init = base_init, .base_init = base_init,
}; };
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_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) { if (dev->link[0].info->regmap->irq_version == 2) {
ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL); ddbwritel(dev, 0x00000000, INTERRUPT_V2_CONTROL);
@ -114,7 +114,7 @@ static void __devexit ddb_msi_exit(struct ddb *dev)
#endif #endif
} }
static void __devexit ddb_irq_exit(struct ddb *dev) static void ddb_irq_exit(struct ddb *dev)
{ {
ddb_irq_disable(dev); ddb_irq_disable(dev);
if (dev->msi == 2) if (dev->msi == 2)
@ -255,17 +255,9 @@ static int __devinit ddb_irq_init(struct ddb *dev)
return stat; return stat;
} }
} else { } else {
#ifdef DDB_TEST_THREADED
stat = request_threaded_irq(pci_irq_vector(dev->pdev, 0),
dev->pdev->irq, ddb_irq_handler,
irq_thread,
irq_flag,
"ddbridge", (void *)dev);
#else
stat = request_irq(pci_irq_vector(dev->pdev, 0), stat = request_irq(pci_irq_vector(dev->pdev, 0),
ddb_irq_handler, ddb_irq_handler,
irq_flag, "ddbridge", (void *)dev); irq_flag, "ddbridge", (void *)dev);
#endif
if (stat < 0) if (stat < 0)
return stat; return stat;
} }
@ -291,11 +283,17 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
pci_set_master(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))) { if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
pci_set_consistent_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))) { } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
pci_set_consistent_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)); dev = vzalloc(sizeof(*dev));
if (!dev) if (!dev)
@ -317,7 +315,6 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].dev = dev; dev->link[0].dev = dev;
dev->link[0].info = get_ddb_info(id->vendor, id->device, dev->link[0].info = get_ddb_info(id->vendor, id->device,
id->subvendor, pdev->subsystem_device); id->subvendor, pdev->subsystem_device);
dev_info(dev->dev, "device name: %s\n", dev->link[0].info->name);
dev->regs_len = pci_resource_len(dev->pdev, 0); dev->regs_len = pci_resource_len(dev->pdev, 0);
dev->regs = ioremap(pci_resource_start(dev->pdev, 0), dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
@ -337,10 +334,6 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->link[0].ids.hwid = ddbreadl(dev, 0); dev->link[0].ids.hwid = ddbreadl(dev, 0);
dev->link[0].ids.regmapid = ddbreadl(dev, 4); dev->link[0].ids.regmapid = ddbreadl(dev, 4);
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,
dev->link[0].ids.hwid & 0xffff);
if ((dev->link[0].ids.hwid & 0xffffff) < if ((dev->link[0].ids.hwid & 0xffffff) <
dev->link[0].info->hw_min) { dev->link[0].info->hw_min) {
u32 min = dev->link[0].info->hw_min; u32 min = dev->link[0].info->hw_min;
@ -357,33 +350,27 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
if (dev->link[0].info->type != DDB_MOD) if (dev->link[0].info->type != DDB_MOD)
ddbwritel(dev, 0, DMA_BASE_WRITE); ddbwritel(dev, 0, DMA_BASE_WRITE);
if (dev->link[0].info->type == DDB_MOD if (dev->link[0].info->type == DDB_MOD &&
&& dev->link[0].info->version <= 1) { dev->link[0].info->version <= 1) {
if (ddbreadl(dev, 0x1c) == 4) if (ddbreadl(dev, 0x1c) == 4)
dev->link[0].info = dev->link[0].info =
get_ddb_info(0xdd01, 0x0201, 0xdd01, 0x0004); 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;
switch (lic) { if (dev->link[0].info->type == DDB_MOD &&
case 0: dev->link[0].info->version == 2) {
dev->link[0].info = if (dev->link[0].ids.revision == 1)
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0000); dev->link[0].info = get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0004);
break; else if ((ddbreadl(dev, 0x1c) & 7) != 7)
case 1: dev->link[0].info = get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0004);
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0003);
break;
case 3:
dev->link[0].info =
get_ddb_info(0xdd01, 0x0210, 0xdd01, 0x0002);
break;
default:
break;
}
} }
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,
dev->link[0].ids.hwid & 0xffff);
stat = ddb_irq_init(dev); stat = ddb_irq_init(dev);
if (stat < 0) if (stat < 0)
goto fail0; goto fail0;
@ -401,13 +388,19 @@ fail:
ddb_unmap(dev); ddb_unmap(dev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev); pci_disable_device(pdev);
return -1; return stat;
} }
/****************************************************************************/ /****************************************************************************/
/****************************************************************************/ /****************************************************************************/
/****************************************************************************/ /****************************************************************************/
#ifndef PCI_DEVICE_SUB
#define PCI_DEVICE_SUB(vend, dev, subvend, subdev) \
.vendor = (vend), .device = (dev), \
.subvendor = (subvend), .subdevice = (subdev)
#endif
#define DDB_DEVICE_ANY(_device) \ #define DDB_DEVICE_ANY(_device) \
{ PCI_DEVICE_SUB(0xdd01, _device, 0xdd01, PCI_ANY_ID) } { PCI_DEVICE_SUB(0xdd01, _device, 0xdd01, PCI_ANY_ID) }
@ -424,7 +417,12 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = {
DDB_DEVICE_ANY(0x0011), DDB_DEVICE_ANY(0x0011),
DDB_DEVICE_ANY(0x0012), DDB_DEVICE_ANY(0x0012),
DDB_DEVICE_ANY(0x0013), DDB_DEVICE_ANY(0x0013),
DDB_DEVICE_ANY(0x0014),
DDB_DEVICE_ANY(0x0020), 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(0x0201),
DDB_DEVICE_ANY(0x0203), DDB_DEVICE_ANY(0x0203),
DDB_DEVICE_ANY(0x0210), DDB_DEVICE_ANY(0x0210),
@ -432,17 +430,10 @@ static const struct pci_device_id ddb_id_table[] __devinitconst = {
DDB_DEVICE_ANY(0x0221), DDB_DEVICE_ANY(0x0221),
DDB_DEVICE_ANY(0x0222), DDB_DEVICE_ANY(0x0222),
DDB_DEVICE_ANY(0x0223), 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} {0}
}; };
MODULE_DEVICE_TABLE(pci, ddb_id_table); MODULE_DEVICE_TABLE(pci, ddb_id_table);
static pci_ers_result_t ddb_pci_slot_reset(struct pci_dev *dev) static pci_ers_result_t ddb_pci_slot_reset(struct pci_dev *dev)
{ {
pr_info("pci_slot_reset\n"); pr_info("pci_slot_reset\n");
@ -482,7 +473,6 @@ static const struct pci_error_handlers ddb_error = {
.resume = ddb_pci_resume, .resume = ddb_pci_resume,
}; };
static struct pci_driver ddb_pci_driver = { static struct pci_driver ddb_pci_driver = {
.name = "ddbridge", .name = "ddbridge",
.id_table = ddb_id_table, .id_table = ddb_id_table,

View File

@ -28,6 +28,10 @@
/* MAX LNB interface related module parameters */ /* 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; static int fmode;
module_param(fmode, int, 0444); module_param(fmode, int, 0444);
MODULE_PARM_DESC(fmode, "frontend emulation mode"); MODULE_PARM_DESC(fmode, "frontend emulation mode");
@ -44,31 +48,36 @@ static int no_voltage;
module_param(no_voltage, int, 0444); module_param(no_voltage, int, 0444);
MODULE_PARM_DESC(no_voltage, "Do not enable voltage on LNBH (will also disable 22KHz tone)."); 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 */ /* MAX LNB interface related functions */
static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd) static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
{ {
u32 c, v = 0, tag = DDB_LINK_TAG(link); 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)); 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++) { 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) if ((v & LNB_BUSY) == 0)
break; break;
msleep(20); msleep(20);
} }
if (c == 10) if (c == 10)
dev_info(dev->dev, dev_info(dev->dev,
"%s lnb = %08x cmd = %08x\n", "%s lnb = %08x cmd = %08x timed out\n",
__func__, lnb, cmd); __func__, lnb, cmd | v);
return 0; return 0;
} }
static int max_set_input(struct dvb_frontend *fe, int in); static int max_set_input(struct dvb_frontend *fe, int in);
static int max_emulate_switch(struct dvb_frontend *fe, static int max_emulate_switch(struct dvb_frontend *fe, u8 *cmd, u32 len)
u8 *cmd, u32 len)
{ {
int input; int input;
@ -91,6 +100,7 @@ static int max_send_master_cmd(struct dvb_frontend *fe,
struct ddb *dev = port->dev; struct ddb *dev = port->dev;
struct ddb_dvb *dvb = &port->dvb[input->nr & 1]; struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
u32 tag = DDB_LINK_TAG(port->lnr); u32 tag = DDB_LINK_TAG(port->lnr);
u32 base = dev->link[port->lnr].info->lnb_base;
int i; int i;
u32 fmode = dev->link[port->lnr].lnb.fmode; 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)) if (!max_emulate_switch(fe, cmd->msg, cmd->msg_len))
return 0; 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) if (dvb->diseqc_send_master_cmd)
dvb->diseqc_send_master_cmd(fe, cmd); dvb->diseqc_send_master_cmd(fe, cmd);
mutex_lock(&dev->link[port->lnr].lnb.lock); 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++) 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); lnb_command(dev, port->lnr, dvb->input, LNB_CMD_DISEQC);
mutex_unlock(&dev->link[port->lnr].lnb.lock); mutex_unlock(&dev->link[port->lnr].lnb.lock);
return 0; return 0;
@ -117,11 +132,12 @@ static int lnb_send_diseqc(struct ddb *dev, u32 link, u32 input,
struct dvb_diseqc_master_cmd *cmd) struct dvb_diseqc_master_cmd *cmd)
{ {
u32 tag = DDB_LINK_TAG(link); u32 tag = DDB_LINK_TAG(link);
u32 base = dev->link[link].info->lnb_base;
int i; 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++) 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); lnb_command(dev, link, input, LNB_CMD_DISEQC);
return 0; 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_port *port = input->port;
struct ddb *dev = port->dev; struct ddb *dev = port->dev;
u32 tag = DDB_LINK_TAG(port->lnr); 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]; struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
u32 fmode = dev->link[port->lnr].lnb.fmode; 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: default:
case 0: case 0:
case 3: case 3:
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(dvb->input)); ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(dvb->input));
break; break;
case 1: case 1:
case 2: case 2:
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(0)); ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(0));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(1)); ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(1));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(2)); ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(2));
ddbwritel(dev, arg ? 0x34 : 0x01, tag | LNB_CONTROL(3)); ddbwritel(dev, arg ? 0x34 : 0x01, tag | base | LNB_CONTROL(3));
break; break;
} }
mutex_unlock(&dev->link[port->lnr].lnb.lock); mutex_unlock(&dev->link[port->lnr].lnb.lock);
@ -465,14 +482,20 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
cfg = mxl5xx; cfg = mxl5xx;
cfg.fw_priv = link; cfg.fw_priv = link;
if (dev->link[0].info->type == DDB_OCTONET) if (dev->link[0].info->type == DDB_OCTONET) {
;/*cfg.ts_clk = 69;*/ ;/*cfg.ts_clk = 69;*/
}
demod = input->nr; demod = input->nr;
tuner = demod & 3; tuner = demod & 3;
if (fmode >= 3) if (fmode >= 3)
tuner = 0; tuner = 0;
dvb->fe = dvb_attach(mxl5xx_attach, i2c, &cfg, demod, tuner); #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) { if (!dvb->fe) {
dev_err(dev->dev, "No MXL5XX found!\n"); dev_err(dev->dev, "No MXL5XX found!\n");
return -ENODEV; return -ENODEV;
@ -490,13 +513,18 @@ int ddb_fe_attach_mxl5xx(struct ddb_input *input)
dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd; dvb->fe->ops.diseqc_send_master_cmd = max_send_master_cmd;
dvb->fe->ops.diseqc_send_burst = max_send_burst; dvb->fe->ops.diseqc_send_burst = max_send_burst;
dvb->fe->sec_priv = input; dvb->fe->sec_priv = input;
dvb->set_input = dvb->fe->ops.set_input; #ifndef KERNEL_DVB_CORE
dvb->fe->ops.set_input = max_set_input; dvb->fe->ops.set_input = max_set_input;
#endif
dvb->input = tuner; dvb->input = tuner;
return 0; return 0;
} }
/* MAX MCI related functions */ /* 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_mx_attach(struct ddb_input *input, int nr, int tuner, int type);
int ddb_fe_attach_mci(struct ddb_input *input, u32 type) int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
{ {
@ -505,30 +533,67 @@ int ddb_fe_attach_mci(struct ddb_input *input, u32 type)
struct ddb_port *port = input->port; struct ddb_port *port = input->port;
struct ddb_link *link = &dev->link[port->lnr]; struct ddb_link *link = &dev->link[port->lnr];
int demod, tuner; int demod, tuner;
struct mci_cfg cfg;
int fm = fmode; int fm = fmode;
demod = input->nr; demod = input->nr;
tuner = demod & 3; tuner = demod & 3;
switch (type) { switch (type) {
case DDB_TUNER_MCI_SX8: case DDB_TUNER_MCI_SX8:
cfg = ddb_max_sx8_cfg;
if (fm >= 3) if (fm >= 3)
tuner = 0; tuner = 0;
dvb->fe = ddb_sx8_attach(input, demod, tuner, &dvb->set_input);
dvb->input = tuner;
break; break;
case DDB_TUNER_MCI_M4: case DDB_TUNER_MCI_M4:
fm = 0; fm = 0;
cfg = ddb_max_m4_cfg; dvb->fe = ddb_mx_attach(input, demod, tuner, 0);
dvb->input = tuner;
break; 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: default:
return -EINVAL; return -EINVAL;
} }
dvb->fe = ddb_mci_attach(input, &cfg, demod, tuner);
if (!dvb->fe) { if (!dvb->fe) {
dev_err(dev->dev, "No MCI card found!\n"); dev_err(dev->dev, "No MCI card found!\n");
return -ENODEV; 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_command(dev, port->lnr, input->nr, LNB_CMD_INIT);
lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF); lnb_set_voltage(dev, port->lnr, input->nr, SEC_VOLTAGE_OFF);
} }
@ -541,14 +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_master_cmd = max_send_master_cmd;
dvb->fe->ops.diseqc_send_burst = max_send_burst; dvb->fe->ops.diseqc_send_burst = max_send_burst;
dvb->fe->sec_priv = input; dvb->fe->sec_priv = input;
switch (type) { if (type == DDB_TUNER_MCI_SX8) {
case DDB_TUNER_MCI_M4: #ifndef KERNEL_DVB_CORE
break;
default:
dvb->set_input = dvb->fe->ops.set_input;
dvb->fe->ops.set_input = max_set_input; dvb->fe->ops.set_input = max_set_input;
break; #endif
} }
dvb->input = tuner;
return 0; return 0;
} }

View File

@ -134,6 +134,8 @@ int ddb_mci_cmd_link(struct ddb_link *link,
struct mci_result res; struct mci_result res;
int stat; int stat;
if (!link->mci_ok)
return -EFAULT;
if (!result) if (!result)
result = &res; result = &res;
mutex_lock(&link->mci_lock); mutex_lock(&link->mci_lock);
@ -150,6 +152,17 @@ int ddb_mci_cmd_link(struct ddb_link *link,
return stat; 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) static void mci_handler(void *priv)
{ {
struct ddb_link *link = (struct ddb_link *) priv; struct ddb_link *link = (struct ddb_link *) priv;
@ -197,7 +210,7 @@ int ddb_mci_cmd(struct mci *state,
} }
int ddb_mci_cmd_raw(struct mci *state, static int ddb_mci_cmd_raw(struct mci *state,
struct mci_command *command, u32 command_len, struct mci_command *command, u32 command_len,
struct mci_result *result, u32 result_len) struct mci_result *result, u32 result_len)
{ {
@ -221,21 +234,6 @@ int ddb_mci_get_status(struct mci *mci, struct mci_result *res)
return ddb_mci_cmd_raw(mci, &cmd, 1, res, 1); return ddb_mci_cmd_raw(mci, &cmd, 1, res, 1);
} }
static void ddb_mci_print_info(struct mci *mci)
{
struct ddb_link *link = mci->base->link;
const struct ddb_regmap *regmap = link->info->regmap;
struct mci_command cmd;
struct mci_result res;
cmd.command = 0x0f;
if (ddb_mci_cmd_raw(mci, &cmd, 1, &res, 1) < 0)
return;
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
link->dev->regs + regmap->mci_buf->base + MCI_COMMAND_SIZE,
16, false);
}
int ddb_mci_get_snr(struct dvb_frontend *fe) int ddb_mci_get_snr(struct dvb_frontend *fe)
{ {
struct mci *mci = fe->demodulator_priv; struct mci *mci = fe->demodulator_priv;
@ -300,7 +298,7 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
}; };
const enum fe_code_rate dvbs_fec_lut[8] = { const enum fe_code_rate dvbs_fec_lut[8] = {
FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6,
FEC_NONE, FEC_7_8, FEC_NONE, FEC_NONE, FEC_7_8, FEC_7_8, FEC_NONE, FEC_NONE,
}; };
const enum fe_rolloff ro_lut[8] = { const enum fe_rolloff ro_lut[8] = {
ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_10, ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_10,
@ -309,8 +307,9 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
p->frequency = p->frequency =
mci->signal_info.dvbs2_signal_info.frequency; mci->signal_info.dvbs2_signal_info.frequency;
p->symbol_rate =
mci->signal_info.dvbs2_signal_info.symbol_rate;
switch (p->delivery_system) { switch (p->delivery_system) {
default:
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
{ {
@ -353,6 +352,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
break; break;
} }
case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_A:
p->modulation =
mci->signal_info.dvbc_signal_info.constellation + 1;
break; break;
case SYS_DVBT: case SYS_DVBT:
break; break;
@ -362,6 +363,8 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p)
break; break;
case SYS_ISDBT: case SYS_ISDBT:
break; break;
default:
break;
} }
/* post is correct, we cannot provide both pre and post at the same time */ /* post is correct, we cannot provide both pre and post at the same time */
/* set pre and post the same for now */ /* set pre and post the same for now */

View File

@ -96,11 +96,13 @@
#define SX8_DEMOD_IQ_MODE (1) #define SX8_DEMOD_IQ_MODE (1)
#define SX8_DEMOD_WAIT_MATYPE (3) #define SX8_DEMOD_WAIT_MATYPE (3)
#define M4_DEMOD_WAIT_TS (6) #define MX_DEMOD_WAIT_TS (6)
#define M4_DEMOD_C2SCAN (16) #define MX_DEMOD_C2SCAN (16)
#define MCI_STATUS_OK (0x00) #define MCI_STATUS_OK (0x00)
#define MCI_STATUS_UNSUPPORTED (0x80) #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_INVALID_PARAMETER (0xFC)
#define MCI_STATUS_RETRY (0xFD) #define MCI_STATUS_RETRY (0xFD)
#define MCI_STATUS_NOT_READY (0xFE) #define MCI_STATUS_NOT_READY (0xFE)
@ -111,6 +113,8 @@
#define MCI_CMD_GETSIGNALINFO (0x03) #define MCI_CMD_GETSIGNALINFO (0x03)
//#define MCI_CMD_RFPOWER (0x04) //#define MCI_CMD_RFPOWER (0x04)
#define MCI_CMD_SET_INPUT_CONFIG (0x05)
#define MCI_CMD_SEARCH_DVBS (0x10) #define MCI_CMD_SEARCH_DVBS (0x10)
#define MCI_CMD_SEARCH_ISDBS (0x11) #define MCI_CMD_SEARCH_ISDBS (0x11)
@ -123,6 +127,9 @@
#define MCI_CMD_SEARCH_ISDBC (0x25) #define MCI_CMD_SEARCH_ISDBC (0x25)
#define MCI_CMD_SEARCH_J83B (0x26) #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_CMD_GET_IQSYMBOL (0x30)
#define MCI_BANDWIDTH_UNKNOWN (0) #define MCI_BANDWIDTH_UNKNOWN (0)
@ -140,42 +147,45 @@
#define SX8_CMD_ENABLE_IQOUTPUT (0x44) #define SX8_CMD_ENABLE_IQOUTPUT (0x44)
#define SX8_CMD_DISABLE_IQOUTPUT (0x45) #define SX8_CMD_DISABLE_IQOUTPUT (0x45)
#define M4_CMD_GET_L1INFO (0x50) #define MX_CMD_GET_L1INFO (0x50)
#define M4_CMD_GET_IDS (0x51) #define MX_CMD_GET_IDS (0x51)
#define M4_CMD_GET_DVBT_TPS (0x52) #define MX_CMD_GET_DVBT_TPS (0x52)
#define MCI_CMD_GET_BBHEADER (0x53) #define MCI_CMD_GET_BBHEADER (0x53)
#define M4_CMD_GET_ISDBT_TMCC (0x54) #define MX_CMD_GET_ISDBT_TMCC (0x54)
#define M4_CMD_GET_ISDBS_TMCC (0x55) #define MX_CMD_GET_ISDBS_TMCC (0x55)
#define M4_CMD_GET_ISDBC_TSMF (0x56) #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 MX_L1INFO_SEL_PRE (0)
#define M4_L1INFO_SEL_DSINFO (1) #define MX_L1INFO_SEL_DSINFO (1)
#define M4_L1INFO_SEL_PLPINFO (2) #define MX_L1INFO_SEL_PLPINFO (2)
#define M4_L1INFO_SEL_PLPINFO_C (3) #define MX_L1INFO_SEL_PLPINFO_C (3)
#define M4_L1INFO_SEL_SETID (0x80) #define MX_L1INFO_SEL_SETID (0x80)
#define MCI_BANDWIDTH_EXTENSION (0x80) // currently used only for J83B in Japan #define MCI_BANDWIDTH_EXTENSION (0x80) // currently used only for J83B in Japan
#define M4_MODE_DVBSX (2) #define MX_MODE_DVBSX (2)
#define M4_MODE_DVBC (3) #define MX_MODE_DVBC (3)
#define M4_MODE_DVBT (4) #define MX_MODE_DVBT (4)
#define M4_MODE_DVBT2 (5) #define MX_MODE_DVBT2 (5)
#define M4_MODE_DVBC2 (6) #define MX_MODE_DVBC2 (6)
#define M4_MODE_J83B (7) #define MX_MODE_J83B (7)
#define M4_MODE_ISDBT (8) #define MX_MODE_ISDBT (8)
#define M4_MODE_ISDBC (9) #define MX_MODE_ISDBC (9)
#define M4_MODE_ISDBS (10) #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 MX_DVBC_CONSTELLATION_16QAM (0)
#define M4_DVBC_CONSTELLATION_32QAM (1) #define MX_DVBC_CONSTELLATION_32QAM (1)
#define M4_DVBC_CONSTELLATION_64QAM (2) // also valid for J83B and ISDB-C #define MX_DVBC_CONSTELLATION_64QAM (2) // also valid for J83B and ISDB-C
#define M4_DVBC_CONSTELLATION_128QAM (3) #define MX_DVBC_CONSTELLATION_128QAM (3)
#define M4_DVBC_CONSTELLATION_256QAM (4) // also valid for J83B and ISDB-C #define MX_DVBC_CONSTELLATION_256QAM (4) // also valid for J83B and ISDB-C
#define M4_SIGNALINFO_FLAG_CHANGE (0x01) #define MX_SIGNALINFO_FLAG_CHANGE (0x01)
#define M4_SIGNALINFO_FLAG_EWS (0x02) #define MX_SIGNALINFO_FLAG_EWS (0x02)
#define SX8_ROLLOFF_35 0 #define SX8_ROLLOFF_35 0
#define SX8_ROLLOFF_25 1 #define SX8_ROLLOFF_25 1
@ -203,6 +213,23 @@
#define MOD_STANDARD_DVBT_6 (0x03) #define MOD_STANDARD_DVBT_6 (0x03)
#define MOD_STANDARD_DVBT_5 (0x04) #define MOD_STANDARD_DVBT_5 (0x04)
#define MOD_STANDARD_DVBC_8 (0x08)
#define MOD_STANDARD_DVBC_7 (0x09)
#define MOD_STANDARD_DVBC_6 (0x0A)
#define MOD_STANDARD_J83A_8 (MOD_STANDARD_DVBC_8)
#define MOD_STANDARD_J83A_7 (MOD_STANDARD_DVBC_7)
#define MOD_STANDARD_J83A_6 (MOD_STANDARD_DVBC_6)
#define MOD_STANDARD_J83B_QAM64 (0x0B)
#define MOD_STANDARD_J83B_QAM256 (0x0C)
#define MOD_STANDARD_ISDBC_QAM64 (0x0D)
#define MOD_STANDARD_ISDBC_QAM256 (0x0E)
#define MOD_STANDARD_J83C_QAM64 (MOD_STANDARD_ISDBC_QAM64 )
#define MOD_STANDARD_J83C_QAM256 (MOD_STANDARD_ISDBC_QAM256)
#define MOD_CONNECTOR_OFF (0x00) #define MOD_CONNECTOR_OFF (0x00)
#define MOD_CONNECTOR_F (0x01) #define MOD_CONNECTOR_F (0x01)
#define MOD_CONNECTOR_SMA (0x02) #define MOD_CONNECTOR_SMA (0x02)
@ -232,6 +259,26 @@
#define MOD_DVBT_16QAM (0x01) #define MOD_DVBT_16QAM (0x01)
#define MOD_DVBT_64QAM (0x02) #define MOD_DVBT_64QAM (0x02)
#define MOD_QAM_DVBC_16 (0x00)
#define MOD_QAM_DVBC_32 (0x01)
#define MOD_QAM_DVBC_64 (0x02)
#define MOD_QAM_DVBC_128 (0x03)
#define MOD_QAM_DVBC_256 (0x04)
#define MOD_QAM_J83B_64 (0x05)
#define MOD_QAM_J83B_256 (0x06)
#define MOD_QAM_GENERIC (0x07)
#define MOD_QAM_ISDBC_64 (0x08)
#define MOD_QAM_ISDBC_256 (0x09)
#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 { struct mod_setup_channels {
u8 flags; u8 flags;
u8 standard; u8 standard;
@ -242,17 +289,29 @@ struct mod_setup_channels {
u32 bandwidth; /* used only when Standard == 0 */ u32 bandwidth; /* used only when Standard == 0 */
}; };
struct mod_ofdm_parameter {
u8 fft_size; /* 0 = 2K, 1 = 8K (2K not yet supported) */
u8 guard_interval; /* 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4 (DVB-T Encoding) */
u8 puncture_rate; /* 0 = 1/2, 1 = 2/3, 2 = 3/4, 3 = 5/6, 4 = 7/8 (DVB-T Encoding) */
u8 constellation; /* MOD_DVBT_QPSK, MOD_DVBT_16QAM, MOD_DVBT_64QAM */
u8 rsvd2[2]; /* Reserved for DVB-T hierarchical */
u16 cell_identifier;
};
struct mod_qam_parameter {
u8 modulation;
u8 rolloff; /* Legal values: 12,13,15,18 */
};
struct mod_setup_stream { struct mod_setup_stream {
u8 standard; u8 standard;
u8 stream_format; u8 stream_format;
u8 rsvd1[2]; u8 rsvd1[2];
u32 symbol_rate; /* only used when Standard doesn't define a fixed symbol rate */ u32 symbol_rate; /* only used when Standard doesn't define a fixed symbol rate */
u8 fft_size; /* 0 = 2K, 1 = 8K (2K yet supported) */ union {
u8 guard_interval; /* 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4 (DVB-T Encoding) */ struct mod_ofdm_parameter ofdm;
u8 puncture_rate; /* 0 = 1/2, 1 = 2/3, 2 = 3/4, 3 = 5/6, 4 = 7/8 (DVB-T Encoding) */ struct mod_qam_parameter qam;
u8 constellation; };
u8 rsvd2[2]; /* Reserved for DVB-T hierarchical */
u16 cell_identifier;
}; };
struct mod_setup_output { struct mod_setup_output {
@ -283,6 +342,7 @@ struct mci_command {
}; };
union { union {
u32 params[31]; u32 params[31];
u8 params8[31*4];
struct { struct {
u8 flags; /* Bit 0: DVB-S Enabled, 1: DVB-S2 Enabled, u8 flags; /* Bit 0: DVB-S Enabled, 1: DVB-S2 Enabled,
5: ChannelBonding, 6: FrequencyRange, 7: InputStreamID */ 5: ChannelBonding, 6: FrequencyRange, 7: InputStreamID */
@ -431,6 +491,20 @@ struct mci_command {
struct mod_setup_channels mod_setup_channels[4]; struct mod_setup_channels mod_setup_channels[4];
struct mod_setup_stream mod_setup_stream; struct mod_setup_stream mod_setup_stream;
struct mod_setup_output mod_setup_output; 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;
}; };
}; };
@ -456,7 +530,7 @@ struct mci_result {
s16 channel_power; /* channel power in dBm x 100 */ s16 channel_power; /* channel power in dBm x 100 */
s16 rsvd2; s16 rsvd2;
s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */ s16 signal_to_noise; /* SNR in dB x 100, Note: negativ values are valid in DVB-S2 */
s16 rsvd3; u16 signal_loss_counter;/* Counts signal losses and automatic retunes */
u32 rsvd4; u32 rsvd4;
u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */ u32 ber_numerator; /* Bit error rate: PreRS in DVB-S, PreBCH in DVB-S2X */
u32 ber_denominator; u32 ber_denominator;
@ -614,8 +688,8 @@ struct mci_result {
struct { struct {
u8 tps_info[7]; u8 tps_info[7];
// uint16_t tps_cell_id; // u16 tps_cell_id;
} DVBT_TPSInfo; } dvbt_tps_info;
struct { struct {
struct { struct {
@ -644,7 +718,7 @@ struct mci_result {
u8 CurrentRFIndex; u8 CurrentRFIndex;
u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit u8 T2Version_PostScrambled_BaseLite_Rsvd[2]; // 4,1,1,4 bit
u8 CRC32[4]; u8 CRC32[4];
} DVBT2_L1Pre; } dvbt2_l1_pre;
struct { struct {
u8 SubSlicesPerFrame[2]; u8 SubSlicesPerFrame[2];
@ -656,8 +730,8 @@ struct mci_result {
u8 FEFType; u8 FEFType;
u8 FEFLength[3]; u8 FEFLength[3];
u8 FEFInterval; u8 FEFInterval;
} DVBT2_L1Post; } dvbt2_l1_post;
} DVBT2_L1Info; } dvbt2_l1_info;
struct { struct {
u8 PLPID; u8 PLPID;
@ -677,7 +751,7 @@ struct mci_result {
u8 TimeILType; u8 TimeILType;
u8 InBandAFlag; u8 InBandAFlag;
u8 InBandBFlag_Rsvd1_Mode_StaticFlag_StaticPaddingFlag[2]; // 1,11,2,1,1 u8 InBandBFlag_Rsvd1_Mode_StaticFlag_StaticPaddingFlag[2]; // 1,11,2,1,1
} DVBT2_PLPInfo; } dvbt2_plp_info;
struct { struct {
u8 NetworkID[2]; u8 NetworkID[2];
@ -735,18 +809,18 @@ struct mci_result {
} DVBC2_PLPInfo; } DVBC2_PLPInfo;
struct { struct {
u8 Valid; u8 valid;
u8 MATYPE_1; u8 matype_1;
u8 MATYPE_2; u8 matype_2;
u8 UPL[2]; u8 upl[2];
u8 DFL[2]; u8 dfl[2];
u8 SYNC; u8 sync;
u8 SYNCD[2]; u8 syncd[2];
u8 rsvd; u8 rsvd;
u8 ISSY[3]; u8 issy[3];
u8 min_input_stream_id; u8 min_input_stream_id;
u8 max_input_stream_id; u8 max_input_stream_id;
} BBHeader; } bb_header;
struct { struct {
u8 Mode; // FFT Mode 1,2,3 u8 Mode; // FFT Mode 1,2,3
@ -770,11 +844,41 @@ struct mci_result {
} ISDBS_TMCCInfo; } ISDBS_TMCCInfo;
struct { struct {
uint8_t cut; u8 cut;
uint8_t avs_code; u8 avs_code;
uint8_t temperature; u8 temperature;
uint8_t rsvd[13]; u8 rsvd[13];
} sx8_bist; } sx8_bist;
struct {
u8 status;
u8 offset;
u8 length;
u8 rsvd2;
u32 rsvd3[2];
u8 data[96];
} SX8_packet_filter_status;
struct {
u8 version; /* 0 = none, 1 = SX8 */
u8 flags; /* Bit 0: 1 = Tuner Valid, Bit 1: 1 = Output Valid */
u8 tuner;
u8 output;
} extended_status;
struct {
u8 reserved;
u8 serial_number[17];
} serial_number;
struct {
u8 flags;
u8 serial_number[17];
u16 code;
u8 ID[8];
u8 LK[24];
} license;
}; };
u32 version[3]; u32 version[3];
u8 version_rsvd; u8 version_rsvd;
@ -889,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(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(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_status(struct mci *mci, struct mci_result *res);
int ddb_mci_get_snr(struct dvb_frontend *fe); int ddb_mci_get_snr(struct dvb_frontend *fe);
int ddb_mci_get_info(struct mci *mci); int ddb_mci_get_info(struct mci *mci);
@ -897,8 +1002,6 @@ void ddb_mci_proc_info(struct mci *mci, struct dtv_frontend_properties *p);
int mci_init(struct ddb_link *link); int mci_init(struct ddb_link *link);
int mci_cmd_val(struct ddb_link *link, u32 cmd, u32 val); int mci_cmd_val(struct ddb_link *link, u32 cmd, u32 val);
extern struct mci_cfg ddb_max_sx8_cfg;
extern struct mci_cfg ddb_max_m4_cfg;
#endif #endif
#endif #endif

View File

@ -23,8 +23,13 @@
#include "ddbridge.h" #include "ddbridge.h"
#include "ddbridge-io.h" #include "ddbridge-io.h"
#include "ddbridge-ioctl.h"
#ifdef KERNEL_DVB_CORE
#include "../include/linux/dvb/mod.h"
#else
#include <linux/dvb/mod.h> #include <linux/dvb/mod.h>
#endif
#include <linux/gcd.h> #include <linux/gcd.h>
/****************************************************************************/ /****************************************************************************/
@ -164,11 +169,6 @@ static void mod_calc_rateinc(struct ddb_mod *mod)
{ {
u32 ri; u32 ri;
dev_info(mod->port->dev->dev,
"ibitrate %llu\n", mod->ibitrate);
dev_info(mod->port->dev->dev,
"obitrate %llu\n", mod->obitrate);
if (mod->ibitrate != 0) { if (mod->ibitrate != 0) {
u64 d = mod->obitrate - mod->ibitrate; u64 d = mod->obitrate - mod->ibitrate;
@ -195,6 +195,48 @@ static int mod_calc_obitrate(struct ddb_mod *mod)
return 0; 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) static int mod_set_symbolrate(struct ddb_mod *mod, u32 srate)
{ {
struct ddb *dev = mod->port->dev; 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->symbolrate = srate;
mod_calc_obitrate(mod); mod_calc_obitrate(mod);
mod_set_stream(mod->port->output);
return 0; return 0;
} }
@ -227,6 +270,7 @@ static int mod_set_modulation(struct ddb_mod *mod,
ddbwritel(dev, qamtab[modulation], ddbwritel(dev, qamtab[modulation],
CHANNEL_SETTINGS(mod->port->nr)); CHANNEL_SETTINGS(mod->port->nr));
mod_calc_obitrate(mod); mod_calc_obitrate(mod);
mod_set_stream(mod->port->output);
return 0; return 0;
} }
@ -241,6 +285,7 @@ static int mod_set_frequency(struct ddb_mod *mod, u32 frequency)
if ((freq < 114) || (freq > 874)) if ((freq < 114) || (freq > 874))
return -EINVAL; return -EINVAL;
mod->frequency = frequency; mod->frequency = frequency;
mod_set_stream(mod->port->output);
return 0; return 0;
} }
@ -322,14 +367,27 @@ int ddbridge_mod_output_start(struct ddb_output *output)
CHANNEL_CONTROL(output->nr)); CHANNEL_CONTROL(output->nr));
udelay(10); udelay(10);
ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr)); ddbwritel(dev, mod->Control, CHANNEL_CONTROL(output->nr));
switch (dev->link[0].info->version) {
if (dev->link[0].info->version == 2) { case 2:
{
u32 Output = (mod->frequency - 114000000) / 8000000; u32 Output = (mod->frequency - 114000000) / 8000000;
u32 KF = Symbolrate; u32 KF = Symbolrate;
u32 LF = 9000000UL; u32 LF = 9000000UL;
u32 d = gcd(KF, LF); u32 d = gcd(KF, LF);
u32 checkLF; u32 checkLF;
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;
}
}
ddbwritel(dev, mod->modulation - 1, CHANNEL_SETTINGS(Channel)); ddbwritel(dev, mod->modulation - 1, CHANNEL_SETTINGS(Channel));
ddbwritel(dev, Output, CHANNEL_SETTINGS2(Channel)); ddbwritel(dev, Output, CHANNEL_SETTINGS2(Channel));
@ -356,16 +414,21 @@ int ddbridge_mod_output_start(struct ddb_output *output)
CHANNEL_CONTROL_CMD_SETUP)) CHANNEL_CONTROL_CMD_SETUP))
return -EINVAL; return -EINVAL;
mod->Control |= CHANNEL_CONTROL_ENABLE_DVB; mod->Control |= CHANNEL_CONTROL_ENABLE_DVB;
} else if (dev->link[0].info->version <= 1) { break;
}
case 0:
case 1:
/* QAM: 600 601 602 903 604 = 16 32 64 128 256 */ /* QAM: 600 601 602 903 604 = 16 32 64 128 256 */
/* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */ /* ddbwritel(dev, 0x604, CHANNEL_SETTINGS(output->nr)); */
ddbwritel(dev, qamtab[mod->modulation], ddbwritel(dev, qamtab[mod->modulation],
CHANNEL_SETTINGS(output->nr)); CHANNEL_SETTINGS(output->nr));
mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ | mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ |
CHANNEL_CONTROL_ENABLE_DVB); CHANNEL_CONTROL_ENABLE_DVB);
} else if (dev->link[0].info->version >= 16) { break;
default:
mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ | mod->Control |= (CHANNEL_CONTROL_ENABLE_IQ |
CHANNEL_CONTROL_ENABLE_DVB); CHANNEL_CONTROL_ENABLE_DVB);
break;
} }
if (dev->link[0].info->version < 16) { if (dev->link[0].info->version < 16) {
mod_set_rateinc(dev, output->nr); mod_set_rateinc(dev, output->nr);
@ -389,18 +452,20 @@ int ddbridge_mod_output_start(struct ddb_output *output)
static int mod_write_max2871(struct ddb *dev, u32 val) static int mod_write_max2871(struct ddb *dev, u32 val)
{ {
u32 retry = 100;
ddbwritel(dev, val, MAX2871_OUTDATA); ddbwritel(dev, val, MAX2871_OUTDATA);
ddbwritel(dev, MAX2871_CONTROL_CE | MAX2871_CONTROL_WRITE, ddbwritel(dev, MAX2871_CONTROL_CE | MAX2871_CONTROL_WRITE,
MAX2871_CONTROL); MAX2871_CONTROL);
while (1) { while (--retry) {
u32 ControlReg = ddbreadl(dev, MAX2871_CONTROL); u32 ControlReg = ddbreadl(dev, MAX2871_CONTROL);
if (ControlReg == 0xFFFFFFFF) if (ControlReg == 0xFFFFFFFF)
return -EIO;
if ((ControlReg & MAX2871_CONTROL_WRITE) == 0)
break; break;
} if ((ControlReg & MAX2871_CONTROL_WRITE) == 0)
return 0; return 0;
udelay(10);
}
return -EIO;
} }
static u32 max2871_fsm[6] = { static u32 max2871_fsm[6] = {
@ -511,10 +576,37 @@ static int mod_fsm_setup(struct ddb *dev, u32 MaxUsedChannels)
return status; 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) static int mod_set_vga(struct ddb *dev, u32 gain)
{ {
if (gain > 255) if (gain > 255)
return -EINVAL; return -EINVAL;
if (dev->link[0].ids.revision == 1) {
dev->mod_base.gain = gain;
return mod_set_power(dev);
}
ddbwritel(dev, gain, RF_VGA); ddbwritel(dev, gain, RF_VGA);
return 0; return 0;
} }
@ -622,6 +714,10 @@ static int mod_set_attenuator(struct ddb *dev, u32 Value)
{ {
if (Value > 31) if (Value > 31)
return -EINVAL; return -EINVAL;
if (dev->link[0].ids.revision == 1) {
dev->mod_base.attenuation = Value;
return mod_set_power(dev);
} else
ddbwritel(dev, Value, RF_ATTENUATOR); ddbwritel(dev, Value, RF_ATTENUATOR);
return 0; return 0;
} }
@ -1653,7 +1749,11 @@ static int mod_prop_proc(struct ddb_mod *mod, struct dtv_property *tvp)
return mod_set_attenuator(mod->port->dev, tvp->u.data); return mod_set_attenuator(mod->port->dev, tvp->u.data);
case MODULATOR_INPUT_BITRATE: case MODULATOR_INPUT_BITRATE:
#ifdef KERNEL_DVB_CORE
return mod_set_ibitrate(mod, *(u64 *) &tvp->u.buffer.data[0]);
#else
return mod_set_ibitrate(mod, tvp->u.data64); return mod_set_ibitrate(mod, tvp->u.data64);
#endif
case MODULATOR_GAIN: case MODULATOR_GAIN:
if (mod->port->dev->link[0].info->version == 2) if (mod->port->dev->link[0].info->version == 2)
@ -1709,10 +1809,16 @@ static int mod_prop_get(struct ddb_mod *mod, struct dtv_property *tvp)
return 0; return 0;
case MODULATOR_GAIN: case MODULATOR_GAIN:
if (dev->link[0].ids.revision == 1)
tvp->u.data = dev->mod_base.gain;
else
tvp->u.data = 0xff & ddbreadl(dev, RF_VGA); tvp->u.data = 0xff & ddbreadl(dev, RF_VGA);
return 0; return 0;
case MODULATOR_ATTENUATOR: case MODULATOR_ATTENUATOR:
if (dev->link[0].ids.revision == 1)
tvp->u.data = dev->mod_base.attenuation;
else
tvp->u.data = 0x1f & ddbreadl(dev, RF_ATTENUATOR); tvp->u.data = 0x1f & ddbreadl(dev, RF_ATTENUATOR);
return 0; return 0;
@ -1752,7 +1858,8 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
(struct dtv_properties __user *) parg; (struct dtv_properties __user *) parg;
int i, ret = 0; 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; return -EINVAL;
mutex_lock(&dev->ioctl_mutex); mutex_lock(&dev->ioctl_mutex);
switch (cmd) { switch (cmd) {
@ -1844,6 +1951,28 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
mod->pcr_correction = cp->pcr_correction; mod->pcr_correction = cp->pcr_correction;
break; break;
} }
case IOCTL_DDB_MCI_CMD:
{
struct ddb_mci_msg *msg =
(struct ddb_mci_msg __user *) parg;
struct ddb_link *link;
if (dev->link[0].ids.revision != 1) {
ret = -EINVAL;
break;
}
if (msg->link > 3) {
ret = -EFAULT;
break;
}
link = &dev->link[msg->link];
if (!link->mci_ok) {
ret = -EFAULT;
break;
}
ret = ddb_mci_cmd_link(link, &msg->cmd, &msg->res);
break;
}
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;
@ -1852,6 +1981,22 @@ int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg)
return ret; return ret;
} }
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];
}
return 0;
}
static int mod_init_2(struct ddb *dev, u32 Frequency) static int mod_init_2(struct ddb *dev, u32 Frequency)
{ {
int i, status, streams = dev->link[0].info->port_num; int i, status, streams = dev->link[0].info->port_num;
@ -1863,8 +2008,6 @@ static int mod_init_2(struct ddb *dev, u32 Frequency)
dev_err(dev->dev, "FSM setup failed!\n"); dev_err(dev->dev, "FSM setup failed!\n");
return -1; return -1;
} }
if (dev->link[0].ids.revision == 1)
return 0;
for (i = 0; i < streams; i++) { for (i = 0; i < streams; i++) {
struct ddb_mod *mod = &dev->mod[i]; struct ddb_mod *mod = &dev->mod[i];
@ -2014,7 +2157,6 @@ static int mod_init_3(struct ddb *dev, u32 Frequency)
return ret; return ret;
} }
static int mod_init_sdr_iq(struct ddb *dev) static int mod_init_sdr_iq(struct ddb *dev)
{ {
int streams = dev->link[0].info->port_num; int streams = dev->link[0].info->port_num;
@ -2031,55 +2173,53 @@ static int mod_init_sdr_iq(struct ddb *dev)
ddbwritel(dev, 0x01, 0x240); ddbwritel(dev, 0x01, 0x240);
if (dev->link[0].ids.revision == 1)
return 0;
//mod3_set_base_frequency(dev, 602000000); //mod3_set_base_frequency(dev, 602000000);
dev->mod_base.frequency = 570000000; dev->mod_base.frequency = 570000000;
for (i = 0; i < streams; i++) { for (i = 0; i < streams; i++) {
struct ddb_mod *mod = &dev->mod[i]; struct ddb_mod *mod = &dev->mod[i];
mod->port = &dev->port[i]; mod->port = &dev->port[i];
if (dev->link[0].ids.revision != 1)
ddbwritel(dev, 0x00, SDR_CHANNEL_CONTROL(i)); ddbwritel(dev, 0x00, SDR_CHANNEL_CONTROL(i));
} }
if (dev->link[0].ids.revision == 1)
return ret;
mod_set_sdr_attenuator(dev, 0); mod_set_sdr_attenuator(dev, 0);
udelay(10); udelay(10);
mod_set_sdr_gain(dev, 120); mod_set_sdr_gain(dev, 120);
ddb_mci_cmd_link_simple(&dev->link[0], 0xc0, 0x00, 90);
return ret; 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) int ddbridge_mod_init(struct ddb *dev)
{ {
dev_info(dev->dev, "Revision: %u\n", dev->link[0].ids.revision); dev_info(dev->dev, "Revision: %u\n", dev->link[0].ids.revision);
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.revision == 1) {
switch (dev->link[0].info->version) { if ((dev->link[0].ids.hwid & 0xffffff) >= 9065)
case 0: return mod_init_2_1(dev, 114000000);
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 */
return mod_init_2(dev, 114000000); return mod_init_2(dev, 114000000);
case 16: /* PAL */ case 16: /* PAL */
return mod_init_3(dev, 503250000); return mod_init_3(dev, 503250000);
case 17: /* raw IQ */ case 17: /* raw IQ */
return mod_init_sdr_iq(dev); return mod_init_sdr_iq(dev);
case 18: /* IQ+FFT */ case 18: /* IQ+FFT (DVB-T) */
return mod_init_sdr_iq(dev); return mod_init_dvbt(dev);
default: default:
return -1; return -1;
} }

View File

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

View File

@ -23,7 +23,6 @@
#include "ddbridge.h" #include "ddbridge.h"
#include "ddbridge-io.h" #include "ddbridge-io.h"
#include "ddbridge-i2c.h"
#include "ddbridge-mci.h" #include "ddbridge-mci.h"
static int default_mod = 3; static int default_mod = 3;
@ -34,6 +33,14 @@ static int direct_mode;
module_param(direct_mode, int, 0444); module_param(direct_mode, int, 0444);
MODULE_PARM_DESC(direct_mode, "Ignore LDPC limits and assign high speed demods according to needed symbolrate."); MODULE_PARM_DESC(direct_mode, "Ignore LDPC limits and assign high speed demods according to needed symbolrate.");
static u32 sx8_tuner_flags;
module_param(sx8_tuner_flags, int, 0664);
MODULE_PARM_DESC(sx8_tuner_flags, "Change SX8 tuner flags.");
static u32 sx8_tuner_gain;
module_param(sx8_tuner_gain, int, 0664);
MODULE_PARM_DESC(sx8_tuner_gain, "Change SX8 tuner gain.");
static const u32 MCLK = (1550000000 / 12); static const u32 MCLK = (1550000000 / 12);
/* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */ /* Add 2MBit/s overhead allowance (minimum factor is 90/32400 for QPSK w/o Pilots) */
@ -110,6 +117,9 @@ static void release(struct dvb_frontend *fe)
kfree(mci_base); kfree(mci_base);
} }
kfree(state); kfree(state);
#ifdef CONFIG_MEDIA_ATTACH
__module_get(THIS_MODULE);
#endif
} }
static int ddb_mci_tsconfig(struct mci *state, u32 config) static int ddb_mci_tsconfig(struct mci *state, u32 config)
@ -142,6 +152,7 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
if (stat) if (stat)
goto unlock; goto unlock;
if (res.status == MCI_DEMOD_LOCKED || res.status == SX8_DEMOD_IQ_MODE) { 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 | *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI |
FE_HAS_CARRIER | FE_HAS_SIGNAL; FE_HAS_CARRIER | FE_HAS_SIGNAL;
if (res.status == MCI_DEMOD_LOCKED) { if (res.status == MCI_DEMOD_LOCKED) {
@ -161,8 +172,12 @@ static int read_status(struct dvb_frontend *fe, enum fe_status *status)
} }
} else if (res.status == MCI_DEMOD_TIMEOUT) } else if (res.status == MCI_DEMOD_TIMEOUT)
*status = FE_TIMEDOUT; *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; *status = FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
if (sx8_base->iq_mode)
*status |= FE_HAS_LOCK;
}
unlock: unlock:
mutex_unlock(&state->lock); mutex_unlock(&state->lock);
return stat; return stat;
@ -252,6 +267,11 @@ static int stop(struct dvb_frontend *fe)
return 0; return 0;
} }
static const u8 ro_lut[8] = {
8 | SX8_ROLLOFF_35, 8 | SX8_ROLLOFF_20, 8 | SX8_ROLLOFF_25, 0,
8 | SX8_ROLLOFF_15, 8 | SX8_ROLLOFF_10, 8 | SX8_ROLLOFF_05, 0,
};
static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config) static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
{ {
struct sx8 *state = fe->demodulator_priv; struct sx8 *state = fe->demodulator_priv;
@ -266,10 +286,6 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
u32 bits_per_symbol = 0; u32 bits_per_symbol = 0;
int i = -1, stat = 0; int i = -1, stat = 0;
struct ddb_link *link = state->mci.base->link; struct ddb_link *link = state->mci.base->link;
const u8 ro_lut[8] = {
8 | SX8_ROLLOFF_35, 8 | SX8_ROLLOFF_20, 8 | SX8_ROLLOFF_25, 0,
8 | SX8_ROLLOFF_15, 8 | SX8_ROLLOFF_10, 8 | SX8_ROLLOFF_05, 0,
};
if (link->ids.device == 0x000b) { if (link->ids.device == 0x000b) {
/* Mask out higher modulations and MIS for Basic /* Mask out higher modulations and MIS for Basic
@ -345,7 +361,7 @@ static int start(struct dvb_frontend *fe, u32 flags, u32 modmask, u32 ts_config)
state->mci.demod = i; state->mci.demod = i;
if (!sx8_base->tuner_use_count[input]) if (!sx8_base->tuner_use_count[input])
mci_set_tuner(fe, input, 1, 0, 0); mci_set_tuner(fe, input, 1, sx8_tuner_flags, sx8_tuner_gain);
sx8_base->tuner_use_count[input]++; sx8_base->tuner_use_count[input]++;
sx8_base->iq_mode = (ts_config > 1); sx8_base->iq_mode = (ts_config > 1);
unlock: unlock:
@ -374,6 +390,8 @@ unlock:
cmd.dvbs2_search.s2_modulation_mask = modmask; cmd.dvbs2_search.s2_modulation_mask = modmask;
cmd.dvbs2_search.rsvd1 = ro_lut[p->rolloff & 7]; cmd.dvbs2_search.rsvd1 = ro_lut[p->rolloff & 7];
cmd.dvbs2_search.retry = 2; 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.frequency = p->frequency * 1000;
cmd.dvbs2_search.symbol_rate = p->symbol_rate; cmd.dvbs2_search.symbol_rate = p->symbol_rate;
cmd.dvbs2_search.scrambling_sequence_index = cmd.dvbs2_search.scrambling_sequence_index =
@ -396,7 +414,7 @@ unlock:
static int start_iq(struct dvb_frontend *fe, u32 flags, static int start_iq(struct dvb_frontend *fe, u32 flags,
u32 roll_off, u32 ts_config) u32 ts_config)
{ {
struct sx8 *state = fe->demodulator_priv; struct sx8 *state = fe->demodulator_priv;
struct mci_base *mci_base = state->mci.base; struct mci_base *mci_base = state->mci.base;
@ -423,6 +441,7 @@ static int start_iq(struct dvb_frontend *fe, u32 flags,
state->mci.demod = 0; state->mci.demod = 0;
sx8_base->tuner_use_count[input]++; sx8_base->tuner_use_count[input]++;
sx8_base->iq_mode = 2; sx8_base->iq_mode = 2;
mci_set_tuner(fe, input, 1, flags & 0xff, 0x40);
} else { } else {
if ((state->iq_started & 0x07) != state->mci.nr) { if ((state->iq_started & 0x07) != state->mci.nr) {
stat = -EBUSY; stat = -EBUSY;
@ -433,11 +452,11 @@ unlock:
mutex_unlock(&mci_base->tuner_lock); mutex_unlock(&mci_base->tuner_lock);
if (stat) if (stat)
return stat; return stat;
mci_set_tuner(fe, input, 1, flags & 0xff, 0);
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.command = SX8_CMD_START_IQ; cmd.command = SX8_CMD_START_IQ;
cmd.sx8_start_iq.flags = (flags >> 16) & 0xff; cmd.sx8_start_iq.flags = (flags >> 16) & 0xff;
cmd.sx8_start_iq.roll_off = roll_off; cmd.sx8_start_iq.roll_off = 5;
//cmd.sx8_start_iq.roll_off = ro_lut[p->rolloff & 7];
cmd.sx8_start_iq.frequency = p->frequency * 1000; cmd.sx8_start_iq.frequency = p->frequency * 1000;
cmd.sx8_start_iq.symbol_rate = p->symbol_rate; cmd.sx8_start_iq.symbol_rate = p->symbol_rate;
cmd.sx8_start_iq.gain = (flags >> 8) & 0xff; cmd.sx8_start_iq.gain = (flags >> 8) & 0xff;
@ -482,18 +501,21 @@ static int set_parameters(struct dvb_frontend *fe)
stop_iq(fe); stop_iq(fe);
switch (p->modulation) { switch (p->modulation) {
case APSK_256: case APSK_256:
case APSK_256_L:
mask = 0x7f; mask = 0x7f;
break; break;
case APSK_128: case APSK_128:
mask = 0x3f; mask = 0x3f;
break; break;
case APSK_64: case APSK_64:
case APSK_64_L:
mask = 0x1f; mask = 0x1f;
break; break;
case APSK_32: case APSK_32:
mask = 0x0f; mask = 0x0f;
break; break;
case APSK_16: case APSK_16:
case APSK_16_L:
mask = 0x07; mask = 0x07;
break; break;
default: default:
@ -502,7 +524,7 @@ static int set_parameters(struct dvb_frontend *fe)
} }
stat = start(fe, 3, mask, ts_config); stat = start(fe, 3, mask, ts_config);
} else { } else {
stat = start_iq(fe, isi & 0xffffff, 4, ts_config); stat = start_iq(fe, isi & 0xffffff, ts_config);
} }
mutex_unlock(&state->lock); mutex_unlock(&state->lock);
return stat; return stat;
@ -537,7 +559,9 @@ static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
static int set_input(struct dvb_frontend *fe, int input) static int set_input(struct dvb_frontend *fe, int input)
{ {
struct sx8 *state = fe->demodulator_priv; struct sx8 *state = fe->demodulator_priv;
#ifndef KERNEL_DVB_CORE
struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct dtv_frontend_properties *p = &fe->dtv_property_cache;
#endif
if (input >= SX8_TUNER_NUM) if (input >= SX8_TUNER_NUM)
return -EINVAL; return -EINVAL;
@ -546,7 +570,10 @@ static int set_input(struct dvb_frontend *fe, int input)
mutex_lock(&state->lock); mutex_lock(&state->lock);
stop_iq(fe); stop_iq(fe);
stop(fe); stop(fe);
state->mci.tuner = p->input = input; state->mci.tuner = input;
#ifndef KERNEL_DVB_CORE
p->input = input;
#endif
mutex_unlock(&state->lock); mutex_unlock(&state->lock);
return 0; return 0;
} }
@ -572,7 +599,6 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
static struct dvb_frontend_ops sx8_ops = { static struct dvb_frontend_ops sx8_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2 }, .delsys = { SYS_DVBS, SYS_DVBS2 },
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.info = { .info = {
.name = "DVB-S/S2X", .name = "DVB-S/S2X",
.frequency_min_hz = 950000000, .frequency_min_hz = 950000000,
@ -592,7 +618,10 @@ static struct dvb_frontend_ops sx8_ops = {
.tune = tune, .tune = tune,
.release = release, .release = release,
.read_status = read_status, .read_status = read_status,
#ifndef KERNEL_DVB_CORE
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.set_input = set_input, .set_input = set_input,
#endif
.set_lna = set_lna, .set_lna = set_lna,
.sleep = sleep, .sleep = sleep,
}; };
@ -602,8 +631,10 @@ static int init(struct mci *mci)
struct sx8 *state = (struct sx8 *) mci; struct sx8 *state = (struct sx8 *) mci;
state->mci.demod = SX8_DEMOD_NONE; state->mci.demod = SX8_DEMOD_NONE;
#ifndef KERNEL_DVB_CORE
mci->fe.ops.xbar[1] = mci->nr; mci->fe.ops.xbar[1] = mci->nr;
mci->fe.dtv_property_cache.input = mci->tuner; mci->fe.dtv_property_cache.input = mci->tuner;
#endif
mutex_init(&state->lock); mutex_init(&state->lock);
return 0; return 0;
} }
@ -615,7 +646,7 @@ static int base_init(struct mci_base *mci_base)
return 0; return 0;
} }
struct mci_cfg ddb_max_sx8_cfg = { static struct mci_cfg ddb_max_sx8_cfg = {
.type = 0, .type = 0,
.fe_ops = &sx8_ops, .fe_ops = &sx8_ops,
.base_size = sizeof(struct sx8_base), .base_size = sizeof(struct sx8_base),
@ -623,3 +654,10 @@ struct mci_cfg ddb_max_sx8_cfg = {
.init = init, .init = init,
.base_init = base_init, .base_init = base_init,
}; };
struct dvb_frontend *ddb_sx8_attach(struct ddb_input *input, int nr, int tuner,
int (**fn_set_input)(struct dvb_frontend *fe, int input))
{
*fn_set_input = set_input;
return ddb_mci_attach(input, &ddb_max_sx8_cfg, nr, tuner);
}

View File

@ -23,9 +23,6 @@
#ifndef _DDBRIDGE_H_ #ifndef _DDBRIDGE_H_
#define _DDBRIDGE_H_ #define _DDBRIDGE_H_
/* #define DDB_USE_WORK */
/*#define DDB_TEST_THREADED*/
#include <linux/version.h> #include <linux/version.h>
#if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE) #if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE)
@ -150,13 +147,10 @@ struct ddb_info {
u32 type; u32 type;
#define DDB_NONE 0 #define DDB_NONE 0
#define DDB_OCTOPUS 1 #define DDB_OCTOPUS 1
#define DDB_OCTOPUS_CI 2
#define DDB_MOD 3 #define DDB_MOD 3
#define DDB_OCTONET 4 #define DDB_OCTONET 4
#define DDB_OCTOPUS_MAX 5 #define DDB_OCTOPUS_MAX 5
#define DDB_OCTOPUS_MAX_CT 6 #define DDB_OCTOPUS_MAX_CT 6
#define DDB_OCTOPRO 7
#define DDB_OCTOPRO_HDIN 8
#define DDB_OCTOPUS_MCI 9 #define DDB_OCTOPUS_MCI 9
u32 version; u32 version;
char *name; char *name;
@ -178,11 +172,14 @@ struct ddb_info {
#define TS_QUIRK_ALT_OSC 8 #define TS_QUIRK_ALT_OSC 8
u8 mci_ports; u8 mci_ports;
u8 mci_type; u8 mci_type;
u8 ci_mask;
u32 tempmon_irq; u32 tempmon_irq;
u32 lostlock_irq; u32 lostlock_irq;
u32 mdio_base; u32 mdio_base;
u32 hw_min; u32 hw_min;
u32 ci_base;
u32 lnb_base;
const struct ddb_regmap *regmap; const struct ddb_regmap *regmap;
}; };
@ -205,11 +202,8 @@ struct ddb_dma {
u32 div; u32 div;
u32 bufval; u32 bufval;
#ifdef DDB_USE_WORK
struct work_struct work; struct work_struct work;
#else
struct tasklet_struct tasklet; struct tasklet_struct tasklet;
#endif
spinlock_t lock; /* DMA lock */ spinlock_t lock; /* DMA lock */
wait_queue_head_t wq; wait_queue_head_t wq;
int running; int running;
@ -254,6 +248,7 @@ struct ddb_ci {
struct dvb_ca_en50221 en; struct dvb_ca_en50221 en;
struct ddb_port *port; struct ddb_port *port;
u32 nr; u32 nr;
u32 regs;
}; };
struct ddb_io { struct ddb_io {
@ -327,6 +322,10 @@ struct ddb_port {
#define DDB_TUNER_MCI 48 #define DDB_TUNER_MCI 48
#define DDB_TUNER_MCI_SX8 (DDB_TUNER_MCI + 0) #define DDB_TUNER_MCI_SX8 (DDB_TUNER_MCI + 0)
#define DDB_TUNER_MCI_M4 (DDB_TUNER_MCI + 1) #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_input *input[2];
struct ddb_output *output; struct ddb_output *output;
@ -341,6 +340,8 @@ struct mod_base {
u32 frequency; u32 frequency;
u32 flat_start; u32 flat_start;
u32 flat_end; u32 flat_end;
u32 attenuation;
u32 gain;
}; };
struct ddb_mod { struct ddb_mod {
@ -424,7 +425,6 @@ struct ddb_link {
spinlock_t lock; /* lock link access */ spinlock_t lock; /* lock link access */
struct mutex flash_mutex; /* lock flash access */ struct mutex flash_mutex; /* lock flash access */
struct ddb_lnb lnb; struct ddb_lnb lnb;
struct tasklet_struct tasklet;
struct ddb_ids ids; struct ddb_ids ids;
spinlock_t temp_lock; /* lock temp chip access */ spinlock_t temp_lock; /* lock temp chip access */
@ -537,7 +537,7 @@ struct DDMOD_FLASH {
int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len); 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 */ /* linked function prototypes */
@ -581,5 +581,10 @@ struct ddb_irq *ddb_irq_set(struct ddb *dev, u32 link, u32 nr,
void (*handler)(void *), void *data); 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_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 #endif

View File

@ -26,6 +26,9 @@
#include <linux/net.h> #include <linux/net.h>
#include "dvb_netstream.h" #include "dvb_netstream.h"
int ddb_dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
int (*func)(struct file *file, unsigned int cmd, void *arg));
static ssize_t ns_write(struct file *file, const char *buf, static ssize_t ns_write(struct file *file, const char *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
@ -211,7 +214,7 @@ static int do_ioctl(struct file *file, unsigned int cmd, void *parg)
static long ns_ioctl(struct file *file, static long ns_ioctl(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
return dvb_usercopy(file, cmd, arg, do_ioctl); return ddb_dvb_usercopy(file, cmd, arg, do_ioctl);
} }
static const struct file_operations ns_fops = { static const struct file_operations ns_fops = {

View File

@ -36,7 +36,7 @@
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/in.h> #include <linux/in.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/dvb/ns.h> #include "ns.h"
#include <media/dvbdev.h> #include <media/dvbdev.h>

76
ddbridge/ns.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef _UAPI_DVBNS_H_
#define _UAPI_DVBNS_H_
#include <linux/types.h>
struct dvb_ns_params {
__u8 smac[6];
__u8 dmac[6];
__u8 sip[16];
__u8 dip[16];
__u16 sport;
__u16 dport;
__u16 sport2;
__u16 dport2;
__u8 ssrc[8];
__u8 flags;
__u8 qos;
__u16 vlan;
__u8 ttl;
};
#define DVB_NS_IPV6 0x01
#define DVB_NS_RTP 0x02
#define DVB_NS_RTCP 0x04
#define DVB_NS_RTP_TO 0x08
#define DVB_NS_VLAN 0x10
struct dvb_ns_rtcp {
__u8 *msg;
__u16 len;
};
struct dvb_ns_packet {
__u8 *buf;
__u8 count;
};
struct dvb_nsd_ts {
__u16 pid;
__u16 num;
__u16 input;
__u16 timeout;
__u16 len;
__u8 *ts;
__u8 mode;
__u8 table;
__u8 filter_mask;
__u8 section;
__u16 section_id;
};
struct dvb_ns_cap {
__u8 streams_max;
__u8 reserved[127];
};
#define NS_SET_NET _IOW('o', 192, struct dvb_ns_params)
#define NS_START _IO('o', 193)
#define NS_STOP _IO('o', 194)
#define NS_SET_PID _IOW('o', 195, __u16)
#define NS_SET_PIDS _IOW('o', 196, __u8 *)
#define NS_SET_RTCP_MSG _IOW('o', 197, struct dvb_ns_rtcp)
#define NSD_START_GET_TS _IOWR('o', 198, struct dvb_nsd_ts)
#define NSD_STOP_GET_TS _IOWR('o', 199, struct dvb_nsd_ts)
#define NSD_CANCEL_GET_TS _IO('o', 200)
#define NSD_POLL_GET_TS _IOWR('o', 201, struct dvb_nsd_ts)
#define NS_SET_PACKETS _IOW('o', 202, struct dvb_ns_packet)
#define NS_INSERT_PACKETS _IOW('o', 203, __u8)
#define NS_SET_CI _IOW('o', 204, __u8)
#define NS_GET_CAP _IOR('o', 204, struct dvb_ns_cap))
#endif /*_UAPI_DVBNS_H_*/

View File

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

View File

@ -7,7 +7,21 @@ API:
Currently DTV_STREAM_ID is misused. Currently DTV_STREAM_ID is misused.
0x10000000 - symbols (locked and tracked) at symbol rate 0x10000000 - symbols (locked and tracked) at symbol rate
0x20000000 - samples at ADC rate (1550/24=64.583... MHz) 0x20000000 - samples at symbol rate
0x30000000 - samples at symbol rate (fixed at ADC rate (1550/24=64.583... MHz) if 0x00010000 is set)
Max. sample rate is 64.583333 MHz.
Max. sample rate is 64.583333 MHz. 0x00xx0000 - flags
Bit 0 : 0 = VTM/SDR, 1 = SCAN,
Bit 1: 1 = Disable channel AGC,
Bit 2: 1 = Set Gain.
0x0000xx00 - xx=gain
0x000000xx - xx=flags
Bit 0:1 Preamp Mode; 0 = Preamp AGC, 1 == Minimum (~ -17dB) ,
2 = Medium, 3 = Maximum gain {~ 15dB}
Bit 2: Bypass Input LNA (6 dB less gain) (Note this is after Preamp)
Bit 4: Set RF Gain
Bit 5: Freeze RF Gain (Turn AGC off at current gain, only when already enabled)
Bit 7: Optimize RF Gain and freeze for FFT

View File

@ -83,6 +83,7 @@ limit depends on # of channels active.
MODULATOR_INPUT_BITRATE: MODULATOR_INPUT_BITRATE:
THIS FEATURE ONLY WORKS FOR DVB-C MODULATORS
The modulator will ALWAY insert null packets if it The modulator will ALWAY insert null packets if it
does not get enough data. does not get enough data.
@ -94,6 +95,21 @@ So, this property should be set last.
unit - 2^-32 Hz 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: 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

@ -28,3 +28,7 @@ devices in any way.
adapter_alloc=3 is rcommended when using redirect adapter_alloc=3 is rcommended when using redirect
The ci device will then show up in the same adapter directory and most The ci device will then show up in the same adapter directory and most
software will then assume it belongs to the frontend in the same directory. software will then assume it belongs to the frontend in the same directory.
Redirect between cards in different IOMMU groups will not work!
Disable IOMMU if you have this problem.

View File

@ -6,7 +6,7 @@
config DVB_MMAP config DVB_MMAP
bool "Enable DVB memory-mapped API (EXPERIMENTAL)" bool "Enable DVB memory-mapped API (EXPERIMENTAL)"
depends on DVB_CORE 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 select VIDEOBUF2_VMALLOC
help help
This option enables DVB experimental memory-mapped API, which This option enables DVB experimental memory-mapped API, which

View File

@ -13,4 +13,3 @@ dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o \
obj-$(CONFIG_DVB_CORE) += dvb-core.o obj-$(CONFIG_DVB_CORE) += dvb-core.o
EXTRA_CFLAGS += -DCONFIG_DVB_DYNAMIC_MINORS -DCONFIG_DVB_NET EXTRA_CFLAGS += -DCONFIG_DVB_DYNAMIC_MINORS -DCONFIG_DVB_NET
#NOSTDINC_FLAGS += -I$(KBUILD_EXTMOD)/include -I$(KBUILD_EXTMOD)/include/linux

View File

@ -4,10 +4,11 @@
dvb-net-$(CONFIG_DVB_NET) := dvb_net.o 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_ca_en50221.o dvb_frontend.o \
$(dvb-net-y) dvb_ringbuffer.o dvb_math.o $(dvb-net-y) dvb_ringbuffer.o dvb_math.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o obj-$(CONFIG_DVB_CORE) += dvb-core.o
ccflags-y += -Idrivers/media/dvb-core/ ccflags-y += -Idrivers/media/dvb-core/
ccflags-y += --include=dd_compat.h

View File

@ -1,19 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/* /*
* dmxdev.c - DVB demultiplexer device * dmxdev.c - DVB demultiplexer device
* *
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH * 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 #define pr_fmt(fmt) "dmxdev: " fmt
@ -415,6 +405,7 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
} }
} }
#endif #endif
static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len, const u8 *buffer2, size_t buffer2_len,
struct dmx_section_filter *filter, struct dmx_section_filter *filter,
@ -480,6 +471,9 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
{ {
struct dmxdev_filter *dmxdevfilter = feed->priv; struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer; struct dvb_ringbuffer *buffer;
#ifdef CONFIG_DVB_MMAP
struct dvb_vb2_ctx *ctx;
#endif
int ret; int ret;
spin_lock(&dmxdevfilter->dev->lock); spin_lock(&dmxdevfilter->dev->lock);
@ -766,7 +760,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
ret = dmxdev->demux->allocate_section_feed(dmxdev->demux, ret = dmxdev->demux->allocate_section_feed(dmxdev->demux,
secfeed, secfeed,
dvb_dmxdev_section_callback); dvb_dmxdev_section_callback);
if (ret < 0) { if (!*secfeed) {
pr_err("DVB (%s): could not alloc feed\n", pr_err("DVB (%s): could not alloc feed\n",
__func__); __func__);
return ret; return ret;
@ -846,6 +840,11 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
if (mutex_lock_interruptible(&dmxdev->mutex)) if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS; return -ERESTARTSYS;
if (dmxdev->exit) {
mutex_unlock(&dmxdev->mutex);
return -ENODEV;
}
for (i = 0; i < dmxdev->filternum; i++) for (i = 0; i < dmxdev->filternum; i++)
if (dmxdev->filter[i].state == DMXDEV_STATE_FREE) if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
break; 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 dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
{ {
int i; int i, ret;
if (dmxdev->demux->open(dmxdev->demux) < 0) if (dmxdev->demux->open(dmxdev->demux) < 0)
return -EUSERS; return -EUSERS;
@ -1505,21 +1504,36 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
DMXDEV_STATE_FREE); 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_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); dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
if (ret < 0)
goto err_register_dvr_dvbdev;
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
return 0; 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); EXPORT_SYMBOL(dvb_dmxdev_init);
void dvb_dmxdev_release(struct dmxdev *dmxdev) void dvb_dmxdev_release(struct dmxdev *dmxdev)
{ {
mutex_lock(&dmxdev->mutex);
dmxdev->exit = 1; dmxdev->exit = 1;
mutex_unlock(&dmxdev->mutex);
if (dmxdev->dvbdev->users > 1) { if (dmxdev->dvbdev->users > 1) {
wait_event(dmxdev->dvbdev->wait_queue, wait_event(dmxdev->dvbdev->wait_queue,
dmxdev->dvbdev->users == 1); 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 * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces
* *
@ -158,13 +158,19 @@ struct dvb_ca_private {
/* mutex serializing ioctls */ /* mutex serializing ioctls */
struct mutex ioctl_mutex; 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) static void dvb_ca_private_free(struct dvb_ca_private *ca)
{ {
unsigned int i; unsigned int i;
dvb_free_device(ca->dvbdev); dvb_device_put(ca->dvbdev);
for (i = 0; i < ca->slot_count; i++) for (i = 0; i < ca->slot_count; i++)
vfree(ca->slot_info[i].rx_buffer.data); vfree(ca->slot_info[i].rx_buffer.data);
@ -194,10 +200,10 @@ 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, static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
u8 *ebuf, int ecount); u8 *ebuf, int ecount);
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
u8 *ebuf, int ecount); u8 *ebuf, int ecount, int size_write_flag);
/** /**
* Safely find needle in haystack. * findstr - Safely find needle in haystack.
* *
* @haystack: Buffer to look in. * @haystack: Buffer to look in.
* @hlen: Number of bytes in haystack. * @hlen: Number of bytes in haystack.
@ -377,7 +383,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10); ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10);
if (ret) if (ret)
return ret; return ret;
ret = dvb_ca_en50221_write_data(ca, slot, buf, 2); ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW);
if (ret != 2) if (ret != 2)
return -EIO; return -EIO;
ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN); ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
@ -785,18 +791,19 @@ exit:
* @buf: The data in this buffer is treated as a complete link-level packet to * @buf: The data in this buffer is treated as a complete link-level packet to
* be written. * be written.
* @bytes_write: Size of ebuf. * @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. * return: Number of bytes written, or < 0 on error.
*/ */
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
u8 *buf, int bytes_write) u8 *buf, int bytes_write, int size_write_flag)
{ {
struct dvb_ca_slot *sl = &ca->slot_info[slot]; struct dvb_ca_slot *sl = &ca->slot_info[slot];
int status; int status;
int i; int i;
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
/* sanity check */ /* sanity check */
if (bytes_write > sl->link_buf_size) if (bytes_write > sl->link_buf_size)
return -EINVAL; return -EINVAL;
@ -824,7 +831,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
/* OK, set HC bit */ /* OK, set HC bit */
status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
IRQEN | CMDREG_HC); IRQEN | CMDREG_HC | size_write_flag);
if (status) if (status)
goto exit; goto exit;
@ -1013,7 +1020,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
/* EN50221 thread functions */ /* EN50221 thread functions */
/** /**
* Wake up the DVB CA thread * dvb_ca_en50221_thread_wakeup - Wake up the DVB CA thread
* *
* @ca: CA instance. * @ca: CA instance.
*/ */
@ -1027,7 +1034,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
} }
/** /**
* Update the delay used by the thread. * dvb_ca_en50221_thread_update_delay - Update the delay used by the thread.
* *
* @ca: CA instance. * @ca: CA instance.
*/ */
@ -1085,7 +1092,7 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
} }
/** /**
* Poll if the CAM is gone. * dvb_ca_en50221_poll_cam_gone - Poll if the CAM is gone.
* *
* @ca: CA instance. * @ca: CA instance.
* @slot: Slot to process. * @slot: Slot to process.
@ -1116,7 +1123,8 @@ static int dvb_ca_en50221_poll_cam_gone(struct dvb_ca_private *ca, int slot)
} }
/** /**
* Thread state machine for one CA slot to perform the data transfer. * dvb_ca_en50221_thread_state_machine - Thread state machine for one CA slot
* to perform the data transfer.
* *
* @ca: CA instance. * @ca: CA instance.
* @slot: Slot to process. * @slot: Slot to process.
@ -1347,13 +1355,14 @@ static int dvb_ca_en50221_thread(void *data)
/* EN50221 IO interface functions */ /* EN50221 IO interface functions */
/** /**
* Real ioctl implementation. * dvb_ca_en50221_io_do_ioctl - Real ioctl implementation.
* NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them.
* *
* @file: File concerned. * @file: File concerned.
* @cmd: IOCTL command. * @cmd: IOCTL command.
* @parg: Associated argument. * @parg: Associated argument.
* *
* NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them.
*
* return: 0 on success, <0 on error. * return: 0 on success, <0 on error.
*/ */
static int dvb_ca_en50221_io_do_ioctl(struct file *file, static int dvb_ca_en50221_io_do_ioctl(struct file *file,
@ -1407,6 +1416,9 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file,
err = -EINVAL; err = -EINVAL;
goto out_unlock; goto out_unlock;
} }
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
slot = array_index_nospec(slot, ca->slot_count);
#endif
info->type = CA_CI_LINK; info->type = CA_CI_LINK;
info->flags = 0; info->flags = 0;
@ -1431,7 +1443,7 @@ out_unlock:
} }
/** /**
* Wrapper for ioctl implementation. * dvb_ca_en50221_io_ioctl - Wrapper for ioctl implementation.
* *
* @file: File concerned. * @file: File concerned.
* @cmd: IOCTL command. * @cmd: IOCTL command.
@ -1446,7 +1458,7 @@ static long dvb_ca_en50221_io_ioctl(struct file *file,
} }
/** /**
* Implementation of write() syscall. * dvb_ca_en50221_io_write - Implementation of write() syscall.
* *
* @file: File structure. * @file: File structure.
* @buf: Source buffer. * @buf: Source buffer.
@ -1486,6 +1498,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
return -EFAULT; return -EFAULT;
buf += 2; buf += 2;
count -= 2; count -= 2;
if (slot >= ca->slot_count) if (slot >= ca->slot_count)
return -EINVAL; return -EINVAL;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
@ -1529,7 +1542,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
mutex_lock(&sl->slot_lock); mutex_lock(&sl->slot_lock);
status = dvb_ca_en50221_write_data(ca, slot, fragbuf, status = dvb_ca_en50221_write_data(ca, slot, fragbuf,
fraglen + 2); fraglen + 2, 0);
mutex_unlock(&sl->slot_lock); mutex_unlock(&sl->slot_lock);
if (status == (fraglen + 2)) { if (status == (fraglen + 2)) {
written = 1; written = 1;
@ -1603,7 +1616,7 @@ nextslot:
} }
/** /**
* Implementation of read() syscall. * dvb_ca_en50221_io_read - Implementation of read() syscall.
* *
* @file: File structure. * @file: File structure.
* @buf: Destination buffer. * @buf: Destination buffer.
@ -1714,7 +1727,7 @@ exit:
} }
/** /**
* Implementation of file open syscall. * dvb_ca_en50221_io_open - Implementation of file open syscall.
* *
* @inode: Inode concerned. * @inode: Inode concerned.
* @file: File concerned. * @file: File concerned.
@ -1730,12 +1743,22 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
dprintk("%s\n", __func__); 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; return -EIO;
}
err = dvb_generic_open(inode, file); err = dvb_generic_open(inode, file);
if (err < 0) { if (err < 0) {
module_put(ca->pub->owner); module_put(ca->pub->owner);
mutex_unlock(&ca->remove_mutex);
return err; return err;
} }
@ -1760,11 +1783,12 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
dvb_ca_private_get(ca); dvb_ca_private_get(ca);
mutex_unlock(&ca->remove_mutex);
return 0; return 0;
} }
/** /**
* Implementation of file close syscall. * dvb_ca_en50221_io_release - Implementation of file close syscall.
* *
* @inode: Inode concerned. * @inode: Inode concerned.
* @file: File concerned. * @file: File concerned.
@ -1779,6 +1803,8 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
mutex_lock(&ca->remove_mutex);
/* mark the CA device as closed */ /* mark the CA device as closed */
ca->open = 0; ca->open = 0;
dvb_ca_en50221_thread_update_delay(ca); dvb_ca_en50221_thread_update_delay(ca);
@ -1789,11 +1815,18 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
dvb_ca_private_put(ca); 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; return err;
} }
/** /**
* Implementation of poll() syscall. * dvb_ca_en50221_io_poll - Implementation of poll() syscall.
* *
* @file: File concerned. * @file: File concerned.
* @wait: poll wait table. * @wait: poll wait table.
@ -1855,7 +1888,7 @@ static const struct dvb_device dvbdev_ca = {
/* Initialisation/shutdown functions */ /* Initialisation/shutdown functions */
/** /**
* Initialise a new DVB CA EN50221 interface device. * dvb_ca_en50221_init - Initialise a new DVB CA EN50221 interface device.
* *
* @dvb_adapter: DVB adapter to attach the new CA device to. * @dvb_adapter: DVB adapter to attach the new CA device to.
* @pubca: The dvb_ca instance. * @pubca: The dvb_ca instance.
@ -1916,6 +1949,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
} }
mutex_init(&ca->ioctl_mutex); mutex_init(&ca->ioctl_mutex);
mutex_init(&ca->remove_mutex);
if (signal_pending(current)) { if (signal_pending(current)) {
ret = -EINTR; ret = -EINTR;
@ -1947,7 +1981,7 @@ exit:
EXPORT_SYMBOL(dvb_ca_en50221_init); EXPORT_SYMBOL(dvb_ca_en50221_init);
/** /**
* Release a DVB CA EN50221 interface device. * dvb_ca_en50221_release - Release a DVB CA EN50221 interface device.
* *
* @pubca: The associated dvb_ca instance. * @pubca: The associated dvb_ca instance.
*/ */
@ -1958,6 +1992,14 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
dprintk("%s\n", __func__); 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 */ /* shutdown the thread if there was one */
kthread_stop(ca->thread); 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 * dvb_demux.c - DVB kernel demux API
* *
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de> * Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de> * & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH * 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 #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; cc = buf[3] & 0x0f;
ccok = ((feed->cc + 1) & 0x0f) == cc; ccok = ((feed->cc + 1) & 0x0f) == cc;
feed->cc = cc;
if (!ccok) { if (!ccok) {
set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED); set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
dprintk_sect_loss("missed packet: %d instead of %d!\n", dprintk_sect_loss("missed packet: %d instead of %d!\n",
cc, (feed->cc + 1) & 0x0f); cc, (feed->cc + 1) & 0x0f);
} }
feed->cc = cc;
if (buf[1] & 0x40) // PUSI ? if (buf[1] & 0x40) // PUSI ?
feed->peslen = 0xfffa; 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 dvb_demux *demux = feed->demux;
struct dmx_section_feed *sec = &feed->feed.sec; struct dmx_section_feed *sec = &feed->feed.sec;
u16 limit, seclen, n; u16 limit, seclen;
if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE) if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
return 0; 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 */ /* to be sure always set secbuf */
sec->secbuf = sec->secbuf_base + sec->secbufp; 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); seclen = section_length(sec->secbuf);
if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
|| seclen + sec->secbufp > limit) || seclen + sec->secbufp > limit)
@ -323,7 +313,6 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
cc = buf[3] & 0x0f; cc = buf[3] & 0x0f;
ccok = ((feed->cc + 1) & 0x0f) == cc; ccok = ((feed->cc + 1) & 0x0f) == cc;
feed->cc = cc;
if (buf[3] & 0x20) { if (buf[3] & 0x20) {
/* adaption field present, check for discontinuity_indicator */ /* 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; feed->pusi_seen = false;
dvb_dmx_swfilter_section_new(feed); dvb_dmx_swfilter_section_new(feed);
} }
feed->cc = cc;
if (buf[1] & 0x40) { if (buf[1] & 0x40) {
/* PUSI=1 (is set), section boundary is here */ /* PUSI=1 (is set), section boundary is here */

View File

@ -1,603 +0,0 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include "dvb_filter.h"
#if 0
static unsigned int bitrates[3][16] =
{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
#endif
static u32 freq[4] = {480, 441, 320, 0};
static unsigned int ac3_bitrates[32] =
{32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
0,0,0,0,0,0,0,0,0,0,0,0,0};
static u32 ac3_frames[3][32] =
{{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
{69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
{96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
#if 0
static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
void (*pes_write)(u8 *buf, int count, void *data),
void *priv)
{
dvb_filter_ipack_init(pa, IPACKS, pes_write);
dvb_filter_ipack_init(pv, IPACKS, pes_write);
pa->pid = pida;
pv->pid = pidv;
pa->data = priv;
pv->data = priv;
}
#endif
#if 0
static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
{
u8 off = 0;
if (!buf || !p ){
printk("NULL POINTER IDIOT\n");
return;
}
if (buf[1]&PAY_START) {
if (p->plength == MMAX_PLENGTH-6 && p->found>6){
p->plength = p->found-6;
p->found = 0;
send_ipack(p);
dvb_filter_ipack_reset(p);
}
}
if (buf[3] & ADAPT_FIELD) { // adaptation field?
off = buf[4] + 1;
if (off+4 > 187) return;
}
dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p);
}
#endif
#if 0
/* needs 5 byte input, returns picture coding type*/
static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr)
{
u8 pct;
if (pr) printk( "Pic header: ");
pic->temporal_reference[field] = (( headr[0] << 2 ) |
(headr[1] & 0x03) )& 0x03ff;
if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
pct = ( headr[1] >> 2 ) & 0x07;
pic->picture_coding_type[field] = pct;
if (pr) {
switch(pct){
case I_FRAME:
printk( " I-FRAME");
break;
case B_FRAME:
printk( " B-FRAME");
break;
case P_FRAME:
printk( " P-FRAME");
break;
}
}
pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) |
( (headr[3] & 0x1F) << 11) ) & 0xffff;
if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
((headr[4] & 0x80) >> 3);
if ( pct == B_FRAME ){
pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
}
if (pr) printk( " pic head param: 0x%x",
pic->picture_header_parameter);
return pct;
}
#endif
#if 0
/* needs 4 byte input */
static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
{
if (pr) printk("GOP header: ");
pic->time_code = (( headr[0] << 17 ) | ( headr[1] << 9) |
( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff;
if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F,
((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F),
((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F));
if ( ( headr[3] & 0x40 ) != 0 ){
pic->closed_gop = 1;
} else {
pic->closed_gop = 0;
}
if (pr) printk("closed: %d", pic->closed_gop);
if ( ( headr[3] & 0x20 ) != 0 ){
pic->broken_link = 1;
} else {
pic->broken_link = 0;
}
if (pr) printk(" broken: %d\n", pic->broken_link);
return 0;
}
#endif
#if 0
/* needs 8 byte input */
static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
{
int sw;
int form = -1;
if (pr) printk("Reading sequence header\n");
vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]);
sw = (int)((headr[3]&0xF0) >> 4) ;
switch( sw ){
case 1:
if (pr)
printk("Videostream: ASPECT: 1:1");
vi->aspect_ratio = 100;
break;
case 2:
if (pr)
printk("Videostream: ASPECT: 4:3");
vi->aspect_ratio = 133;
break;
case 3:
if (pr)
printk("Videostream: ASPECT: 16:9");
vi->aspect_ratio = 177;
break;
case 4:
if (pr)
printk("Videostream: ASPECT: 2.21:1");
vi->aspect_ratio = 221;
break;
case 5 ... 15:
if (pr)
printk("Videostream: ASPECT: reserved");
vi->aspect_ratio = 0;
break;
default:
vi->aspect_ratio = 0;
return -1;
}
if (pr)
printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size);
sw = (int)(headr[3]&0x0F);
switch ( sw ) {
case 1:
if (pr)
printk(" FRate: 23.976 fps");
vi->framerate = 23976;
form = -1;
break;
case 2:
if (pr)
printk(" FRate: 24 fps");
vi->framerate = 24000;
form = -1;
break;
case 3:
if (pr)
printk(" FRate: 25 fps");
vi->framerate = 25000;
form = VIDEO_MODE_PAL;
break;
case 4:
if (pr)
printk(" FRate: 29.97 fps");
vi->framerate = 29970;
form = VIDEO_MODE_NTSC;
break;
case 5:
if (pr)
printk(" FRate: 30 fps");
vi->framerate = 30000;
form = VIDEO_MODE_NTSC;
break;
case 6:
if (pr)
printk(" FRate: 50 fps");
vi->framerate = 50000;
form = VIDEO_MODE_PAL;
break;
case 7:
if (pr)
printk(" FRate: 60 fps");
vi->framerate = 60000;
form = VIDEO_MODE_NTSC;
break;
}
vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
vi->vbv_buffer_size
= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
if (pr){
printk(" BRate: %d Mbit/s",4*(vi->bit_rate)/10000);
printk(" vbvbuffer %d",16*1024*(vi->vbv_buffer_size));
printk("\n");
}
vi->video_format = form;
return 0;
}
#endif
#if 0
static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr)
{
u8 *headr;
int found = 0;
int c = 0;
while (found < 4 && c+4 < count){
u8 *b;
b = mbuf+c;
if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
&& b[3] == 0xb3) found = 4;
else {
c++;
}
}
if (! found) return -1;
c += 4;
if (c+12 >= count) return -1;
headr = mbuf+c;
if (read_sequence_header(headr, vi, pr) < 0) return -1;
vi->off = c-4;
return 0;
}
#endif
#if 0
static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
{
u8 *headr;
int found = 0;
int c = 0;
int fr = 0;
while (found < 2 && c < count){
u8 b[2];
memcpy( b, mbuf+c, 2);
if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
found = 2;
else {
c++;
}
}
if (!found) return -1;
if (c+3 >= count) return -1;
headr = mbuf+c;
ai->layer = (headr[1] & 0x06) >> 1;
if (pr)
printk("Audiostream: Layer: %d", 4-ai->layer);
ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
if (pr){
if (ai->bit_rate == 0)
printk(" Bit rate: free");
else if (ai->bit_rate == 0xf)
printk(" BRate: reserved");
else
printk(" BRate: %d kb/s", ai->bit_rate/1000);
}
fr = (headr[2] & 0x0c ) >> 2;
ai->frequency = freq[fr]*100;
if (pr){
if (ai->frequency == 3)
printk(" Freq: reserved\n");
else
printk(" Freq: %d kHz\n",ai->frequency);
}
ai->off = c;
return 0;
}
#endif
int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
{
u8 *headr;
int found = 0;
int c = 0;
u8 frame = 0;
int fr = 0;
while ( !found && c < count){
u8 *b = mbuf+c;
if ( b[0] == 0x0b && b[1] == 0x77 )
found = 1;
else {
c++;
}
}
if (!found) return -1;
if (pr)
printk("Audiostream: AC3");
ai->off = c;
if (c+5 >= count) return -1;
ai->layer = 0; // 0 for AC3
headr = mbuf+c+2;
frame = (headr[2]&0x3f);
ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
if (pr)
printk(" BRate: %d kb/s", (int) ai->bit_rate/1000);
ai->frequency = (headr[2] & 0xc0 ) >> 6;
fr = (headr[2] & 0xc0 ) >> 6;
ai->frequency = freq[fr]*100;
if (pr) printk (" Freq: %d Hz\n", (int) ai->frequency);
ai->framesize = ac3_frames[fr][frame >> 1];
if ((frame & 1) && (fr == 1)) ai->framesize++;
ai->framesize = ai->framesize << 1;
if (pr) printk (" Framesize %d\n",(int) ai->framesize);
return 0;
}
EXPORT_SYMBOL(dvb_filter_get_ac3info);
#if 0
static u8 *skip_pes_header(u8 **bufp)
{
u8 *inbuf = *bufp;
u8 *buf = inbuf;
u8 *pts = NULL;
int skip = 0;
static const int mpeg1_skip_table[16] = {
1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
};
if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
if (buf[7] & PTS_ONLY)
pts = buf+9;
else pts = NULL;
buf = inbuf + 9 + inbuf[8];
} else { /* mpeg1 */
for (buf = inbuf + 6; *buf == 0xff; buf++)
if (buf == inbuf + 6 + 16) {
break;
}
if ((*buf & 0xc0) == 0x40)
buf += 2;
skip = mpeg1_skip_table [*buf >> 4];
if (skip == 5 || skip == 10) pts = buf;
else pts = NULL;
buf += mpeg1_skip_table [*buf >> 4];
}
*bufp = buf;
return pts;
}
#endif
#if 0
static void initialize_quant_matrix( u32 *matrix )
{
int i;
matrix[0] = 0x08101013;
matrix[1] = 0x10131616;
matrix[2] = 0x16161616;
matrix[3] = 0x1a181a1b;
matrix[4] = 0x1b1b1a1a;
matrix[5] = 0x1a1a1b1b;
matrix[6] = 0x1b1d1d1d;
matrix[7] = 0x2222221d;
matrix[8] = 0x1d1d1b1b;
matrix[9] = 0x1d1d2020;
matrix[10] = 0x22222526;
matrix[11] = 0x25232322;
matrix[12] = 0x23262628;
matrix[13] = 0x28283030;
matrix[14] = 0x2e2e3838;
matrix[15] = 0x3a454553;
for ( i = 16 ; i < 32 ; i++ )
matrix[i] = 0x10101010;
}
#endif
#if 0
static void initialize_mpg_picture(struct mpg_picture *pic)
{
int i;
/* set MPEG1 */
pic->mpeg1_flag = 1;
pic->profile_and_level = 0x4A ; /* MP@LL */
pic->progressive_sequence = 1;
pic->low_delay = 0;
pic->sequence_display_extension_flag = 0;
for ( i = 0 ; i < 4 ; i++ ){
pic->frame_centre_horizontal_offset[i] = 0;
pic->frame_centre_vertical_offset[i] = 0;
}
pic->last_frame_centre_horizontal_offset = 0;
pic->last_frame_centre_vertical_offset = 0;
pic->picture_display_extension_flag[0] = 0;
pic->picture_display_extension_flag[1] = 0;
pic->sequence_header_flag = 0;
pic->gop_flag = 0;
pic->sequence_end_flag = 0;
}
#endif
#if 0
static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic )
{
int16_t last_h_offset;
int16_t last_v_offset;
int16_t *p_h_offset;
int16_t *p_v_offset;
if ( pic->mpeg1_flag ){
pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE;
pic->top_field_first = 0;
pic->repeat_first_field = 0;
pic->progressive_frame = 1;
pic->picture_coding_parameter = 0x000010;
}
/* Reset flag */
pic->picture_display_extension_flag[field_type] = 0;
last_h_offset = pic->last_frame_centre_horizontal_offset;
last_v_offset = pic->last_frame_centre_vertical_offset;
if ( field_type == FIRST_FIELD ){
p_h_offset = pic->frame_centre_horizontal_offset;
p_v_offset = pic->frame_centre_vertical_offset;
*p_h_offset = last_h_offset;
*(p_h_offset + 1) = last_h_offset;
*(p_h_offset + 2) = last_h_offset;
*p_v_offset = last_v_offset;
*(p_v_offset + 1) = last_v_offset;
*(p_v_offset + 2) = last_v_offset;
} else {
pic->frame_centre_horizontal_offset[3] = last_h_offset;
pic->frame_centre_vertical_offset[3] = last_v_offset;
}
}
#endif
#if 0
static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type)
{
pic->picture_header = 0;
pic->sequence_header_data
= ( INIT_HORIZONTAL_SIZE << 20 )
| ( INIT_VERTICAL_SIZE << 8 )
| ( INIT_ASPECT_RATIO << 4 )
| ( INIT_FRAME_RATE );
pic->mpeg1_flag = 0;
pic->vinfo.horizontal_size
= INIT_DISP_HORIZONTAL_SIZE;
pic->vinfo.vertical_size
= INIT_DISP_VERTICAL_SIZE;
pic->picture_display_extension_flag[field_type]
= 0;
pic->pts_flag[field_type] = 0;
pic->sequence_gop_header = 0;
pic->picture_header = 0;
pic->sequence_header_flag = 0;
pic->gop_flag = 0;
pic->sequence_end_flag = 0;
pic->sequence_display_extension_flag = 0;
pic->last_frame_centre_horizontal_offset = 0;
pic->last_frame_centre_vertical_offset = 0;
pic->channel = chan;
}
#endif
void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
dvb_filter_pes2ts_cb_t *cb, void *priv)
{
unsigned char *buf=p2ts->buf;
buf[0]=0x47;
buf[1]=(pid>>8);
buf[2]=pid&0xff;
p2ts->cc=0;
p2ts->cb=cb;
p2ts->priv=priv;
}
EXPORT_SYMBOL(dvb_filter_pes2ts_init);
int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
int len, int payload_start)
{
unsigned char *buf=p2ts->buf;
int ret=0, rest;
//len=6+((pes[4]<<8)|pes[5]);
if (payload_start)
buf[1]|=0x40;
else
buf[1]&=~0x40;
while (len>=184) {
buf[3]=0x10|((p2ts->cc++)&0x0f);
memcpy(buf+4, pes, 184);
if ((ret=p2ts->cb(p2ts->priv, buf)))
return ret;
len-=184; pes+=184;
buf[1]&=~0x40;
}
if (!len)
return 0;
buf[3]=0x30|((p2ts->cc++)&0x0f);
rest=183-len;
if (rest) {
buf[5]=0x00;
if (rest-1)
memset(buf+6, 0xff, rest-1);
}
buf[4]=rest;
memcpy(buf+5+rest, pes, len);
return p2ts->cb(p2ts->priv, buf);
}
EXPORT_SYMBOL(dvb_filter_pes2ts);

View File

@ -20,6 +20,7 @@
#include <linux/version.h> #include <linux/version.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include <linux/nospec.h>
#else #else
#include <linux/sched.h> #include <linux/sched.h>
#endif #endif
@ -140,7 +141,7 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv) if (fepriv)
dvb_free_device(fepriv->dvbdev); dvb_device_put(fepriv->dvbdev);
dvb_frontend_invoke_release(fe, fe->ops.release); dvb_frontend_invoke_release(fe, fe->ops.release);
@ -298,14 +299,28 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
} }
if (events->eventw == events->eventr) { 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) if (flags & O_NONBLOCK)
return -EWOULDBLOCK; return -EWOULDBLOCK;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
ret = wait_event_interruptible(events->wait_queue, ret = wait_event_interruptible(events->wait_queue,
dvb_frontend_test_event(fepriv, events)); 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) if (ret < 0)
return ret; return ret;
} }
@ -487,6 +502,11 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp; struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
if (fepriv->max_drift)
dev_warn_once(fe->dvb->device,
"Frontend requested software zigzag, but didn't set the frequency step size\n");
#endif
/* if we've got no parameters, just keep idling */ /* if we've got no parameters, just keep idling */
if (fepriv->state & FESTATE_IDLE) { if (fepriv->state & FESTATE_IDLE) {
fepriv->delay = 3 * HZ; fepriv->delay = 3 * HZ;
@ -919,6 +939,7 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
/* If the standard is for satellite, convert frequencies to kHz */ /* If the standard is for satellite, convert frequencies to kHz */
switch (c->delivery_system) { switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
case SYS_TURBO: case SYS_TURBO:
@ -944,6 +965,7 @@ static u32 dvb_frontend_get_stepsize(struct dvb_frontend *fe)
u32 step = max(fe_step, tuner_step); u32 step = max(fe_step, tuner_step);
switch (c->delivery_system) { switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
case SYS_TURBO: case SYS_TURBO:
@ -975,6 +997,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
/* range check: symbol rate */ /* range check: symbol rate */
switch (c->delivery_system) { switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
case SYS_TURBO: case SYS_TURBO:
@ -990,6 +1013,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
fe->ops.info.symbol_rate_max); fe->ops.info.symbol_rate_max);
return -EINVAL; return -EINVAL;
} }
break;
default: default:
break; break;
} }
@ -1041,6 +1065,10 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
c->input = NO_INPUT; c->input = NO_INPUT;
switch (c->delivery_system) { switch (c->delivery_system) {
case SYS_DSS:
c->modulation = QPSK;
c->rolloff = ROLLOFF_20;
break;
case SYS_DVBS: case SYS_DVBS:
case SYS_DVBS2: case SYS_DVBS2:
case SYS_TURBO: case SYS_TURBO:
@ -1065,108 +1093,100 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
return 0; return 0;
} }
#define _DTV_CMD(n, s, b) \ #define _DTV_CMD(n) \
[n] = { \ [n] = #n
.name = #n, \
.cmd = n, \
.set = s,\
.buffer = b \
}
struct dtv_cmds_h { static char *dtv_cmds[DTV_MAX_COMMAND + 1] = {
char *name; /* A display name for debugging purposes */ _DTV_CMD(DTV_TUNE),
_DTV_CMD(DTV_CLEAR),
__u32 cmd; /* A unique ID */
/* Flags */
__u32 set:1; /* Either a set or get property */
__u32 buffer:1; /* Does this property use the buffer? */
__u32 reserved:30; /* Align */
};
static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_TUNE, 1, 0),
_DTV_CMD(DTV_CLEAR, 1, 0),
/* Set */ /* Set */
_DTV_CMD(DTV_FREQUENCY, 1, 0), _DTV_CMD(DTV_FREQUENCY),
_DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0), _DTV_CMD(DTV_BANDWIDTH_HZ),
_DTV_CMD(DTV_MODULATION, 1, 0), _DTV_CMD(DTV_MODULATION),
_DTV_CMD(DTV_INVERSION, 1, 0), _DTV_CMD(DTV_INVERSION),
_DTV_CMD(DTV_DISEQC_MASTER, 1, 1), _DTV_CMD(DTV_DISEQC_MASTER),
_DTV_CMD(DTV_SYMBOL_RATE, 1, 0), _DTV_CMD(DTV_SYMBOL_RATE),
_DTV_CMD(DTV_INNER_FEC, 1, 0), _DTV_CMD(DTV_INNER_FEC),
_DTV_CMD(DTV_VOLTAGE, 1, 0), _DTV_CMD(DTV_VOLTAGE),
_DTV_CMD(DTV_TONE, 1, 0), _DTV_CMD(DTV_TONE),
_DTV_CMD(DTV_PILOT, 1, 0), _DTV_CMD(DTV_PILOT),
_DTV_CMD(DTV_ROLLOFF, 1, 0), _DTV_CMD(DTV_ROLLOFF),
_DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0), _DTV_CMD(DTV_DELIVERY_SYSTEM),
_DTV_CMD(DTV_HIERARCHY, 1, 0), _DTV_CMD(DTV_HIERARCHY),
_DTV_CMD(DTV_CODE_RATE_HP, 1, 0), _DTV_CMD(DTV_CODE_RATE_HP),
_DTV_CMD(DTV_CODE_RATE_LP, 1, 0), _DTV_CMD(DTV_CODE_RATE_LP),
_DTV_CMD(DTV_GUARD_INTERVAL, 1, 0), _DTV_CMD(DTV_GUARD_INTERVAL),
_DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0), _DTV_CMD(DTV_TRANSMISSION_MODE),
_DTV_CMD(DTV_INTERLEAVING, 1, 0), _DTV_CMD(DTV_INTERLEAVING),
_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0), _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION),
_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0), _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING),
_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0), _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0), _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX),
_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0), _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0), _DTV_CMD(DTV_ISDBT_LAYER_ENABLED),
_DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERA_FEC),
_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION),
_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING),
_DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERB_FEC),
_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION),
_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING),
_DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERC_FEC),
_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION),
_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT),
_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0), _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING),
_DTV_CMD(DTV_STREAM_ID, 1, 0), _DTV_CMD(DTV_STREAM_ID),
_DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY, 1, 0), _DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY),
_DTV_CMD(DTV_SCRAMBLING_SEQUENCE_INDEX, 1, 0), _DTV_CMD(DTV_SCRAMBLING_SEQUENCE_INDEX),
_DTV_CMD(DTV_LNA, 1, 0), _DTV_CMD(DTV_LNA),
_DTV_CMD(DTV_INPUT, 1, 0), _DTV_CMD(DTV_INPUT),
/* Get */ /* Get */
_DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1), _DTV_CMD(DTV_DISEQC_SLAVE_REPLY),
_DTV_CMD(DTV_API_VERSION, 0, 0), _DTV_CMD(DTV_API_VERSION),
_DTV_CMD(DTV_ENUM_DELSYS, 0, 0), _DTV_CMD(DTV_ENUM_DELSYS),
_DTV_CMD(DTV_ATSCMH_PARADE_ID, 1, 0), _DTV_CMD(DTV_ATSCMH_PARADE_ID),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0), _DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE),
_DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0), _DTV_CMD(DTV_ATSCMH_FIC_VER),
_DTV_CMD(DTV_ATSCMH_NOG, 0, 0), _DTV_CMD(DTV_ATSCMH_NOG),
_DTV_CMD(DTV_ATSCMH_TNOG, 0, 0), _DTV_CMD(DTV_ATSCMH_TNOG),
_DTV_CMD(DTV_ATSCMH_SGN, 0, 0), _DTV_CMD(DTV_ATSCMH_SGN),
_DTV_CMD(DTV_ATSCMH_PRC, 0, 0), _DTV_CMD(DTV_ATSCMH_PRC),
_DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0), _DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0), _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI),
_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0), _DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC),
_DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0), _DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A, 0, 0), _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0), _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0), _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C),
_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0), _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D),
/* Statistics API */ /* Statistics API */
_DTV_CMD(DTV_STAT_SIGNAL_STRENGTH, 0, 0), _DTV_CMD(DTV_STAT_SIGNAL_STRENGTH),
_DTV_CMD(DTV_STAT_CNR, 0, 0), _DTV_CMD(DTV_STAT_CNR),
_DTV_CMD(DTV_STAT_PRE_ERROR_BIT_COUNT, 0, 0), _DTV_CMD(DTV_STAT_PRE_ERROR_BIT_COUNT),
_DTV_CMD(DTV_STAT_PRE_TOTAL_BIT_COUNT, 0, 0), _DTV_CMD(DTV_STAT_PRE_TOTAL_BIT_COUNT),
_DTV_CMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0, 0), _DTV_CMD(DTV_STAT_POST_ERROR_BIT_COUNT),
_DTV_CMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0, 0), _DTV_CMD(DTV_STAT_POST_TOTAL_BIT_COUNT),
_DTV_CMD(DTV_STAT_ERROR_BLOCK_COUNT, 0, 0), _DTV_CMD(DTV_STAT_ERROR_BLOCK_COUNT),
_DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0), _DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT),
}; };
static char *dtv_cmd_name(u32 cmd)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 18))
cmd = array_index_nospec(cmd, DTV_MAX_COMMAND);
#endif
return dtv_cmds[cmd];
}
/* Synchronise the legacy tuning parameters into the cache, so that demodulator /* Synchronise the legacy tuning parameters into the cache, so that demodulator
* drivers can use a single set_frontend tuning function, regardless of whether * drivers can use a single set_frontend tuning function, regardless of whether
* it's being used for the legacy or new API, reducing code and complexity. * it's being used for the legacy or new API, reducing code and complexity.
@ -1349,8 +1369,9 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
struct file *file) struct file *file)
{ {
int ncaps; int ncaps;
unsigned int len = 1;
switch(tvp->cmd) { switch (tvp->cmd) {
case DTV_ENUM_DELSYS: case DTV_ENUM_DELSYS:
ncaps = 0; ncaps = 0;
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) { while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
@ -1358,6 +1379,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
ncaps++; ncaps++;
} }
tvp->u.buffer.len = ncaps; tvp->u.buffer.len = ncaps;
len = ncaps;
break; break;
case DTV_FREQUENCY: case DTV_FREQUENCY:
tvp->u.data = c->frequency; tvp->u.data = c->frequency;
@ -1543,27 +1565,51 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
/* Fill quality measures */ /* Fill quality measures */
case DTV_STAT_SIGNAL_STRENGTH: case DTV_STAT_SIGNAL_STRENGTH:
tvp->u.st = c->strength; tvp->u.st = c->strength;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break; break;
case DTV_STAT_CNR: case DTV_STAT_CNR:
tvp->u.st = c->cnr; tvp->u.st = c->cnr;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break; break;
case DTV_STAT_PRE_ERROR_BIT_COUNT: case DTV_STAT_PRE_ERROR_BIT_COUNT:
tvp->u.st = c->pre_bit_error; tvp->u.st = c->pre_bit_error;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break; break;
case DTV_STAT_PRE_TOTAL_BIT_COUNT: case DTV_STAT_PRE_TOTAL_BIT_COUNT:
tvp->u.st = c->pre_bit_count; tvp->u.st = c->pre_bit_count;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break; break;
case DTV_STAT_POST_ERROR_BIT_COUNT: case DTV_STAT_POST_ERROR_BIT_COUNT:
tvp->u.st = c->post_bit_error; tvp->u.st = c->post_bit_error;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break; break;
case DTV_STAT_POST_TOTAL_BIT_COUNT: case DTV_STAT_POST_TOTAL_BIT_COUNT:
tvp->u.st = c->post_bit_count; tvp->u.st = c->post_bit_count;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break; break;
case DTV_STAT_ERROR_BLOCK_COUNT: case DTV_STAT_ERROR_BLOCK_COUNT:
tvp->u.st = c->block_error; tvp->u.st = c->block_error;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break; break;
case DTV_STAT_TOTAL_BLOCK_COUNT: case DTV_STAT_TOTAL_BLOCK_COUNT:
tvp->u.st = c->block_count; tvp->u.st = c->block_count;
if (tvp->u.buffer.len > MAX_DTV_STATS * sizeof(u32))
tvp->u.buffer.len = MAX_DTV_STATS * sizeof(u32);
len = tvp->u.buffer.len;
break; break;
default: default:
dev_dbg(fe->dvb->device, dev_dbg(fe->dvb->device,
@ -1572,18 +1618,13 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
return -EINVAL; return -EINVAL;
} }
if (!dtv_cmds[tvp->cmd].buffer) if (len < 1)
dev_dbg(fe->dvb->device, len = 1;
"%s: GET cmd 0x%08x (%s) = 0x%08x\n",
__func__, tvp->cmd, dtv_cmds[tvp->cmd].name,
tvp->u.data);
else
dev_dbg(fe->dvb->device, dev_dbg(fe->dvb->device,
"%s: GET cmd 0x%08x (%s) len %d: %*ph\n", "%s: GET cmd 0x%08x (%s) len %d: %*ph\n",
__func__, __func__, tvp->cmd, dtv_cmd_name(tvp->cmd),
tvp->cmd, dtv_cmds[tvp->cmd].name, tvp->u.buffer.len, tvp->u.buffer.len, tvp->u.buffer.data);
tvp->u.buffer.len,
tvp->u.buffer.len, tvp->u.buffer.data);
return 0; return 0;
} }
@ -1806,6 +1847,54 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
return emulate_delivery_system(fe, delsys); return emulate_delivery_system(fe, delsys);
} }
static void prepare_tuning_algo_parameters(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_frontend_tune_settings fetunesettings = { 0 };
/* get frontend-specific tuning settings */
if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
fepriv->max_drift = fetunesettings.max_drift;
fepriv->step_size = fetunesettings.step_size;
} else {
/* default values */
switch (c->delivery_system) {
case SYS_DSS:
case SYS_DVBS:
case SYS_DVBS2:
case SYS_ISDBS:
case SYS_TURBO:
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
fepriv->min_delay = HZ / 20;
fepriv->step_size = c->symbol_rate / 16000;
fepriv->max_drift = c->symbol_rate / 2000;
break;
case SYS_DVBT:
case SYS_DVBT2:
case SYS_ISDBT:
case SYS_DTMB:
fepriv->min_delay = HZ / 20;
fepriv->step_size = dvb_frontend_get_stepsize(fe) * 2;
fepriv->max_drift = fepriv->step_size + 1;
break;
default:
/*
* FIXME: This sounds wrong! if freqency_stepsize is
* defined by the frontend, why not use it???
*/
fepriv->min_delay = HZ / 20;
fepriv->step_size = 0; /* no zigzag */
fepriv->max_drift = 0;
break;
}
}
if (dvb_override_tune_delay > 0)
fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
}
/** /**
* dtv_property_process_set - Sets a single DTV property * dtv_property_process_set - Sets a single DTV property
* @fe: Pointer to &struct dvb_frontend * @fe: Pointer to &struct dvb_frontend
@ -1834,7 +1923,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
else else
dev_dbg(fe->dvb->device, dev_dbg(fe->dvb->device,
"%s: SET cmd 0x%08x (%s) to 0x%08x\n", "%s: SET cmd 0x%08x (%s) to 0x%08x\n",
__func__, cmd, dtv_cmds[cmd].name, data); __func__, cmd, dtv_cmd_name(cmd), data);
switch (cmd) { switch (cmd) {
case DTV_CLEAR: case DTV_CLEAR:
/* /*
@ -2204,7 +2293,6 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
{ {
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_frontend_tune_settings fetunesettings;
u32 rolloff = 0; u32 rolloff = 0;
if (dvb_frontend_check_parameters(fe) < 0) if (dvb_frontend_check_parameters(fe) < 0)
@ -2247,6 +2335,9 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
case SYS_DVBC_ANNEX_C: case SYS_DVBC_ANNEX_C:
rolloff = 113; rolloff = 113;
break; break;
case SYS_DSS:
rolloff = 120;
break;
case SYS_DVBS: case SYS_DVBS:
case SYS_TURBO: case SYS_TURBO:
case SYS_ISDBS: case SYS_ISDBS:
@ -2282,46 +2373,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE) if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE)
c->code_rate_LP = FEC_AUTO; c->code_rate_LP = FEC_AUTO;
/* get frontend-specific tuning settings */ prepare_tuning_algo_parameters(fe);
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
fepriv->max_drift = fetunesettings.max_drift;
fepriv->step_size = fetunesettings.step_size;
} else {
/* default values */
switch (c->delivery_system) {
case SYS_DVBS:
case SYS_DVBS2:
case SYS_ISDBS:
case SYS_TURBO:
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
fepriv->min_delay = HZ / 20;
fepriv->step_size = c->symbol_rate / 16000;
fepriv->max_drift = c->symbol_rate / 2000;
break;
case SYS_DVBT:
case SYS_DVBT2:
case SYS_ISDBT:
case SYS_DTMB:
fepriv->min_delay = HZ / 20;
fepriv->step_size = dvb_frontend_get_stepsize(fe) * 2;
fepriv->max_drift = (dvb_frontend_get_stepsize(fe) * 2) + 1;
break;
default:
/*
* FIXME: This sounds wrong! if freqency_stepsize is
* defined by the frontend, why not use it???
*/
fepriv->min_delay = HZ / 20;
fepriv->step_size = 0; /* no zigzag */
fepriv->max_drift = 0;
break;
}
}
if (dvb_override_tune_delay > 0)
fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
fepriv->state = FESTATE_RETUNE; fepriv->state = FESTATE_RETUNE;
@ -2336,7 +2388,6 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
return 0; return 0;
} }
static int dvb_get_property(struct dvb_frontend *fe, struct file *file, static int dvb_get_property(struct dvb_frontend *fe, struct file *file,
struct dtv_properties *tvps) struct dtv_properties *tvps)
{ {
@ -2557,8 +2608,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_DISEQC_SEND_BURST: case FE_DISEQC_SEND_BURST:
if (fe->ops.diseqc_send_burst) { if (fe->ops.diseqc_send_burst) {
err = fe->ops.diseqc_send_burst(fe, err = fe->ops.diseqc_send_burst(fe, (long)parg);
(enum fe_sec_mini_cmd)parg);
fepriv->state = FESTATE_DISEQC; fepriv->state = FESTATE_DISEQC;
fepriv->status = 0; fepriv->status = 0;
} }
@ -2566,9 +2616,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_SET_TONE: case FE_SET_TONE:
if (fe->ops.set_tone) { if (fe->ops.set_tone) {
err = fe->ops.set_tone(fe, fepriv->tone = (long)parg;
(enum fe_sec_tone_mode)parg); err = fe->ops.set_tone(fe, fepriv->tone);
fepriv->tone = (enum fe_sec_tone_mode)parg;
fepriv->state = FESTATE_DISEQC; fepriv->state = FESTATE_DISEQC;
fepriv->status = 0; fepriv->status = 0;
} }
@ -2576,9 +2625,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_SET_VOLTAGE: case FE_SET_VOLTAGE:
if (fe->ops.set_voltage) { if (fe->ops.set_voltage) {
err = fe->ops.set_voltage(fe, fepriv->voltage = (long)parg;
(enum fe_sec_voltage)parg); err = fe->ops.set_voltage(fe, fepriv->voltage);
fepriv->voltage = (enum fe_sec_voltage)parg;
fepriv->state = FESTATE_DISEQC; fepriv->state = FESTATE_DISEQC;
fepriv->status = 0; fepriv->status = 0;
} }
@ -2742,7 +2790,6 @@ typedef unsigned int __poll_t;
#define EPOLLOUT POLLOUT #define EPOLLOUT POLLOUT
#endif #endif
static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
@ -2771,7 +2818,17 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
if (fe->exit == DVB_FE_DEVICE_REMOVED) if (fe->exit == DVB_FE_DEVICE_REMOVED)
return -ENODEV; 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); mutex_lock(&adapter->mfe_lock);
if (!adapter->mfe_dvbdev) if (!adapter->mfe_dvbdev)
@ -2949,7 +3006,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe)
else if (fe->ops.tuner_ops.sleep) else if (fe->ops.tuner_ops.sleep)
ret = fe->ops.tuner_ops.sleep(fe); 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); ret = fe->ops.sleep(fe);
return ret; return ret;
@ -2965,7 +3024,9 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
fe->id); fe->id);
fe->exit = DVB_FE_DEVICE_RESUME; 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); ret = fe->ops.init(fe);
if (fe->ops.tuner_ops.resume) if (fe->ops.tuner_ops.resume)
@ -2999,6 +3060,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
.name = fe->ops.info.name, .name = fe->ops.info.name,
#endif #endif
}; };
int ret;
dev_dbg(dvb->device, "%s:\n", __func__); dev_dbg(dvb->device, "%s:\n", __func__);
@ -3028,12 +3090,18 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
fe->dvb = dvb; fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF; fepriv->inversion = INVERSION_OFF;
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, dev_info(fe->dvb->device,
"DVB: registering adapter %i frontend %i (%s)...\n", "DVB: registering adapter %i frontend %i (%s)...\n",
fe->dvb->num, fe->id, fe->ops.info.name); fe->dvb->num, fepriv->dvbdev->id, fe->ops.info.name);
dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND, 0);
/* /*
* Initialize the cache to the proper values according with the * Initialize the cache to the proper values according with the

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/* /*
* dvb-math provides some complex fixed-point math * dvb-math provides some complex fixed-point math
* operations shared between the dvb related stuff * operations shared between the dvb related stuff
@ -15,6 +16,7 @@
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
*/ */
#if (KERNEL_VERSION(6, 6, 0) > LINUX_VERSION_CODE)
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
@ -139,3 +141,6 @@ unsigned int intlog10(u32 value)
return (log * 646456993) >> 31; return (log * 646456993) >> 31;
} }
EXPORT_SYMBOL(intlog10); EXPORT_SYMBOL(intlog10);
#else
#include <linux/int_log.h>
#endif

View File

@ -60,6 +60,9 @@
#include <media/dvb_demux.h> #include <media/dvb_demux.h>
#include <media/dvb_net.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 ) static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
{ {
@ -553,7 +556,7 @@ static int dvb_net_ule_new_payload(struct dvb_net_ule_handle *h)
h->priv->ule_sndu_type_1 = 1; h->priv->ule_sndu_type_1 = 1;
h->ts_remain -= 1; h->ts_remain -= 1;
h->from_where += 1; h->from_where += 1;
/* fallthrough */ fallthrough;
case 0: case 0:
h->new_ts = 1; h->new_ts = 1;
h->ts += TS_SZ; h->ts += TS_SZ;
@ -678,7 +681,7 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
hexdump(ule_where - TS_SZ, TS_SZ); hexdump(ule_where - TS_SZ, TS_SZ);
} }
ule_dump = 1; ule_dump = 1;
#endif #endif
h->dev->stats.rx_errors++; h->dev->stats.rx_errors++;
h->dev->stats.rx_crc_errors++; h->dev->stats.rx_crc_errors++;
@ -1018,7 +1021,7 @@ static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static int dvb_net_filter_sec_set(struct net_device *dev, static int dvb_net_filter_sec_set(struct net_device *dev,
struct dmx_section_filter **secfilter, struct dmx_section_filter **secfilter,
u8 *mac, u8 *mac_mask) const u8 *mac, u8 *mac_mask)
{ {
struct dvb_net_priv *priv = netdev_priv(dev); struct dvb_net_priv *priv = netdev_priv(dev);
int ret; int ret;
@ -1062,7 +1065,7 @@ static int dvb_net_feed_start(struct net_device *dev)
int ret = 0, i; int ret = 0, i;
struct dvb_net_priv *priv = netdev_priv(dev); struct dvb_net_priv *priv = netdev_priv(dev);
struct dmx_demux *demux = priv->demux; struct dmx_demux *demux = priv->demux;
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); netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
mutex_lock(&priv->mutex); 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 dvb_net_priv *priv = netdev_priv(dev);
struct sockaddr *addr=p; struct sockaddr *addr=p;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0))
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
#else
eth_hw_addr_set(dev, addr->sa_data);
#endif
if (netif_running(dev)) if (netif_running(dev))
schedule_work(&priv->restart_net_feed_wq); 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); dvbnet->dvbdev->adapter->num, if_num);
net->addr_len = 6; net->addr_len = 6;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0))
memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6); 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; dvbnet->device[if_num] = net;
priv = netdev_priv(net); priv = netdev_priv(net);
@ -1477,14 +1487,21 @@ static int dvb_net_do_ioctl(struct file *file,
struct net_device *netdev; struct net_device *netdev;
struct dvb_net_priv *priv_data; struct dvb_net_priv *priv_data;
struct dvb_net_if *dvbnetif = parg; struct dvb_net_if *dvbnetif = parg;
int if_num = dvbnetif->if_num;
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || if (if_num >= DVB_NET_DEVICES_MAX) {
!dvbnet->state[dvbnetif->if_num]) { 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; ret = -EINVAL;
goto ioctl_error; goto ioctl_error;
} }
netdev = dvbnet->device[dvbnetif->if_num]; netdev = dvbnet->device[if_num];
priv_data = netdev_priv(netdev); priv_data = netdev_priv(netdev);
dvbnetif->pid=priv_data->pid; dvbnetif->pid=priv_data->pid;
@ -1537,14 +1554,21 @@ static int dvb_net_do_ioctl(struct file *file,
struct net_device *netdev; struct net_device *netdev;
struct dvb_net_priv *priv_data; struct dvb_net_priv *priv_data;
struct __dvb_net_if_old *dvbnetif = parg; struct __dvb_net_if_old *dvbnetif = parg;
int if_num = dvbnetif->if_num;
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || if (if_num >= DVB_NET_DEVICES_MAX) {
!dvbnet->state[dvbnetif->if_num]) { 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; ret = -EINVAL;
goto ioctl_error; goto ioctl_error;
} }
netdev = dvbnet->device[dvbnetif->if_num]; netdev = dvbnet->device[if_num];
priv_data = netdev_priv(netdev); priv_data = netdev_priv(netdev);
dvbnetif->pid=priv_data->pid; 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); 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) static int dvb_net_close(struct inode *inode, struct file *file)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dvb_net *dvbnet = dvbdev->priv; struct dvb_net *dvbnet = dvbdev->priv;
mutex_lock(&dvbnet->remove_mutex);
dvb_generic_release(inode, file); 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); wake_up(&dvbdev->wait_queue);
} else {
mutex_unlock(&dvbnet->remove_mutex);
}
return 0; 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 = { static const struct file_operations dvb_net_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.unlocked_ioctl = dvb_net_ioctl, .unlocked_ioctl = dvb_net_ioctl,
.open = dvb_generic_open, .open = locked_dvb_net_open,
.release = dvb_net_close, .release = dvb_net_close,
.llseek = noop_llseek, .llseek = noop_llseek,
}; };
@ -1601,10 +1653,13 @@ void dvb_net_release (struct dvb_net *dvbnet)
{ {
int i; int i;
mutex_lock(&dvbnet->remove_mutex);
dvbnet->exit = 1; dvbnet->exit = 1;
mutex_unlock(&dvbnet->remove_mutex);
if (dvbnet->dvbdev->users < 1) if (dvbnet->dvbdev->users < 1)
wait_event(dvbnet->dvbdev->wait_queue, wait_event(dvbnet->dvbdev->wait_queue,
dvbnet->dvbdev->users==1); dvbnet->dvbdev->users == 1);
dvb_unregister_device(dvbnet->dvbdev); dvb_unregister_device(dvbnet->dvbdev);
@ -1623,6 +1678,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
int i; int i;
mutex_init(&dvbnet->ioctl_mutex); mutex_init(&dvbnet->ioctl_mutex);
mutex_init(&dvbnet->remove_mutex);
dvbnet->demux = dmx; dvbnet->demux = dmx;
for (i=0; i<DVB_NET_DEVICES_MAX; i++) 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(), * this pairs with smp_store_release() in dvb_ringbuffer_write(),
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset() * 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)); return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
#endif #endif
@ -75,7 +75,7 @@ ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
{ {
ssize_t free; 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(), * this pairs with smp_store_release() in dvb_ringbuffer_read(),
* dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(), * dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(),
* or dvb_ringbuffer_reset() * or dvb_ringbuffer_reset()
@ -171,7 +171,7 @@ ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, si
#else #else
/* smp_store_release() for read pointer update to ensure /* smp_store_release() for read pointer update to ensure
* that buf is not overwritten until read is complete, * 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); smp_store_release(&rbuf->pread, 0);
#endif #endif
@ -203,7 +203,7 @@ void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
#else #else
/* smp_store_release() for read pointer update to ensure /* smp_store_release() for read pointer update to ensure
* that buf is not overwritten until read is complete, * 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); smp_store_release(&rbuf->pread, 0);
#endif #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; 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) { while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {

View File

@ -5,10 +5,6 @@
* Copyright (C) 2015 Samsung Electronics * Copyright (C) 2015 Samsung Electronics
* *
* Author: jh1009.sung@samsung.com * 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> #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)); memset(ctx, 0, sizeof(struct dvb_vb2_ctx));
q->type = DVB_BUF_TYPE_CAPTURE; q->type = DVB_BUF_TYPE_CAPTURE;
/**capture type*/
q->is_output = 0;
/**only mmap is supported currently*/ /**only mmap is supported currently*/
q->io_modes = VB2_MMAP; q->io_modes = VB2_MMAP;
q->drv_priv = ctx; q->drv_priv = ctx;
q->buf_struct_size = sizeof(struct dvb_buffer); q->buf_struct_size = sizeof(struct dvb_buffer);
q->min_buffers_needed = 1; q->min_queued_buffers = 1;
q->ops = &dvb_vb2_qops; q->ops = &dvb_vb2_qops;
q->mem_ops = &vb2_vmalloc_memops; q->mem_ops = &vb2_vmalloc_memops;
q->buf_ops = &dvb_vb2_buf_ops; q->buf_ops = &dvb_vb2_buf_ops;
q->num_buffers = 0;
ret = vb2_core_queue_init(q); ret = vb2_core_queue_init(q);
if (ret) { if (ret) {
ctx->state = DVB_VB2_STATE_NONE; 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) 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); dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
return 0; 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; struct vb2_queue *q = &ctx->vb_q;
int ret; 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); 0, exp->flags);
if (ret) { if (ret) {
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name, 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) 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; 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) { if (ret) {
dprintk(1, "[%s] index=%d errno=%d\n", ctx->name, dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
b->index, ret); b->index, ret);

View File

@ -1,20 +1,10 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/* /*
* dvbdev.c * dvbdev.c
* *
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de> * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de> * & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH * 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 #define pr_fmt(fmt) "dvbdev: " fmt
@ -40,6 +30,7 @@
#endif #endif
static DEFINE_MUTEX(dvbdev_mutex); static DEFINE_MUTEX(dvbdev_mutex);
static LIST_HEAD(dvbdevfops_list);
static int dvbdev_debug; static int dvbdev_debug;
module_param(dvbdev_debug, int, 0644); module_param(dvbdev_debug, int, 0644);
@ -86,12 +77,16 @@ static const u8 minor_type[] = {
[DVB_DEVICE_CA] = 6, [DVB_DEVICE_CA] = 6,
[DVB_DEVICE_NET] = 7, [DVB_DEVICE_NET] = 7,
[DVB_DEVICE_OSD] = 8, [DVB_DEVICE_OSD] = 8,
[DVB_DEVICE_CI] = 9,
[DVB_DEVICE_MOD] = 10,
[DVB_DEVICE_NS] = 11,
[DVB_DEVICE_NSD] = 12,
}; };
#define nums2minor(num, type, id) \ #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 #endif
static struct class *dvb_class; static struct class *dvb_class;
@ -114,7 +109,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
new_fops = fops_get(dvbdev->fops); new_fops = fops_get(dvbdev->fops);
if (!new_fops) if (!new_fops)
goto fail; goto fail;
file->private_data = dvbdev; file->private_data = dvb_device_get(dvbdev);
replace_fops(file, new_fops); replace_fops(file, new_fops);
if (file->f_op->open) if (file->f_op->open)
err = file->f_op->open(inode, file); err = file->f_op->open(inode, file);
@ -128,9 +123,7 @@ fail:
return -ENODEV; return -ENODEV;
} }
static const struct file_operations dvb_device_fops = {
static const struct file_operations dvb_device_fops =
{
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = dvb_device_open, .open = dvb_device_open,
.llseek = noop_llseek, .llseek = noop_llseek,
@ -141,29 +134,38 @@ static struct cdev dvb_device_cdev;
int dvb_generic_open(struct inode *inode, struct file *file) int dvb_generic_open(struct inode *inode, struct file *file)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
int ret = 0;
if (!dvbdev) if (!dvbdev)
return -ENODEV; return -ENODEV;
if (!dvbdev->users) mutex_lock(&dvbdev->lock);
return -EBUSY; if (!dvbdev->users) {
ret = -EBUSY;
goto unlock;
}
if ((file->f_flags & O_ACCMODE) == O_RDONLY) { if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
if (!dvbdev->readers) if (!dvbdev->readers) {
return -EBUSY; ret = -EBUSY;
goto unlock;
}
dvbdev->readers--; dvbdev->readers--;
} else { } else {
if (!dvbdev->writers) if (!dvbdev->writers) {
return -EBUSY; ret = -EBUSY;
goto unlock;
}
dvbdev->writers--; dvbdev->writers--;
} }
dvbdev->users--; dvbdev->users--;
return 0; unlock:
mutex_unlock(&dvbdev->lock);
return ret;
} }
EXPORT_SYMBOL(dvb_generic_open); EXPORT_SYMBOL(dvb_generic_open);
int dvb_generic_release(struct inode *inode, struct file *file) int dvb_generic_release(struct inode *inode, struct file *file)
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
@ -171,18 +173,21 @@ int dvb_generic_release(struct inode *inode, struct file *file)
if (!dvbdev) if (!dvbdev)
return -ENODEV; return -ENODEV;
if ((file->f_flags & O_ACCMODE) == O_RDONLY) { mutex_lock(&dvbdev->lock);
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
dvbdev->readers++; dvbdev->readers++;
} else { else
dvbdev->writers++; dvbdev->writers++;
}
dvbdev->users++; dvbdev->users++;
mutex_unlock(&dvbdev->lock);
dvb_device_put(dvbdev);
return 0; return 0;
} }
EXPORT_SYMBOL(dvb_generic_release); EXPORT_SYMBOL(dvb_generic_release);
long dvb_generic_ioctl(struct file *file, long dvb_generic_ioctl(struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
@ -198,13 +203,13 @@ long dvb_generic_ioctl(struct file *file,
} }
EXPORT_SYMBOL(dvb_generic_ioctl); 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; u32 id = 0;
while (id < DVB_MAX_IDS) { while (id < DVB_MAX_IDS) {
struct dvb_device *dev; struct dvb_device *dev;
list_for_each_entry(dev, &adap->device_list, list_head) list_for_each_entry(dev, &adap->device_list, list_head)
if (dev->type == type && dev->id == id) if (dev->type == type && dev->id == id)
goto skip; goto skip;
@ -248,6 +253,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
if (dvbdev->adapter->conn) { if (dvbdev->adapter->conn) {
media_device_unregister_entity(dvbdev->adapter->conn); media_device_unregister_entity(dvbdev->adapter->conn);
kfree(dvbdev->adapter->conn);
dvbdev->adapter->conn = NULL; dvbdev->adapter->conn = NULL;
kfree(dvbdev->adapter->conn_pads); kfree(dvbdev->adapter->conn_pads);
dvbdev->adapter->conn_pads = NULL; dvbdev->adapter->conn_pads = NULL;
@ -259,7 +265,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
static int dvb_create_tsout_entity(struct dvb_device *dvbdev, 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), dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads),
GFP_KERNEL); GFP_KERNEL);
@ -276,6 +282,7 @@ static int dvb_create_tsout_entity(struct dvb_device *dvbdev,
for (i = 0; i < npads; i++) { for (i = 0; i < npads; i++) {
struct media_pad *pads = &dvbdev->tsout_pads[i]; struct media_pad *pads = &dvbdev->tsout_pads[i];
struct media_entity *entity = &dvbdev->tsout_entity[i]; struct media_entity *entity = &dvbdev->tsout_entity[i];
int ret;
entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i); entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
if (!entity->name) if (!entity->name)
@ -346,8 +353,9 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
if (npads) { if (npads) {
dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads), dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
GFP_KERNEL); GFP_KERNEL);
if (!dvbdev->pads){ if (!dvbdev->pads) {
kfree(dvbdev->entity); kfree(dvbdev->entity);
dvbdev->entity = NULL;
return -ENOMEM; return -ENOMEM;
} }
} }
@ -397,7 +405,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
static int dvb_register_media_device(struct dvb_device *dvbdev, static int dvb_register_media_device(struct dvb_device *dvbdev,
int type, int minor, int type, int minor,
unsigned demux_sink_pads) unsigned int demux_sink_pads)
{ {
#if defined(CONFIG_MEDIA_CONTROLLER_DVB) #if defined(CONFIG_MEDIA_CONTROLLER_DVB)
struct media_link *link; struct media_link *link;
@ -464,14 +472,16 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
enum dvb_device_type type, int demux_sink_pads) enum dvb_device_type type, int demux_sink_pads)
{ {
struct dvb_device *dvbdev; struct dvb_device *dvbdev;
struct file_operations *dvbdevfops; struct file_operations *dvbdevfops = NULL;
struct dvbdevfops_node *node = NULL, *new_node = NULL;
struct device *clsdev; struct device *clsdev;
int minor; int minor;
int id, ret; int id, ret;
mutex_lock(&dvbdev_register_lock); 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); mutex_unlock(&dvbdev_register_lock);
*pdvbdev = NULL; *pdvbdev = NULL;
pr_err("%s: couldn't find free device id\n", __func__); pr_err("%s: couldn't find free device id\n", __func__);
@ -479,40 +489,69 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
} }
*pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
if (!dvbdev) {
if (!dvbdev){
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
return -ENOMEM; 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){ if (!dvbdevfops) {
kfree (dvbdev); dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
if (!dvbdevfops) {
kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
return -ENOMEM; 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)); memcpy(dvbdev, template, sizeof(struct dvb_device));
kref_init(&dvbdev->ref);
dvbdev->type = type; dvbdev->type = type;
dvbdev->id = id; dvbdev->id = id;
dvbdev->adapter = adap; dvbdev->adapter = adap;
dvbdev->priv = priv; dvbdev->priv = priv;
dvbdev->fops = dvbdevfops; dvbdev->fops = dvbdevfops;
init_waitqueue_head (&dvbdev->wait_queue); mutex_init(&dvbdev->lock);
init_waitqueue_head(&dvbdev->wait_queue);
dvbdevfops->owner = adap->module; 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); down_write(&minor_rwsem);
#ifdef CONFIG_DVB_DYNAMIC_MINORS #ifdef CONFIG_DVB_DYNAMIC_MINORS
for (minor = 0; minor < MAX_DVB_MINORS; minor++) for (minor = 0; minor < MAX_DVB_MINORS; minor++)
if (dvb_minors[minor] == NULL) if (!dvb_minors[minor])
break; break;
if (minor == MAX_DVB_MINORS) { if (minor == MAX_DVB_MINORS) {
if (new_node) {
list_del(&new_node->list_head);
kfree(dvbdevfops); kfree(dvbdevfops);
kfree(new_node);
}
list_del(&dvbdev->list_head);
kfree(dvbdev); kfree(dvbdev);
up_write(&minor_rwsem); up_write(&minor_rwsem);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
@ -521,41 +560,51 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
#else #else
minor = nums2minor(adap->num, type, id); minor = nums2minor(adap->num, type, id);
#endif #endif
dvbdev->minor = minor; dvbdev->minor = minor;
dvb_minors[minor] = dvbdev; dvb_minors[minor] = dvb_device_get(dvbdev);
up_write(&minor_rwsem); up_write(&minor_rwsem);
ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
if (ret) { if (ret) {
pr_err("%s: dvb_register_media_device failed to create the mediagraph\n", pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
__func__); __func__);
if (new_node) {
dvb_media_device_free(dvbdev); list_del(&new_node->list_head);
kfree(dvbdevfops); kfree(dvbdevfops);
kfree(new_node);
}
dvb_media_device_free(dvbdev);
list_del(&dvbdev->list_head);
kfree(dvbdev); kfree(dvbdev);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
return ret; return ret;
} }
mutex_unlock(&dvbdev_register_lock);
clsdev = device_create(dvb_class, adap->device, clsdev = device_create(dvb_class, adap->device,
MKDEV(DVB_MAJOR, minor), MKDEV(DVB_MAJOR, minor),
dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) { if (IS_ERR(clsdev)) {
pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n", pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); __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(dvbdev);
mutex_unlock(&dvbdev_register_lock);
return PTR_ERR(clsdev); return PTR_ERR(clsdev);
} }
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
adap->num, dnames[type], id, minor, minor); adap->num, dnames[type], id, minor, minor);
mutex_unlock(&dvbdev_register_lock);
return 0; return 0;
} }
EXPORT_SYMBOL(dvb_register_device); EXPORT_SYMBOL(dvb_register_device);
void dvb_remove_device(struct dvb_device *dvbdev) void dvb_remove_device(struct dvb_device *dvbdev)
{ {
if (!dvbdev) if (!dvbdev)
@ -563,36 +612,44 @@ void dvb_remove_device(struct dvb_device *dvbdev)
down_write(&minor_rwsem); down_write(&minor_rwsem);
dvb_minors[dvbdev->minor] = NULL; dvb_minors[dvbdev->minor] = NULL;
dvb_device_put(dvbdev);
up_write(&minor_rwsem); up_write(&minor_rwsem);
dvb_media_device_free(dvbdev); dvb_media_device_free(dvbdev);
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
list_del (&dvbdev->list_head); list_del(&dvbdev->list_head);
} }
EXPORT_SYMBOL(dvb_remove_device); EXPORT_SYMBOL(dvb_remove_device);
static void dvb_free_device(struct kref *ref)
void dvb_free_device(struct dvb_device *dvbdev)
{ {
if (!dvbdev) struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
return;
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) void dvb_unregister_device(struct dvb_device *dvbdev)
{ {
dvb_remove_device(dvbdev); dvb_remove_device(dvbdev);
dvb_free_device(dvbdev); dvb_device_put(dvbdev);
} }
EXPORT_SYMBOL(dvb_unregister_device); EXPORT_SYMBOL(dvb_unregister_device);
#ifdef CONFIG_MEDIA_CONTROLLER_DVB #ifdef CONFIG_MEDIA_CONTROLLER_DVB
static int dvb_create_io_intf_links(struct dvb_adapter *adap, static int dvb_create_io_intf_links(struct dvb_adapter *adap,
@ -625,9 +682,9 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
struct media_entity *demux = NULL, *ca = NULL; struct media_entity *demux = NULL, *ca = NULL;
struct media_link *link; struct media_link *link;
struct media_interface *intf; struct media_interface *intf;
unsigned demux_pad = 0; unsigned int demux_pad = 0;
unsigned dvr_pad = 0; unsigned int dvr_pad = 0;
unsigned ntuner = 0, ndemod = 0; unsigned int ntuner = 0, ndemod = 0;
int ret, pad_source, pad_sink; int ret, pad_source, pad_sink;
static const char *connector_name = "Television"; static const char *connector_name = "Television";
@ -698,7 +755,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
false); false);
} else { } else {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0)) #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); PAD_SIGNAL_ANALOG);
if (pad_sink < 0) if (pad_sink < 0)
return -EINVAL; return -EINVAL;
@ -720,7 +777,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
if (ntuner && ndemod) { if (ntuner && ndemod) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,2,0))
/* NOTE: first found tuner source pad presumed correct */ /* 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); PAD_SIGNAL_ANALOG);
if (pad_source < 0) if (pad_source < 0)
return -EINVAL; return -EINVAL;
@ -829,8 +886,10 @@ EXPORT_SYMBOL_GPL(dvb_create_media_graph);
static int dvbdev_check_free_adapter_num(int num) static int dvbdev_check_free_adapter_num(int num)
{ {
struct list_head *entry; struct list_head *entry;
list_for_each(entry, &dvb_adapter_list) { list_for_each(entry, &dvb_adapter_list) {
struct dvb_adapter *adap; struct dvb_adapter *adap;
adap = list_entry(entry, struct dvb_adapter, list_head); adap = list_entry(entry, struct dvb_adapter, list_head);
if (adap->num == num) if (adap->num == num)
return 0; return 0;
@ -838,7 +897,7 @@ static int dvbdev_check_free_adapter_num(int num)
return 1; return 1;
} }
static int dvbdev_get_free_adapter_num (void) static int dvbdev_get_free_adapter_num(void)
{ {
int num = 0; int num = 0;
@ -851,7 +910,6 @@ static int dvbdev_get_free_adapter_num (void)
return -ENFILE; return -ENFILE;
} }
int dvb_register_adapter(struct dvb_adapter *adap, const char *name, int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
struct module *module, struct device *device, struct module *module, struct device *device,
short *adapter_nums) short *adapter_nums)
@ -878,8 +936,8 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
return -ENFILE; return -ENFILE;
} }
memset (adap, 0, sizeof(struct dvb_adapter)); memset(adap, 0, sizeof(struct dvb_adapter));
INIT_LIST_HEAD (&adap->device_list); INIT_LIST_HEAD(&adap->device_list);
pr_info("DVB: registering new adapter (%s)\n", name); pr_info("DVB: registering new adapter (%s)\n", name);
@ -889,13 +947,13 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
adap->device = device; adap->device = device;
adap->mfe_shared = 0; adap->mfe_shared = 0;
adap->mfe_dvbdev = NULL; adap->mfe_dvbdev = NULL;
mutex_init (&adap->mfe_lock); mutex_init(&adap->mfe_lock);
#ifdef CONFIG_MEDIA_CONTROLLER_DVB #ifdef CONFIG_MEDIA_CONTROLLER_DVB
mutex_init(&adap->mdev_lock); mutex_init(&adap->mdev_lock);
#endif #endif
list_add_tail (&adap->list_head, &dvb_adapter_list); list_add_tail(&adap->list_head, &dvb_adapter_list);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
@ -903,21 +961,22 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
} }
EXPORT_SYMBOL(dvb_register_adapter); EXPORT_SYMBOL(dvb_register_adapter);
int dvb_unregister_adapter(struct dvb_adapter *adap) int dvb_unregister_adapter(struct dvb_adapter *adap)
{ {
mutex_lock(&dvbdev_register_lock); mutex_lock(&dvbdev_register_lock);
list_del (&adap->list_head); list_del(&adap->list_head);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
return 0; return 0;
} }
EXPORT_SYMBOL(dvb_unregister_adapter); 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 * if the miracle happens and "generic_usercopy()" is included into
define this as video_usercopy(). this will introduce a dependency * the kernel, then this can vanish. please don't make the mistake and
to the v4l "videodev.o" module, which is unnecessary for some * define this as video_usercopy(). this will introduce a dependency
cards (ie. the budget dvb-cards don't need the v4l module...) */ * 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, int dvb_usercopy(struct file *file,
unsigned int cmd, unsigned long arg, unsigned int cmd, unsigned long arg,
int (*func)(struct file *file, int (*func)(struct file *file,
@ -935,7 +994,7 @@ int dvb_usercopy(struct file *file,
* For this command, the pointer is actually an integer * For this command, the pointer is actually an integer
* argument. * argument.
*/ */
parg = (void *) arg; parg = (void *)arg;
break; break;
case _IOC_READ: /* some v4l ioctls are marked wrong ... */ case _IOC_READ: /* some v4l ioctls are marked wrong ... */
case _IOC_WRITE: case _IOC_WRITE:
@ -945,7 +1004,7 @@ int dvb_usercopy(struct file *file,
} else { } else {
/* too big to allocate from stack */ /* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
if (NULL == mbuf) if (!mbuf)
return -ENOMEM; return -ENOMEM;
parg = mbuf; parg = mbuf;
} }
@ -957,15 +1016,15 @@ int dvb_usercopy(struct file *file,
} }
/* call driver */ /* call driver */
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) err = func(file, cmd, parg);
if (err == -ENOIOCTLCMD)
err = -ENOTTY; err = -ENOTTY;
if (err < 0) if (err < 0)
goto out; goto out;
/* Copy results into user buffer */ /* Copy results into user buffer */
switch (_IOC_DIR(cmd)) switch (_IOC_DIR(cmd)) {
{
case _IOC_READ: case _IOC_READ:
case (_IOC_WRITE | _IOC_READ): case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
@ -977,7 +1036,6 @@ out:
kfree(mbuf); kfree(mbuf);
return err; return err;
} }
EXPORT_SYMBOL(dvb_usercopy);
#if IS_ENABLED(CONFIG_I2C) #if IS_ENABLED(CONFIG_I2C)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0))
@ -1030,9 +1088,13 @@ EXPORT_SYMBOL_GPL(dvb_module_release);
#endif #endif
#endif #endif
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) 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_ADAPTER_NUM=%d", dvbdev->adapter->num);
add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]); add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
@ -1040,9 +1102,13 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0; return 0;
} }
#if (KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE)
static char *dvb_devnode(struct device *dev, umode_t *mode) 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", return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
@ -1054,18 +1120,24 @@ static int __init init_dvbdev(void)
int retval; int retval;
dev_t dev = MKDEV(DVB_MAJOR, 0); 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); pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR);
return retval; return retval;
} }
cdev_init(&dvb_device_cdev, &dvb_device_fops); 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"); pr_err("dvb-core: unable register character device\n");
goto error; goto error;
} }
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,4,0))
dvb_class = class_create(THIS_MODULE, "dvb"); dvb_class = class_create(THIS_MODULE, "dvb");
#else
dvb_class = class_create("dvb");
#endif
if (IS_ERR(dvb_class)) { if (IS_ERR(dvb_class)) {
retval = PTR_ERR(dvb_class); retval = PTR_ERR(dvb_class);
goto error; goto error;
@ -1080,12 +1152,19 @@ error:
return retval; return retval;
} }
static void __exit exit_dvbdev(void) static void __exit exit_dvbdev(void)
{ {
struct dvbdevfops_node *node, *next;
class_destroy(dvb_class); class_destroy(dvb_class);
cdev_del(&dvb_device_cdev); cdev_del(&dvb_device_cdev);
unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); 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); subsys_initcall(init_dvbdev);

View File

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

View File

@ -4,6 +4,7 @@
ccflags-y += -I$(srctree)/drivers/media/dvb-core/ ccflags-y += -I$(srctree)/drivers/media/dvb-core/
ccflags-y += -I$(srctree)/drivers/media/tuners/ ccflags-y += -I$(srctree)/drivers/media/tuners/
ccflags-y += --include=dd_compat.h
# FIXME: RTL2832 SDR driver uses power management directly from USB IF driver # FIXME: RTL2832 SDR driver uses power management directly from USB IF driver
ifdef CONFIG_DVB_RTL2832_SDR ifdef CONFIG_DVB_RTL2832_SDR

View File

@ -780,7 +780,7 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
return &ci->en; return &ci->en;
} }
EXPORT_SYMBOL(cxd2099_attach); EXPORT_SYMBOL_GPL(cxd2099_attach);
MODULE_DESCRIPTION("cxd2099"); MODULE_DESCRIPTION("cxd2099");
MODULE_AUTHOR("Ralph Metzler"); MODULE_AUTHOR("Ralph Metzler");

View File

@ -36,7 +36,11 @@
#include <asm/div64.h> #include <asm/div64.h>
#include <media/dvb_frontend.h> #include <media/dvb_frontend.h>
#if (KERNEL_VERSION(6, 6, 0) > LINUX_VERSION_CODE)
#include <media/dvb_math.h> #include <media/dvb_math.h>
#else
#include <linux/int_log.h>
#endif
#include "cxd2843.h" #include "cxd2843.h"
#define Log10x100(x) ((s32)(((((u64) intlog2(x) * 0x1e1a5e2e) >> 47 ) + 1) >> 1)) #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); kfree(state);
return NULL; return NULL;
} }
EXPORT_SYMBOL(cxd2843_attach); EXPORT_SYMBOL_GPL(cxd2843_attach);
MODULE_DESCRIPTION("CXD2843/37/38 driver"); MODULE_DESCRIPTION("CXD2843/37/38 driver");
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); 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; 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 #define NOA1ROM 0
#ifndef CHK_ERROR #ifndef CHK_ERROR
@ -492,7 +482,7 @@ static int WriteBlock(struct drxk_state *state, u32 Address,
#define DRXK_MAX_RETRIES_POWERUP 20 #define DRXK_MAX_RETRIES_POWERUP 20
#endif #endif
int PowerUpDevice(struct drxk_state *state) static int PowerUpDevice(struct drxk_state *state)
{ {
int status; int status;
u8 data = 0; u8 data = 0;
@ -1566,7 +1556,7 @@ static int SetOperationMode(struct drxk_state *state, enum OperationMode oMode)
case OM_QAM_ITU_B: case OM_QAM_ITU_B:
status = -1; status = -1;
break; break;
case OM_QAM_ITU_A: /* fallthrough */ case OM_QAM_ITU_A:
case OM_QAM_ITU_C: case OM_QAM_ITU_C:
CHK_ERROR(MPEGTSStop(state)); CHK_ERROR(MPEGTSStop(state));
CHK_ERROR(PowerDownQAM(state)); CHK_ERROR(PowerDownQAM(state));
@ -1589,7 +1579,7 @@ static int SetOperationMode(struct drxk_state *state, enum OperationMode oMode)
case OM_QAM_ITU_B: case OM_QAM_ITU_B:
status = -1; status = -1;
break; break;
case OM_QAM_ITU_A: /* fallthrough */ case OM_QAM_ITU_A:
case OM_QAM_ITU_C: case OM_QAM_ITU_C:
state->m_OperationMode = oMode; state->m_OperationMode = oMode;
CHK_ERROR(SetQAMStandard(state,oMode)); CHK_ERROR(SetQAMStandard(state,oMode));
@ -1765,7 +1755,7 @@ static int MPEGTSDtoSetup(struct drxk_state *state, enum OperationMode oMode)
fecOcRcnCtlRate = 0xC00000; fecOcRcnCtlRate = 0xC00000;
staticCLK = state->m_DVBTStaticCLK; staticCLK = state->m_DVBTStaticCLK;
break; break;
case OM_QAM_ITU_A: /* fallthrough */ case OM_QAM_ITU_A:
case OM_QAM_ITU_C: case OM_QAM_ITU_C:
fecOcTmdMode = 0x0004; fecOcTmdMode = 0x0004;
fecOcRcnCtlRate = 0xD2B4EE; /* good for >63 Mb/s */ fecOcRcnCtlRate = 0xD2B4EE; /* good for >63 Mb/s */
@ -2804,12 +2794,12 @@ static int DVBTScCommand(struct drxk_state *state,
case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM: case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
status = Write16_0(state, OFDM_SC_RA_RAM_PARAM1__A, param1); status = Write16_0(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
/* All commands using 1 parameters */ /* All commands using 1 parameters */
/* fall through */ fallthrough;
case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING: case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
case OFDM_SC_RA_RAM_CMD_USER_IO: case OFDM_SC_RA_RAM_CMD_USER_IO:
status = Write16_0(state, OFDM_SC_RA_RAM_PARAM0__A, param0); status = Write16_0(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
/* All commands using 0 parameters */ /* All commands using 0 parameters */
/* fall through */ fallthrough;
case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM: case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
case OFDM_SC_RA_RAM_CMD_NULL: case OFDM_SC_RA_RAM_CMD_NULL:
/* Write command */ /* Write command */
@ -3218,7 +3208,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
default: default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
/* try first guess DRX_FFTMODE_8K */ /* try first guess DRX_FFTMODE_8K */
/* fall through */ fallthrough;
case TRANSMISSION_MODE_8K: case TRANSMISSION_MODE_8K:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
break; break;
@ -3237,7 +3227,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
case GUARD_INTERVAL_AUTO: case GUARD_INTERVAL_AUTO:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
/* try first guess DRX_GUARD_1DIV4 */ /* try first guess DRX_GUARD_1DIV4 */
/* fall through */ fallthrough;
case GUARD_INTERVAL_1_4: case GUARD_INTERVAL_1_4:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
break; break;
@ -3265,7 +3255,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
/* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ /* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
// transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; // transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO;
//break; //break;
/* fall through */ fallthrough;
case HIERARCHY_1: case HIERARCHY_1:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
break; break;
@ -3288,7 +3278,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
default: default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
/* try first guess DRX_CONSTELLATION_QAM64 */ /* try first guess DRX_CONSTELLATION_QAM64 */
/* fall through */ fallthrough;
case QAM_64: case QAM_64:
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
break; break;
@ -3311,7 +3301,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
WR16(devAddr, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI)); WR16(devAddr, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI));
break; break;
case DRX_PRIORITY_UNKNOWN : /* fall through */ case DRX_PRIORITY_UNKNOWN:
default: default:
return (DRX_STS_INVALID_ARG); return (DRX_STS_INVALID_ARG);
break; break;
@ -3332,7 +3322,7 @@ static int SetDVBT (struct drxk_state *state,u16 IntermediateFreqkHz, s32 tunerF
default: default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
/* try first guess DRX_CODERATE_2DIV3 */ /* try first guess DRX_CODERATE_2DIV3 */
/* fall through */ fallthrough;
case FEC_2_3 : case FEC_2_3 :
transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
break; break;
@ -5097,4 +5087,4 @@ MODULE_DESCRIPTION("DRX-K driver");
MODULE_AUTHOR("Ralph Metzler"); MODULE_AUTHOR("Ralph Metzler");
MODULE_LICENSE("GPL v2"); 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; return fe;
} }
EXPORT_SYMBOL(lnbh25_attach); EXPORT_SYMBOL_GPL(lnbh25_attach);
MODULE_DESCRIPTION("LNBH25"); MODULE_DESCRIPTION("LNBH25");
MODULE_AUTHOR("Ralph Metzler"); 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, return lnbx2x_attach(fe, i2c, override_set, override_clear,
i2c_addr, LNBH24_TTX); i2c_addr, LNBH24_TTX);
} }
EXPORT_SYMBOL(lnbh24_attach); EXPORT_SYMBOL_GPL(lnbh24_attach);
struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 override_set, 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, return lnbx2x_attach(fe, i2c, override_set, override_clear,
0x08, LNBP21_ISEL); 0x08, LNBP21_ISEL);
} }
EXPORT_SYMBOL(lnbp21_attach); EXPORT_SYMBOL_GPL(lnbp21_attach);
MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21, lnbh24"); MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21, lnbh24");
MODULE_AUTHOR("Oliver Endriss, Igor M. Liplianin"); MODULE_AUTHOR("Oliver Endriss, Igor M. Liplianin");

View File

@ -39,7 +39,9 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/div64.h> #include <asm/div64.h>
#if (KERNEL_VERSION(6, 12, 0) > LINUX_VERSION_CODE)
#include <asm/unaligned.h> #include <asm/unaligned.h>
#endif
#include <media/dvb_frontend.h> #include <media/dvb_frontend.h>
#include "mxl5xx.h" #include "mxl5xx.h"
@ -786,7 +788,7 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
default: default:
break; break;
} }
/* fallthrough */ fallthrough;
case SYS_DVBS: case SYS_DVBS:
switch ((MXL_HYDRA_MODULATION_E) switch ((MXL_HYDRA_MODULATION_E)
regData[DMD_MODULATION_SCHEME_ADDR]) { regData[DMD_MODULATION_SCHEME_ADDR]) {
@ -823,15 +825,19 @@ static int get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties
static int set_input(struct dvb_frontend *fe, int input) static int set_input(struct dvb_frontend *fe, int input)
{ {
struct mxl *state = fe->demodulator_priv; struct mxl *state = fe->demodulator_priv;
#ifndef KERNEL_DVB_CORE
struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct dtv_frontend_properties *p = &fe->dtv_property_cache;
#endif
state->tuner = p->input = input; state->tuner = input;
#ifndef KERNEL_DVB_CORE
p->input = input;
#endif
return 0; return 0;
} }
static struct dvb_frontend_ops mxl_ops = { static struct dvb_frontend_ops mxl_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
.info = { .info = {
.name = "MXL5XX", .name = "MXL5XX",
.frequency_min_hz = 300000000, .frequency_min_hz = 300000000,
@ -856,7 +862,10 @@ static struct dvb_frontend_ops mxl_ops = {
.read_signal_strength = read_signal_strength, .read_signal_strength = read_signal_strength,
.read_ucblocks = read_ucblocks, .read_ucblocks = read_ucblocks,
.get_frontend = get_frontend, .get_frontend = get_frontend,
#ifndef KERNEL_DVB_CORE
.set_input = set_input, .set_input = set_input,
.xbar = { 4, 0, 8 }, /* tuner_max, demod id, demod_max */
#endif
.diseqc_send_master_cmd = send_master_cmd, .diseqc_send_master_cmd = send_master_cmd,
}; };
@ -1873,7 +1882,8 @@ static int probe(struct mxl *state, struct mxl5xx_cfg *cfg)
struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg, struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner) u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int))
{ {
struct mxl *state; struct mxl *state;
struct mxl_base *base; struct mxl_base *base;
@ -1913,9 +1923,12 @@ struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
list_add(&base->mxllist, &mxllist); list_add(&base->mxllist, &mxllist);
} }
state->fe.ops = mxl_ops; state->fe.ops = mxl_ops;
#ifndef KERNEL_DVB_CORE
state->fe.ops.xbar[1] = demod; state->fe.ops.xbar[1] = demod;
state->fe.demodulator_priv = state;
state->fe.dtv_property_cache.input = tuner; state->fe.dtv_property_cache.input = tuner;
#endif
state->fe.demodulator_priv = state;
*fn_set_input = set_input;
list_add(&state->mxl, &base->mxls); list_add(&state->mxl, &base->mxls);
return &state->fe; return &state->fe;

View File

@ -23,12 +23,15 @@ struct mxl5xx_cfg {
extern struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, extern struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg, struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner); u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int));
#else #else
static inline struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, static inline struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c,
struct mxl5xx_cfg *cfg, struct mxl5xx_cfg *cfg,
u32 demod, u32 tuner) u32 demod, u32 tuner,
int (**fn_set_input)(struct dvb_frontend *, int))
{ {
pr_warn("%s: driver disabled by Kconfig\n", __func__); pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL; return NULL;

View File

@ -2338,7 +2338,7 @@ error:
kfree(state); kfree(state);
return NULL; return NULL;
} }
EXPORT_SYMBOL(stv0367ter_attach); EXPORT_SYMBOL_GPL(stv0367ter_attach);
static int stv0367cab_gate_ctrl(struct dvb_frontend *fe, int enable) static int stv0367cab_gate_ctrl(struct dvb_frontend *fe, int enable)
{ {
@ -3462,7 +3462,7 @@ error:
kfree(state); kfree(state);
return NULL; return NULL;
} }
EXPORT_SYMBOL(stv0367cab_attach); EXPORT_SYMBOL_GPL(stv0367cab_attach);
MODULE_PARM_DESC(debug, "Set debug"); MODULE_PARM_DESC(debug, "Set debug");
MODULE_PARM_DESC(i2c_debug, "Set i2c 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)) if (!(OFDM_Status & 0x40))
return -1; return -1;
//printk("lock 1\n");
readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT); readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT);
FFTMode = (SYR_STAT & 0x0C) >> 2; FFTMode = (SYR_STAT & 0x0C) >> 2;
@ -1609,9 +1608,9 @@ static int ofdm_lock(struct stv_state *state)
writereg(state, R367_TSGENERAL,tmp2 & ~0x01); writereg(state, R367_TSGENERAL,tmp2 & ~0x01);
} }
msleep(FECTimeOut); msleep(FECTimeOut);
if( (OFDM_Status & 0x98) != 0x98 ) if( (OFDM_Status & 0x98) != 0x98 ) {
;//return -1; ;//return -1;
//printk("lock 2\n"); }
{ {
u8 Guard = (SYR_STAT & 0x03); u8 Guard = (SYR_STAT & 0x03);
@ -2154,7 +2153,7 @@ MODULE_DESCRIPTION("STV0367DD driver");
MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
EXPORT_SYMBOL(stv0367_attach); EXPORT_SYMBOL_GPL(stv0367_attach);

View File

@ -5254,7 +5254,7 @@ error:
kfree(state); kfree(state);
return NULL; return NULL;
} }
EXPORT_SYMBOL(stv090x_attach); EXPORT_SYMBOL_GPL(stv090x_attach);
MODULE_PARM_DESC(verbose, "Set Verbosity level"); MODULE_PARM_DESC(verbose, "Set Verbosity level");
MODULE_AUTHOR("Manu Abraham"); MODULE_AUTHOR("Manu Abraham");
MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend"); MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");

View File

@ -118,6 +118,7 @@ struct stv {
enum fe_code_rate puncture_rate; enum fe_code_rate puncture_rate;
enum fe_stv0910_modcod modcod; enum fe_stv0910_modcod modcod;
u8 pls;
enum dvbs2_fec_type fec_type; enum dvbs2_fec_type fec_type;
u32 pilots; u32 pilots;
enum fe_stv0910_roll_off fe_roll_off; 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) { if (state->receive_mode == RCVMODE_DVBS2) {
read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp); read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp);
state->pls = tmp & 0x7f;
state->modcod = (enum fe_stv0910_modcod)((tmp & 0x7c) >> 2); state->modcod = (enum fe_stv0910_modcod)((tmp & 0x7c) >> 2);
state->pilots = (tmp & 0x01) != 0; state->pilots = (tmp & 0x01) != 0;
state->fec_type = (enum dvbs2_fec_type)((tmp & 0x02) >> 1); 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); read_reg(state, RSTV0910_P2_DMDMODCOD + state->regoff, &tmp);
mc = ((tmp & 0x7c) >> 2); mc = ((tmp & 0x7c) >> 2);
p->transmission_mode = tmp & 0x7f;
p->pilot = (tmp & 0x01) ? PILOT_ON : PILOT_OFF; p->pilot = (tmp & 0x01) ? PILOT_ON : PILOT_OFF;
p->modulation = modcod2mod[mc]; p->modulation = modcod2mod[mc];
p->fec_inner = modcod2fec[mc]; p->fec_inner = modcod2fec[mc];
@ -1643,7 +1646,7 @@ static int clear_slave(struct dvb_frontend *fe)
get_field(RXEND, &done); get_field(RXEND, &done);
get_reg(DISRXBYTES, &n); 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--) for (get_reg(DISRXBYTES, &n); n; n--)
get_reg(DISRXFIFO, &d); get_reg(DISRXFIFO, &d);
@ -1699,7 +1702,7 @@ static int recv_slave_reply(struct dvb_frontend *fe,
msleep(10); msleep(10);
} }
get_reg(DISRXBYTES, &val); 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) if (i == to && !val)
return -EIO; return -EIO;
if (done && !val) 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__); printk(KERN_INFO "%s: Attaching STV6110x\n", __func__);
return stv6110x->devctl; return stv6110x->devctl;
} }
EXPORT_SYMBOL(stv6110x_attach); EXPORT_SYMBOL_GPL(stv6110x_attach);
MODULE_AUTHOR("Manu Abraham"); MODULE_AUTHOR("Manu Abraham");
MODULE_DESCRIPTION("STV6110x Silicon tuner"); MODULE_DESCRIPTION("STV6110x Silicon tuner");

View File

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

View File

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

View File

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

View File

@ -1,5 +1,9 @@
#ifndef _TDA18271C2DD_H_ #ifndef _TDA18271C2DD_H_
#define _TDA18271C2DD_H_ #define _TDA18271C2DD_H_
#include <linux/types.h>
#include <linux/i2c.h>
#if defined(CONFIG_DVB_TDA18271C2DD) || \ #if defined(CONFIG_DVB_TDA18271C2DD) || \
(defined(CONFIG_DVB_TDA18271C2DD_MODULE) \ (defined(CONFIG_DVB_TDA18271C2DD_MODULE) \
&& defined(MODULE)) && defined(MODULE))

31
include/dd_compat.h Normal file
View File

@ -0,0 +1,31 @@
#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
#ifndef fallthrough
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
# define fallthrough do {} while (0) /* fallthrough */
#endif
#endif
#ifdef KERNEL_DVB_CORE
#define DVB_DEVICE_CI 0
#define DVB_DEVICE_NS 6
#define DVB_DEVICE_NSD 7
#define DVB_DEVICE_MOD 8
#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> * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de> * & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH * 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_ #ifndef _DVBAUDIO_H_
@ -54,7 +39,7 @@ typedef enum {
typedef struct audio_mixer { typedef struct audio_mixer {
unsigned int volume_left; unsigned int volume_left;
unsigned int volume_right; unsigned int volume_right;
/* what else do we need? bass, pass-through, ... */ /* what else do we need? bass, pass-through, ... */
} audio_mixer_t; } audio_mixer_t;

View File

@ -5,21 +5,6 @@
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de> * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de> * & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH * 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_ #ifndef _DVBCA_H_
@ -132,11 +117,6 @@ struct ca_descr {
unsigned char cw[8]; unsigned char cw[8];
}; };
struct ca_pid {
unsigned int pid;
int index;/* -1 == disable*/
};
#define CA_RESET _IO('o', 128) #define CA_RESET _IO('o', 128)
#define CA_GET_CAP _IOR('o', 129, struct ca_caps) #define CA_GET_CAP _IOR('o', 129, struct ca_caps)
#define CA_GET_SLOT_INFO _IOR('o', 130, struct ca_slot_info) #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_GET_MSG _IOR('o', 132, struct ca_msg)
#define CA_SEND_MSG _IOW('o', 133, 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_DESCR _IOW('o', 134, struct ca_descr)
#define CA_SET_PID _IOW('o', 135, struct ca_pid)
#if !defined(__KERNEL__) #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_caps ca_caps_t;
typedef struct ca_msg ca_msg_t; typedef struct ca_msg ca_msg_t;
typedef struct ca_descr ca_descr_t; typedef struct ca_descr ca_descr_t;
typedef struct ca_pid ca_pid_t;
#endif #endif

View File

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

View File

@ -7,21 +7,6 @@
* Holger Waechtler <holger@convergence.de> * Holger Waechtler <holger@convergence.de>
* Andre Draszik <ad@convergence.de> * Andre Draszik <ad@convergence.de>
* for convergence integrated media GmbH * 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_ #ifndef _DVBFRONTEND_H_
@ -282,7 +267,6 @@ enum fe_spectral_inversion {
/** /**
* enum fe_code_rate - Type of Forward Error Correction (FEC) * enum fe_code_rate - Type of Forward Error Correction (FEC)
* *
*
* @FEC_NONE: No Forward Error Correction Code * @FEC_NONE: No Forward Error Correction Code
* @FEC_1_2: Forward Error Correction Code 1/2 * @FEC_1_2: Forward Error Correction Code 1/2
* @FEC_2_3: Forward Error Correction Code 2/3 * @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_3_5: Forward Error Correction Code 3/5
* @FEC_9_10: Forward Error Correction Code 9/10 * @FEC_9_10: Forward Error Correction Code 9/10
* @FEC_2_5: Forward Error Correction Code 2/5 * @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. * 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_3_5,
FEC_9_10, FEC_9_10,
FEC_2_5, FEC_2_5,
FEC_1_4,
FEC_1_3, 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 * @APSK_32: 32-APSK modulation
* @DQPSK: DQPSK modulation * @DQPSK: DQPSK modulation
* @QAM_4_NR: 4-QAM-NR 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. * Please note that not all modulations are supported by a given standard.
* *
@ -352,9 +388,16 @@ enum fe_modulation {
APSK_32, APSK_32,
DQPSK, DQPSK,
QAM_4_NR, QAM_4_NR,
QAM_1024,
QAM_4096,
APSK_8_L,
APSK_16_L,
APSK_32_L,
APSK_64, APSK_64,
APSK_64_L,
APSK_128, APSK_128,
APSK_256, APSK_256,
APSK_256_L,
}; };
/** /**
@ -409,6 +452,7 @@ enum fe_transmit_mode {
* @GUARD_INTERVAL_PN420: PN length 420 (1/4) * @GUARD_INTERVAL_PN420: PN length 420 (1/4)
* @GUARD_INTERVAL_PN595: PN length 595 (1/6) * @GUARD_INTERVAL_PN595: PN length 595 (1/6)
* @GUARD_INTERVAL_PN945: PN length 945 (1/9) * @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. * 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_PN420,
GUARD_INTERVAL_PN595, GUARD_INTERVAL_PN595,
GUARD_INTERVAL_PN945, GUARD_INTERVAL_PN945,
GUARD_INTERVAL_1_64,
}; };
/** /**
@ -577,6 +622,9 @@ enum fe_pilot {
* @ROLLOFF_20: Roloff factor: α=20% * @ROLLOFF_20: Roloff factor: α=20%
* @ROLLOFF_25: Roloff factor: α=25% * @ROLLOFF_25: Roloff factor: α=25%
* @ROLLOFF_AUTO: Auto-detect the roloff factor. * @ROLLOFF_AUTO: Auto-detect the roloff factor.
* @ROLLOFF_15: Rolloff factor: α=15%
* @ROLLOFF_10: Rolloff factor: α=10%
* @ROLLOFF_5: Rolloff factor: α=5%
* *
* .. note: * .. note:
* *
@ -603,6 +651,8 @@ enum fe_rolloff {
* Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM) * Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM)
* @SYS_DVBC_ANNEX_C: * @SYS_DVBC_ANNEX_C:
* Cable TV: DVB-C following ITU-T J.83 Annex C spec * Cable TV: DVB-C following ITU-T J.83 Annex C spec
* @SYS_DVBC2:
* Cable TV: DVB-C2
* @SYS_ISDBC: * @SYS_ISDBC:
* Cable TV: ISDB-C (no drivers yet) * Cable TV: ISDB-C (no drivers yet)
* @SYS_DVBT: * @SYS_DVBT:
@ -620,7 +670,7 @@ enum fe_rolloff {
* @SYS_DVBS: * @SYS_DVBS:
* Satellite TV: DVB-S * Satellite TV: DVB-S
* @SYS_DVBS2: * @SYS_DVBS2:
* Satellite TV: DVB-S2 * Satellite TV: DVB-S2 and DVB-S2X
* @SYS_TURBO: * @SYS_TURBO:
* Satellite TV: DVB-S Turbo * Satellite TV: DVB-S Turbo
* @SYS_ISDBS: * @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_211_187: Reed Solomon code (211,187).
* @ATSCMH_RSCODE_223_187: Reed Solomon code (223,187). * @ATSCMH_RSCODE_223_187: Reed Solomon code (223,187).
* @ATSCMH_RSCODE_235_187: Reed Solomon code (235,187). * @ATSCMH_RSCODE_235_187: Reed Solomon code (235,187).

View File

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

View File

@ -7,21 +7,6 @@
* Copyright (C) 2001 Ralph Metzler <ralph@convergence.de> * Copyright (C) 2001 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de> * & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH * 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_ #ifndef _DVBOSD_H_

View File

@ -4,27 +4,12 @@
* *
* Copyright (C) 2000 Holger Waechtler <holger@convergence.de> * Copyright (C) 2000 Holger Waechtler <holger@convergence.de>
* for convergence integrated media GmbH * 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_ #ifndef _DVBVERSION_H_
#define _DVBVERSION_H_ #define _DVBVERSION_H_
#define DVB_API_VERSION 5 #define DVB_API_VERSION 5
#define DVB_API_VERSION_MINOR 11 #define DVB_API_VERSION_MINOR 12
#endif /*_DVBVERSION_H_*/ #endif /*_DVBVERSION_H_*/

View File

@ -7,21 +7,6 @@
* Copyright (C) 2000 Marcus Metzler <marcus@convergence.de> * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
* & Ralph Metzler <ralph@convergence.de> * & Ralph Metzler <ralph@convergence.de>
* for convergence integrated media GmbH * 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_ #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. * allocated by the driver.
* @init: callback function used to initialize the tuner device. * @init: callback function used to initialize the tuner device.
* @sleep: callback function used to put the tuner to sleep. * @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 * @write: callback function used by some demod legacy drivers to
* allow other drivers to write data into their registers. * allow other drivers to write data into their registers.
* Should not be used on new drivers. * Should not be used on new drivers.
@ -438,7 +442,6 @@ struct dvb_frontend_internal_info {
* @analog_ops: pointer to &struct analog_demod_ops * @analog_ops: pointer to &struct analog_demod_ops
*/ */
struct dvb_frontend_ops { struct dvb_frontend_ops {
struct dvb_frontend_internal_info info; struct dvb_frontend_internal_info info;
u8 delsys[MAX_DELSYS]; u8 delsys[MAX_DELSYS];
@ -449,6 +452,8 @@ struct dvb_frontend_ops {
int (*init)(struct dvb_frontend* fe); int (*init)(struct dvb_frontend* fe);
int (*sleep)(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); 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, * &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 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 * The drivers should also call dvb_frontend_suspend\(\) as part of their
* handler for the &device_driver.suspend\(\). * 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. * 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. * 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. * Otherwise,t will call &dvb_frontend_ops.tuner_ops.init\(\), if available.

View File

@ -19,13 +19,11 @@
#define _DVB_NET_H_ #define _DVB_NET_H_
#include <linux/module.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> #include <media/dvbdev.h>
struct net_device;
#define DVB_NET_DEVICES_MAX 10 #define DVB_NET_DEVICES_MAX 10
#ifdef CONFIG_DVB_NET #ifdef CONFIG_DVB_NET
@ -41,6 +39,9 @@
* @exit: flag to indicate when the device is being removed. * @exit: flag to indicate when the device is being removed.
* @demux: pointer to &struct dmx_demux. * @demux: pointer to &struct dmx_demux.
* @ioctl_mutex: protect access to this struct. * @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 * Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network
* devices. * devices.
@ -53,6 +54,7 @@ struct dvb_net {
unsigned int exit:1; unsigned int exit:1;
struct dmx_demux *demux; struct dmx_demux *demux;
struct mutex ioctl_mutex; 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. * @buf: Buffer to write.
* @len: Length of buffer (currently limited to 65535 bytes max). * @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, extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8 *buf,
size_t len); size_t len);

View File

@ -27,11 +27,15 @@
#define DVB_MAJOR 212 #define DVB_MAJOR 212
#if 0
#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0 #if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
#define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS #define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
#else #else
#define DVB_MAX_ADAPTERS 64 #define DVB_MAX_ADAPTERS 64
#endif #endif
#endif
#define DVB_MAX_ADAPTERS 64
#define DVB_UNSET (-1) #define DVB_UNSET (-1)
@ -92,7 +96,11 @@ struct dvb_frontend;
* @device: pointer to struct device * @device: pointer to struct device
* @module: pointer to struct module * @module: pointer to struct module
* @mfe_shared: indicates mutually exclusive frontends. * @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_dvbdev: Frontend device in use, in the case of MFE
* @mfe_lock: Lock to prevent using the other frontends when MFE is * @mfe_lock: Lock to prevent using the other frontends when MFE is
* used. * used.
@ -131,6 +139,7 @@ struct dvb_adapter {
* struct dvb_device - represents a DVB device node * struct dvb_device - represents a DVB device node
* *
* @list_head: List head with all DVB devices * @list_head: List head with all DVB devices
* @ref: reference count for this device
* @fops: pointer to struct file_operations * @fops: pointer to struct file_operations
* @adapter: pointer to the adapter that holds this device node * @adapter: pointer to the adapter that holds this device node
* @type: type of the device, as defined by &enum dvb_device_type. * @type: type of the device, as defined by &enum dvb_device_type.
@ -161,6 +170,7 @@ struct dvb_adapter {
*/ */
struct dvb_device { struct dvb_device {
struct list_head list_head; struct list_head list_head;
struct kref ref;
const struct file_operations *fops; const struct file_operations *fops;
struct dvb_adapter *adapter; struct dvb_adapter *adapter;
enum dvb_device_type type; enum dvb_device_type type;
@ -172,6 +182,7 @@ struct dvb_device {
int readers; int readers;
int writers; int writers;
int users; int users;
struct mutex lock;
wait_queue_head_t wait_queue; wait_queue_head_t wait_queue;
/* don't really need those !? -- FIXME: use video_usercopy */ /* don't really need those !? -- FIXME: use video_usercopy */
@ -192,6 +203,35 @@ struct dvb_device {
void *priv; 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 * dvb_register_adapter - Registers a new DVB adapter
* *
@ -236,29 +276,16 @@ int dvb_register_device(struct dvb_adapter *adap,
/** /**
* dvb_remove_device - Remove a registered DVB device * 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 * @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); 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 * 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 * @dvbdev: pointer to struct dvb_device
*/ */
void dvb_unregister_device(struct dvb_device *dvbdev); void dvb_unregister_device(struct dvb_device *dvbdev);
@ -326,7 +353,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
int dvb_generic_open(struct inode *inode, struct file *file); int dvb_generic_open(struct inode *inode, struct file *file);
/** /**
* dvb_generic_close - Digital TV close function, used by DVB devices * dvb_generic_release - Digital TV close function, used by DVB devices
* *
* @inode: pointer to &struct inode. * @inode: pointer to &struct inode.
* @file: pointer to &struct file. * @file: pointer to &struct file.
@ -421,11 +448,12 @@ void dvb_module_release(struct i2c_client *client);
/* Legacy generic DVB attach function. */ /* Legacy generic DVB attach function. */
#ifdef CONFIG_MEDIA_ATTACH #ifdef CONFIG_MEDIA_ATTACH
/** /**
* dvb_attach - attaches a DVB frontend into the DVB core. * dvb_attach - attaches a DVB frontend into the DVB core.
* *
* @FUNCTION: function on a frontend module to be called. * @FUNCTION: function on a frontend module to be called.
* @ARGS...: @FUNCTION arguments. * @ARGS: @FUNCTION arguments.
* *
* This ancillary function loads a frontend module in runtime and runs * This ancillary function loads a frontend module in runtime and runs
* the @FUNCTION function there, with @ARGS. * the @FUNCTION function there, with @ARGS.

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 CI use. It detects DVB cards and their capabilities and selects
free frontends depending on a given delivery system. 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: On an Ubuntu and other Debian based system you can install it like this:

View File

@ -17,3 +17,19 @@ Tuner5=5,984
Tuner6=6,1020 Tuner6=6,1020
Tuner7=7,1056 Tuner7=7,1056
Tuner8=8,1092 Tuner8=8,1092
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

@ -0,0 +1,36 @@
[scif]
# SCIF Settings
# Manufacturer = nn : Index to selected manaufacturer (only used in config webpage)
# Unit = nn : Index to selected unit (only used in config webpage)
# Type = nn : Type of unit: 1: EN 50494, 2: TS 50607
# TunerN = Slot,Frequency[,Pin] Slot = 1..nn, Frequency = 950..2150, Pin = 0-255
# Slot = 0 (no SCIF)
# Slot = 1..8 for EN 50494, 1..32 for TS 50607
Type=0
Tuner1=0
Tuner2=0
Tuner3=0
Tuner4=0
Tuner5=0
Tuner6=0
Tuner7=0
Tuner8=0
[LNB]
#
# LNB 1 Setting
#
Tuner=1
Source=1
LOF1=9750
LOF2=10600
LOFS=11700
[LNB]
#
# LNB 2 Setting
#
Tuner=2
Source=1
LOF1=9750
LOF2=10600
LOFS=11700

View File

@ -0,0 +1,37 @@
[CA]
family=unix
[scif]
# SCIF Settings
# Manufacturer = nn : Index to selected manaufacturer (only used in config webpage)
# Unit = nn : Index to selected unit (only used in config webpage)
# Type = nn : Type of unit: 1: EN 50494, 2: TS 50607
# TunerN = Slot,Frequency[,Pin] Slot = 1..nn, Frequency = 950..2150, Pin = 0-255
# Slot = 0 (no SCIF)
# Slot = 1..8 for EN 50494, 1..32 for TS 50607
Manufacturer=0
Unit=8
Type=2
Tuner1=1,1210
Tuner2=2,1420
Tuner3=3,1680
Tuner4=4,2040
Tuner5=5,984
Tuner6=6,1020
Tuner7=7,1056
Tuner8=8,1092
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 "../include/linux/dvb/frontend.h"
#include "src/libdddvb.h" #include "src/libdddvb.h"
#include "src/dvb_filter.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <getopt.h> #include <getopt.h>
@ -12,6 +14,8 @@
#include <stdint.h> #include <stdint.h>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
#include <inttypes.h>
#include <errno.h>
char line_start[16] = ""; char line_start[16] = "";
char line_end[16] = "\r"; char line_end[16] = "\r";
@ -22,6 +26,14 @@ uint32_t packets = 0;
uint32_t payload_packets = 0; uint32_t payload_packets = 0;
uint32_t packet_errors = 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 }; 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, }; enum { IQ_RED=1, IQ_GREE, IQ_BLUE , IQ_EVIL, IQ_LOG_RED, IQ_LOG_GREEN, IQ_LOG_BLUE , IQ_LOG_EVIL , IQ_TEST, };
@ -224,6 +236,34 @@ void proc_ts(int i, uint8_t *buf)
#define TSBUFSIZE (100*188) #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) void tscheck(int ts)
{ {
uint8_t *buf; uint8_t *buf;
@ -233,20 +273,19 @@ void tscheck(int ts)
buf=(uint8_t *)malloc(TSBUFSIZE); buf=(uint8_t *)malloc(TSBUFSIZE);
while(1) { while(1) {
len=read(ts, buf, TSBUFSIZE); len=read(ts, buf, TSBUFSIZE);
if (len<0) { if (len<0)
continue;
if (len%188) { /* should not happen */
printf("blah\n");
continue; continue;
} }
if (buf[0]!=0x47) { if (buf[0]!=0x47) {
printf("unaligned\n");
read(ts, buf, 1); read(ts, buf, 1);
continue; continue;
} }
if (len%188) { /* should not happen */
printf("blah\n");
continue;
}
nts=len/188; nts=len/188;
for (i=0; i<nts; i++) for (i=0; i<nts; i++)
proc_ts(i, buf+i*188); proc_ts(i, buf+i*188);
@ -265,6 +304,76 @@ static uint32_t root2gold(uint32_t root)
return 0xffffffff; 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) int main(int argc, char **argv)
{ {
struct dddvb *dd; struct dddvb *dd;
@ -285,7 +394,7 @@ int main(int argc, char **argv)
int color = 0; int color = 0;
pamdata iq; pamdata iq;
memset(pmts, 0, sizeof(pmts));
while (1) { while (1) {
int cur_optind = optind ? optind : 1; int cur_optind = optind ? optind : 1;
int option_index = 0; int option_index = 0;
@ -308,20 +417,41 @@ int main(int argc, char **argv)
{"tscheck", no_argument, 0, 't'}, {"tscheck", no_argument, 0, 't'},
{"tscheck_l", required_argument, 0, 'a'}, {"tscheck_l", required_argument, 0, 'a'},
{"nodvr", no_argument , 0, 'q'}, {"nodvr", no_argument , 0, 'q'},
{"pam", no_argument , 0, 'a'}, {"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'}, {"help", no_argument , 0, 'h'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, c = getopt_long(argc, argv,
"e:c:i:f:s:d:p:hg:r:n:b:l:v:m:ota:q", "e:c:i:f:s:d:p:hg:r:n:b:l:v:m:ota:qPx:L:",
long_options, &option_index); long_options, &option_index);
if (c==-1) if (c==-1)
break; break;
switch (c) { 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': case 'e':
odvr = 2;
color = strtoul(optarg, NULL, 0); color = strtoul(optarg, NULL, 0);
case 'P':
odvr = 2;
break; break;
case 'o': case 'o':
fout = stderr; fout = stderr;
@ -341,7 +471,7 @@ int main(int argc, char **argv)
break; break;
} }
fprintf(fout,"performing continuity check\n"); fprintf(fout,"performing continuity check\n");
odvr = 2; odvr = 3;
break; break;
case 'c': case 'c':
config = strdup(optarg); config = strdup(optarg);
@ -388,6 +518,10 @@ int main(int argc, char **argv)
printf("unknown mtype %s\n", optarg); printf("unknown mtype %s\n", optarg);
break; break;
case 'd': case 'd':
if (!strcmp(optarg, "C2"))
delsys = SYS_DVBC2;
if (!strcmp(optarg, "DVBC2"))
delsys = SYS_DVBC2;
if (!strcmp(optarg, "C")) if (!strcmp(optarg, "C"))
delsys = SYS_DVBC_ANNEX_A; delsys = SYS_DVBC_ANNEX_A;
if (!strcmp(optarg, "DVBC")) if (!strcmp(optarg, "DVBC"))
@ -416,6 +550,8 @@ int main(int argc, char **argv)
delsys = SYS_ISDBT; delsys = SYS_ISDBT;
if (!strcmp(optarg, "ISDBS")) if (!strcmp(optarg, "ISDBS"))
delsys = SYS_ISDBS; delsys = SYS_ISDBS;
if (!strcmp(optarg, "FILE"))
delsys = SYS_FILE;
break; break;
case 'p': case 'p':
if (!strcmp(optarg, "h") || !strcmp(optarg, "H")) if (!strcmp(optarg, "h") || !strcmp(optarg, "H"))
@ -427,12 +563,19 @@ int main(int argc, char **argv)
get_ts = 0; get_ts = 0;
break; break;
case 'h': case 'h':
fprintf(fout,"ddzap [-d delivery_system] [-p polarity] [-c config_dir] [-f frequency(Hz)]\n" fprintf(fout,"ddzap [-d delivery_system] [-p polarity] [-c config_dir]\n"
" [-f frequency(Hz for terr./kHz for SAT)]\n"
" [-m 16APSK/32APSK/64APSK/128APSK/256APSK]\n"
" (only needed for higher modulations than 8PSK) on some cards\n"
" [-b bandwidth(Hz)] [-s symbol_rate(Hz)]\n" " [-b bandwidth(Hz)] [-s symbol_rate(Hz)]\n"
" [-g gold_code] [-r root_code] [-i id] [-n device_num]\n" " [-g gold_code] [-r root_code] [-i id] [-n device_num]\n"
" [-o (write dvr to stdout)]\n" " [-o (write dvr to stdout)]\n"
" [-l (tuner source for unicable)]\n" " [-l (tuner source for unicable)]\n"
" [-t [display line](continuity check)]\n" " [-t (continuity check)]\n"
" [-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" "\n"
" delivery_system = C,S,S2,T,T2,J83B,ISDBC,ISDBT\n" " delivery_system = C,S,S2,T,T2,J83B,ISDBC,ISDBT\n"
" polarity = h/H,v/V\n" " polarity = h/H,v/V\n"
@ -443,9 +586,20 @@ int main(int argc, char **argv)
} }
} }
if (optind < argc) { if (delsys==SYS_FILE) {
fprintf(fout,"Warning: unused arguments\n"); 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) { if (delsys == ~0) {
fprintf(fout,"You have to choose a delivery system: -d (C|S|S2|T|T2)\n"); fprintf(fout,"You have to choose a delivery system: -d (C|S|S2|T|T2)\n");
@ -463,7 +617,12 @@ int main(int argc, char **argv)
fprintf(fout,"dddvb_init failed\n"); fprintf(fout,"dddvb_init failed\n");
exit(-1); 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); dddvb_get_ts(dd, get_ts);
if (num != DDDVB_UNDEF) if (num != DDDVB_UNDEF)
@ -486,14 +645,6 @@ int main(int argc, char **argv)
dddvb_set_ssi(&p, ssi); dddvb_set_ssi(&p, ssi);
dddvb_dvb_tune(fe, &p); dddvb_dvb_tune(fe, &p);
#if 0
{
uint8_t ts[188];
dddvb_ca_write(dd, 0, ts, 188);
}
#endif
if (!odvr){ if (!odvr){
while (1) { while (1) {
fe_status_t stat; fe_status_t stat;
@ -503,14 +654,16 @@ int main(int argc, char **argv)
str = dddvb_get_strength(fe); str = dddvb_get_strength(fe);
cnr = dddvb_get_cnr(fe); cnr = dddvb_get_cnr(fe);
printf("stat=%02x, str=%lld.%03llddB, snr=%lld.%03llddB \n", printf("stat=%02x, str=%" PRId64 ".%03u dBm, "
stat, (long long int)str/1000,(long long int) abs(str%1000),(long long int) cnr/1000, (long long int)abs(cnr%1000)); "snr=%" PRId64 ".%03u dB\n",
stat, str/1000, abs(str%1000),
cnr/1000, abs(cnr%1000));
sleep(1); sleep(1);
} }
} else { } else {
#define BUFFSIZE (1024*188)
fe_status_t stat; fe_status_t stat;
char filename[150]; char filename[150];
#define BUFFSIZE (1024*188)
uint8_t buf[BUFFSIZE]; uint8_t buf[BUFFSIZE];
stat = 0; stat = 0;
@ -523,7 +676,8 @@ int main(int argc, char **argv)
cnr = dddvb_get_cnr(fe); cnr = dddvb_get_cnr(fe);
fprintf(stderr,"stat=%02x, str=%lld.%03llddB, snr=%lld.%03llddB \n", fprintf(stderr,"stat=%02x, str=%lld.%03llddB, snr=%lld.%03llddB \n",
stat,(long long int) str/1000,(long long int) abs(str%1000),(long long int) cnr/1000, (long long int)abs(cnr%1000)); stat, (long long int) str/1000, (long long int) abs(str%1000),
(long long int) cnr/1000, (long long int)abs(cnr%1000));
sleep(1); sleep(1);
} }
fprintf(stderr,"got lock on %s\n", fe->name); fprintf(stderr,"got lock on %s\n", fe->name);
@ -533,7 +687,6 @@ int main(int argc, char **argv)
if ((fd = open(filename ,O_RDONLY)) < 0){ if ((fd = open(filename ,O_RDONLY)) < 0){
fprintf(stderr,"Error opening input file:%s\n",filename); fprintf(stderr,"Error opening input file:%s\n",filename);
} }
if (odvr > 0){
switch (odvr){ switch (odvr){
case 1: case 1:
while(1){ while(1){
@ -549,13 +702,15 @@ int main(int argc, char **argv)
pam_write(STDOUT_FILENO, &iq); pam_write(STDOUT_FILENO, &iq);
} }
break; break;
} case 3:
} else {
if( line >= 0 && line < 64 ){ if( line >= 0 && line < 64 ){
snprintf(line_start,sizeof(line_start)-1,"\0337\033[%d;0H",line); snprintf(line_start,sizeof(line_start)-1,"\0337\033[%d;0H",line);
strncpy(line_end,"\0338",sizeof(line_end)-1); strncpy(line_end,"\0338",sizeof(line_end)-1);
} }
tscheck(fd); tscheck(fd);
break;
case 4:
decode(dd, fd);
} }
} }
} }

View File

@ -2,11 +2,13 @@
#include "dddvb.h" #include "dddvb.h"
#include "tools.h" #include "tools.h"
#include "debug.h" #include "debug.h"
#include "dvb_filter.h"
#include <linux/dvb/dmx.h> #include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
#include <linux/dvb/video.h> #include <linux/dvb/video.h>
#include <linux/dvb/net.h> #include <linux/dvb/net.h>
#include <linux/dvb/ca.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -30,6 +32,23 @@
#define MMI_STATE_ENQ 2 #define MMI_STATE_ENQ 2
#define MMI_STATE_MENU 3 #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) int set_nonblock(int fd)
{ {
@ -165,23 +184,22 @@ static int handle_pmt(struct dvbca *ca, uint8_t *buf, int size)
#endif #endif
#if 0
static void handle_tdt(struct dddvb_ca *ca) static void handle_tdt(struct dddvb_ca *ca)
{ {
struct section *section; struct section *section;
struct dvb_tdt_section *tdt; struct dvb_tdt_section *tdt;
uint8_t sec[4096]; uint8_t *sec=ca->dvbf_tdt.buf;
time_t dvb_time; 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) if (ca->stdcam == NULL)
return; return;
if (ca->stdcam->dvbtime == NULL) if (ca->stdcam->dvbtime == NULL)
return; return;
len = getsec(ca->input, 0x14, 0, 0x70, sec);
if (len < 0)
return;
dbgprintf(DEBUG_CA, "got tdt\n");
section = section_codec(sec, len); section = section_codec(sec, len);
if (section == NULL) if (section == NULL)
@ -195,7 +213,7 @@ static void handle_tdt(struct dddvb_ca *ca)
if (ca->stdcam->dvbtime) if (ca->stdcam->dvbtime)
ca->stdcam->dvbtime(ca->stdcam, dvb_time); ca->stdcam->dvbtime(ca->stdcam, dvb_time);
} }
#endif
static int handle_pmts(struct dddvb_ca *ca) 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 = ((sec[1] & 0x0f) << 8) | sec[2];
len += 3; len += 3;
memcpy(sec, pmts[i], len); memcpy(sec, pmts[i], len);
//dump(stderr, sec, len);
section = section_codec(sec, len); section = section_codec(sec, len);
if (!section) {
dbgprintf(DEBUG_CA, "section_codec failed\n");;
continue;
}
section_ext = section_ext_decode(section, 0); 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 = 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; ca->ca_pmt_version[i] = section_ext->version_number;
if (ca->sentpmt) { if (ca->sentpmt) {
@ -291,14 +327,16 @@ static int set_pmts(struct dddvb_ca *ca, uint8_t **pmts)
listmgmt = CA_LIST_MANAGEMENT_LAST; 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, if ((size = en50221_ca_format_pmt(pmt, capmt, sizeof(capmt), ca->moveca, listmgmt,
CA_PMT_CMD_ID_OK_DESCRAMBLING)) < 0) { CA_PMT_CMD_ID_OK_DESCRAMBLING)) < 0) {
dbgprintf(DEBUG_CA, "Failed to format PMT\n"); dbgprintf(DEBUG_CA, "Failed to format PMT\n");
return -1; 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)) { if (en50221_app_ca_pmt(ca->stdcam->ca_resource, ca->stdcam->ca_session_number, capmt, size)) {
dbgprintf(DEBUG_CA, "Failed to send PMT\n"); dbgprintf(DEBUG_CA, "Failed to send PMT\n");
return -1; return -1;
@ -625,12 +663,27 @@ static int init_ca_stack(struct dddvb_ca *ca)
return 0; 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) static int init_ca(struct dddvb *dd, int a, int f, int fd)
{ {
struct dddvb_ca *ca; struct dddvb_ca *ca;
char fname[80]; char fname[80];
if (dd->dvbca_num >= DDDVB_MAX_DVB_CA)
return -1;
ca = &dd->dvbca[dd->dvbca_num]; ca = &dd->dvbca[dd->dvbca_num];
ca->dd = dd; ca->dd = dd;
ca->anum = a; ca->anum = a;
@ -639,10 +692,13 @@ static int init_ca(struct dddvb *dd, int a, int f, int fd)
ca->fd = fd; ca->fd = fd;
pthread_mutex_init(&ca->mutex, 0); pthread_mutex_init(&ca->mutex, 0);
//cam_reset(fd);
init_ca_stack(ca); init_ca_stack(ca);
pthread_create(&ca->poll_pt, NULL, (void *) ci_poll, ca); pthread_create(&ca->poll_pt, NULL, (void *) ci_poll, ca);
pthread_create(&ca->pt, NULL, (void *) handle_ci, 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); sprintf(fname, "/dev/dvb/adapter%d/ci%d", a, f);
ca->ci_wfd = open(fname, O_WRONLY); 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) int dddvb_ca_write(struct dddvb *dd, uint32_t nr, uint8_t *buf, uint32_t len)
{ {
struct dddvb_ca *ca = &dd->dvbca[nr]; 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); 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]; 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); return set_pmts(ca, pmts);
} }

Some files were not shown because too many files have changed in this diff Show More