├── README-old.md ├── README.md ├── hauppauge.sh ├── hauppauge ├── 001-Hauppauge955D-lgdt3306a-v3.patch ├── 002-Hauppauge955D-em28xx-Tuner1.patch ├── 003-Hauppauge955D-em28xx-Tuner2-v6.patch └── hauppauge955D-SYNOApollolake-DSM622_24922-Kernel_4.4.59-20190520.tar.bz2 ├── images ├── antenne-omnidirectionnelle.jpg ├── antenne-unidirectionnelle.jpg ├── ds918.jpg ├── fireTV-network.jpg ├── fireTV.jpg ├── firetv-downloader-kodiweb-download-android-armv7a32bit-download.png ├── firetv-downloader-kodiweb-download-android-armv7a32bit.png ├── firetv-downloader-kodiweb-download-androidrobot.png ├── firetv-downloader-kodiweb-download.png ├── firetv-downloader.png ├── firetv-kodi-install-01.png ├── firetv-kodi-install-02.png ├── firetv-kodi-install-03.png ├── firetv-kodi-install-04.png ├── firetv-kodi-install-05.png ├── firetv-menu-parametres-mafiretv.png ├── firetv-menu-parametres.png ├── firetv-menu.png ├── firetv-parametres-mafiretv-aproposde-reseau.png ├── firetv-parametres-mafiretv-aproposde.png ├── firetv-parametres-mafiretv-optiondev-adb.png ├── firetv-parametres-mafiretv-optiondev-sources.png ├── firetv-parametres-mafiretv-optiondev.png ├── hdhomerun.jpeg ├── kodi-addiciel-tvheadend-configuration-avance-async_EPG.png ├── kodi-addiciel-tvheadend-configuration-connexion.png ├── kodi-addiciel-tvheadend-configuration.png ├── kodi-parametre-interface-habillage-configurer-elements_menus.png ├── kodi-parametre-interface-habillage-configurer.png ├── kodi-parametre-interface-habillage.png ├── kodi-parametre-interface-region_heure_langue.png ├── kodi-parametre-interface.png ├── kodi-parametre-systeme.png ├── kodi-parametres-addiciels-kodi_repo.png ├── kodi-parametres-addiciels.png ├── kodi-parametres-numeriscope-guide-14jours.png ├── kodi-parametres-numeriscope.png ├── kodi-parametres.png ├── kodi-start-firstrun.png ├── kodi-start.png ├── synology-configuration-group-media-01.png ├── synology-configuration-group-media-02.png ├── synology-configuration-group-media-03.png ├── synology-configuration-group-media-04.png ├── synology-configuration-group-media-05.png ├── synology-configuration-group-media-06.png ├── synology-configuration-groupe-icon.png ├── synology-configuration-icon.png ├── synology-configuration-user-kodi-01.png ├── synology-configuration-user-kodi-02.png ├── synology-configuration-user-kodi-03.png ├── synology-configuration-user-kodi-04.png ├── synology-configuration-user-kodi-05.png ├── synology-configuration-user-kodi-06.png ├── synology-configuration-user-kodi-07.png ├── synology-configuration-utilisateur-icon.png ├── synology-packagecenter-add_source-synocommunity.png ├── synology-packagecenter-beta.png ├── synology-packagecenter-entware-01.png ├── synology-packagecenter-entware-02.png ├── synology-packagecenter-entware-03.png ├── synology-packagecenter-entware-04.png ├── synology-packagecenter-entware-05.png ├── synology-packagecenter-ffmpeg.png ├── synology-packagecenter-icon.png ├── synology-packagecenter-parametres.png ├── synology-packagecenter-perl-01.png ├── synology-packagecenter-sources.png ├── synology-packagecenter-tvheadend.png ├── synology-taskscheduler-tvh_backup-01.png ├── synology-taskscheduler-tvh_backup-02.png ├── synology-taskscheduler-tvh_backup-03.png ├── synology-taskscheduler-zap2xml-01.png ├── synology-taskscheduler-zap2xml-02.png ├── synology-taskscheduler-zap2xml-03.png ├── tvheadend-configuration-epg-chaines-liste-chaine_epg.png ├── tvheadend-configuration-epg-modules_epg-general.png ├── tvheadend-configuration-epg-modules_epg-internal_grabber.png ├── tvheadend-configuration-epg-modules_epg-run_internal_grabbers.png ├── tvheadend-configuration-epg-modules_epg-tv_grab_file-settings.png ├── tvheadend-configuration-epg-modules_epg-tv_grab_file.png ├── tvheadend-configuration-general-base-icons.png ├── tvheadend-kodi_label_formatting_support.png ├── tvheadend-menu-configuration-epg-chaines.png ├── tvheadend-menu-configuration-epg-collecteur_epg.png ├── tvheadend-menu-configuration-epg-modules_epg.png ├── tvheadend-menu-configuration-general-base-Web_Interface_Settings.png ├── tvheadend-menu-configuration-general-base.png └── tvlisting.zap2it-favoris.png ├── kernel └── synocli-kernelmodule.sh └── tvheadend-backup.sh /README-old.md: -------------------------------------------------------------------------------- 1 | # synology - th0ma7 2 | Synology personnal hack, info, tools & source code 3 | 4 | Donnations welcomed at: `0x522d164549E68681dfaC850A2cabdb95686C1fEC` 5 | 6 | # Hauppauge WinTV DualHD HWC 955D 7 | The following allows building kernel modules for the Hauppauge WinTV DualHD HWC 955D media adapter allowing to use TVheadend natively within the NAS. 8 | * https://www.linuxtv.org/wiki/index.php/Hauppauge_WinTV-HVR-955Q 9 | 10 | It was tested on the following hardware: 11 | * model: DS918+ 12 | * OS: DSM 6.2.2 build #24922 13 | * kernel: 4.4.59+ 14 | * arch: x86_64 15 | * core name: Apollo Lake 16 | 17 | Finding your running kernel: 18 | ``` 19 | $ uname -mvr 20 | 4.4.59+ #24922 SMP PREEMPT Thu Mar 28 11:07:03 CST 2019 x86_64 21 | ``` 22 | 23 | Finding your CPU type: 24 | * https://en.wikichip.org/wiki/intel/celeron/j3455 25 | ``` 26 | $ cat /proc/cpuinfo | grep model.name | head -1 27 | model name : Intel(R) Celeron(R) CPU J3455 @ 1.50GHz 28 | ``` 29 | 30 | ## Current status 31 | Available patches makes both tuner detected by the kernel using the `em28xx.ko` updated driver. The `lgdt3306a.ko` demodulator driver providing the dvb-frontend devices now works and has a few DEBUG messages output. It originally failed because I was also sharing the USB device with a Ubuntu VM running on-top and loading the kernel modules in the wrong order. 32 | 33 | Working: 34 | - `em28xx`: both tuners detected & firmware loading OK 35 | - `lgdt3306a`: now functional 36 | End result: 37 | - `tvheadend`: fully detects both tuners 38 | 39 | Work is based on the backporting of the following upstream kernel patches: 40 | 41 | Demodulator (lgdt3306a): 42 | * https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=4f75189024f4186a7ff9d56f4a8cb690774412ec 43 | 44 | Adaptor (em28xx): 45 | * https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=11a2a949d05e9d2d9823f0c45fa476743d9e462b 46 | * https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=1586342e428d80e53f9a926b2e238d2175b9f5b5 47 | * https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=be7fd3c3a8c5e9acbc69f887ca961df5e68cf6f0 48 | 49 | Along with backported patches from the media-tree that b-rad-NDi made available here: 50 | * https://github.com/b-rad-NDi/Ubuntu-media-tree-kernel-builder/tree/master/patches/fedora-22-4.4.0 51 | 52 | ## Preparation 53 | Using a Ubuntu 18.04 OS VM in order to build the updated modules. 54 | 55 | Install a few essential packages: 56 | ``` 57 | $ sudo apt update 58 | $ sudo apt install build-essential ncurses-dev bc libssl-dev libc6-i386 curl 59 | ``` 60 | 61 | The toolchain & kernel sources are located here: 62 | https://sourceforge.net/projects/dsgpl/files/ 63 | 64 | I use a $HOME/synology directory to drop all the downloaded files and a $HOME/source as my working directory. Later references make usage of theses both paths: 65 | ``` 66 | $ mkdir $HOME/synology 67 | $ mkdir $HOME/sources 68 | ``` 69 | 70 | Download the toolchain from Home / DSM 6.2 Tool Chains / Intel x86 Linux 4.4.59 (Apollolake) 71 | ``` 72 | $ wget https://sourceforge.net/projects/dsgpl/files/DSM%206.2%20Tool%20Chains/Intel%20x86%20Linux%204.4.59%20%28Apollolake%29/apollolake-gcc493_glibc220_linaro_x86_64-GPL.txz/download -O apollolake-gcc493_glibc220_linaro_x86_64-GPL.txz -P $HOME/synology 73 | ``` 74 | 75 | Download the synology kernel sources from Home / Synology NAS GPL Source / 22259branch / apollolake-source: 76 | ``` 77 | $ wget https://sourceforge.net/projects/dsgpl/files/Synology%20NAS%20GPL%20Source/22259branch/apollolake-source/linux-4.4.x.txz/download -O linux-4.4.x.txz -P $HOME/synology 78 | ``` 79 | 80 | Extract the files: 81 | * The toolset is decompressed into the `$HOME/synology` directory 82 | * Kernel sources are decompresed in the `$HOME/sources` directory 83 | ``` 84 | $ tar -xvf $HOME/synology/apollolake-gcc493_glibc220_linaro_x86_64-GPL.txz -C $HOME/synology 85 | $ tar -xvf $HOME/synology/linux-4.4.x.txz -C $HOME/sources 86 | ``` 87 | 88 | Download the `lgdt3306a` and `em28xx` patches: 89 | ``` 90 | $ wget https://raw.githubusercontent.com/th0ma7/synology/master/hauppauge/001-Hauppauge955D-lgdt3306a-v3.patch -P $HOME/sources 91 | $ wget https://raw.githubusercontent.com/th0ma7/synology/master/hauppauge/002-Hauppauge955D-em28xx-Tuner1.patch -P $HOME/sources 92 | $ wget https://raw.githubusercontent.com/th0ma7/synology/master/hauppauge/003-Hauppauge955D-em28xx-Tuner2-v6.patch -P $HOME/sources 93 | ``` 94 | 95 | ## Patching 96 | We now have to prepare the kernel sources for compilation. Move down to the `$HOME/sources` directory: 97 | ``` 98 | $ cd $HOME/sources/linux-4.4.x 99 | ``` 100 | 101 | Frist need to copy the apollolake synology kernel configuration 102 | ``` 103 | ~/sources/linux-4.4.x$ synoconfigs/apollolake .config 104 | ``` 105 | 106 | Secondly, using a text editor you need to adjust a few variables in the Makefile such as: 107 | ``` 108 | EXTRAVERSION = + 109 | ARCH ?= x86_64 110 | CROSS_COMPILE ?= /usr/local/x86_64-pc-linux-gnu/bin/x86_64-pc-linux-gnu- 111 | ``` 112 | 113 | Lastly, apply the necessary patches: 114 | ``` 115 | ~/sources/linux-4.4.x$ patch -p1 < ../001-Hauppauge955D-lgdt3306a-v3.patch 116 | ~/sources/linux-4.4.x$ patch -p1 < ../002-Hauppauge955D-em28xx-Tuner1.patch 117 | ~/sources/linux-4.4.x$ patch -p1 < ../003-Hauppauge955D-em28xx-Tuner2-v6.patch 118 | ``` 119 | 120 | # Compilation 121 | Modify the original configuration: 122 | ``` 123 | ~/sources/linux-4.4.x$ sudo make oldconfig 124 | ~/sources/linux-4.4.x$ sudo make menuconfig 125 | Device Drivers ---> 126 | Multimedia support ---> 127 | [*] Media Controller API 128 | [*] V4L2 sub-device userspace API 129 | ``` 130 | Everything should now all set for building the modules: 131 | ``` 132 | ~/sources/linux-4.4.x$ make modules_prepare 133 | ~/sources/linux-4.4.x$ make modules M=drivers/media -j4 134 | ``` 135 | 136 | # Installation 137 | 138 | Using SSH login as admin on the synology NAS: 139 | ``` 140 | $ ssh admin@192.168.x.x 141 | ``` 142 | 143 | Create a new local module directory (name will match kernel version): 144 | ``` 145 | $ sudo mkdir -p /usr/local/lib/modules/$(uname -r) 146 | $ cd /usr/local/lib/modules/$(uname -r) 147 | ``` 148 | 149 | Copy the updated media drivers modules over to the NAS (or download the one from my repository on github - Use at your own risks): 150 | ``` 151 | $ sudo scp "username@192.168.x.x:~/sources/linux-4.4.x/drivers/media/usb/em28xx/*.ko" . 152 | $ sudo scp "username@192.168.x.x:~/sources/linux-4.4.x/drivers/media/dvb-frontends/lgdt3306a.ko" . 153 | $ sudo scp "username@192.168.x.x:~/sources/linux-4.4.x/drivers/media/dvb-frontends/media.ko" . 154 | ``` 155 | 156 | Copy the load/unload script to the NAS as well (and make it executable): 157 | ``` 158 | $ wget https://raw.githubusercontent.com/th0ma7/synology/master/hauppauge/hauppauge-load.sh 159 | $ wget https://raw.githubusercontent.com/th0ma7/synology/master/hauppauge/hauppauge-unload.sh 160 | $ chmod 755 hauppauge-*.sh 161 | ``` 162 | 163 | Create a local rc file locate at `/usr/local/etc/rc.d/hauppauge.sh` that will be executed at boot time (or copy `hauppauge-load.sh` script): 164 | ``` 165 | #!/bin/sh 166 | 167 | # Load mandatory modules 168 | sudo insmod /lib/modules/dvb-core.ko 169 | sudo insmod /lib/modules/rc-core.ko 170 | sudo insmod /lib/modules/dvb-usb.ko 171 | sudo insmod /lib/modules/videodev.ko 172 | sudo insmod /lib/modules/v4l2-common.ko 173 | sudo insmod /lib/modules/tveeprom.ko 174 | 175 | # Load Hauppauge updated drivers 176 | sudo insmod /lib/modules/si2157.ko 177 | sudo insmod /usr/local/lib/modules/$(uname -r)/media.ko 178 | sudo insmod /usr/local/lib/modules/$(uname -r)/lgdt3306a.ko 179 | sudo insmod /usr/local/lib/modules/$(uname -r)/em28xx.ko 180 | sudo insmod /usr/local/lib/modules/$(uname -r)/em28xx-dvb.ko 181 | ``` 182 | 183 | Execute manually the rc script to confirm all is ok: 184 | ``` 185 | $ sudo /usr/local/etc/rc.d/hauppauge.sh 186 | ``` 187 | 188 | Normally should see the following in kernel `dmesg` (added a few DEBUG to lgdt3306a): 189 | ``` 190 | [ 557.806644] em28xx: New device HCW 955D @ 480 Mbps (2040:026d, interface 0, class 0) 191 | [ 557.815308] em28xx: DVB interface 0 found: isoc 192 | [ 557.820423] em28xx: chip ID is em28174 193 | [ 558.939915] em28174 #0: EEPROM ID = 26 00 01 00, EEPROM hash = 0x3d790eca 194 | [ 558.947531] em28174 #0: EEPROM info: 195 | [ 558.951857] em28174 #0: microcode start address = 0x0004, boot configuration = 0x01 196 | [ 558.966683] em28174 #0: AC97 audio (5 sample rates) 197 | [ 558.972234] em28174 #0: 500mA max power 198 | [ 558.976620] em28174 #0: Table at offset 0x27, strings=0x0a72, 0x187c, 0x086a 199 | [ 558.984753] em28174 #0: Identified as Hauppauge WinTV-dualHD 01595 ATSC/QAM (card=100) 200 | [ 558.994647] tveeprom 8-0050: Hauppauge model 204101, rev B2I6, serial# 11584195 201 | [ 559.002824] tveeprom 8-0050: tuner model is SiLabs Si2157 (idx 186, type 4) 202 | [ 559.010649] tveeprom 8-0050: TV standards PAL(B/G) NTSC(M) PAL(I) SECAM(L/L') PAL(D/D1/K) ATSC/DVB Digital (eeprom 0xfc) 203 | [ 559.023133] tveeprom 8-0050: audio processor is None (idx 0) 204 | [ 559.029491] tveeprom 8-0050: has no radio, has IR receiver, has no IR transmitter 205 | [ 559.038167] em28174 #0: dvb set to isoc mode. 206 | [ 559.043177] em28xx: chip ID is em28174 207 | [ 560.162726] em28174 #1: EEPROM ID = 26 00 01 00, EEPROM hash = 0x3d790eca 208 | [ 560.170323] em28174 #1: EEPROM info: 209 | [ 560.174326] em28174 #1: microcode start address = 0x0004, boot configuration = 0x01 210 | [ 560.189064] em28174 #1: AC97 audio (5 sample rates) 211 | [ 560.194613] em28174 #1: 500mA max power 212 | [ 560.199009] em28174 #1: Table at offset 0x27, strings=0x0a72, 0x187c, 0x086a 213 | [ 560.207139] em28174 #1: Identified as Hauppauge WinTV-dualHD 01595 ATSC/QAM (card=100) 214 | [ 560.216915] tveeprom 10-0050: Hauppauge model 204101, rev B2I6, serial# 11584195 215 | [ 560.225192] tveeprom 10-0050: tuner model is SiLabs Si2157 (idx 186, type 4) 216 | [ 560.233070] tveeprom 10-0050: TV standards PAL(B/G) NTSC(M) PAL(I) SECAM(L/L') PAL(D/D1/K) ATSC/DVB Digital (eeprom 0xfc) 217 | [ 560.245327] tveeprom 10-0050: audio processor is None (idx 0) 218 | [ 560.251757] tveeprom 10-0050: has no radio, has IR receiver, has no IR transmitter 219 | [ 560.260220] em28xx: dvb ts2 set to isoc mode. 220 | [ 560.465298] em28174 #0: Binding DVB extension 221 | [ 560.476140] i2c i2c-8: Added multiplexed i2c bus 11 222 | [ 560.481615] DEBUG: Passed lgdt3306a_probe 2351 223 | [ 560.486720] DEBUG: Passed lgdt3306a_probe 2353 224 | [ 560.491791] DEBUG: Passed lgdt3306a_probe 2355 225 | [ 560.496853] DEBUG: Passed lgdt3306a_probe 2357 226 | [ 560.501921] lgdt3306a 8-0059: LG Electronics LGDT3306A successfully identified 227 | [ 560.509994] DEBUG: Passed lgdt3306a_probe 2360 228 | [ 560.517015] si2157 11-0060: Silicon Labs Si2147/2148/2157/2158 successfully attached 229 | [ 560.525695] DVB: registering new adapter (em28174 #0) 230 | [ 560.531352] usb 1-3: DVB: registering adapter 0 frontend 0 (LG Electronics LGDT3306A VSB/QAM Frontend)... 231 | [ 560.544142] em28174 #0: DVB extension successfully initialized 232 | [ 560.550672] em28174 #1: Binding DVB extension 233 | [ 560.560027] i2c i2c-10: Added multiplexed i2c bus 12 234 | [ 560.565578] DEBUG: Passed lgdt3306a_probe 2351 235 | [ 560.570650] DEBUG: Passed lgdt3306a_probe 2353 236 | [ 560.575800] DEBUG: Passed lgdt3306a_probe 2355 237 | [ 560.580886] DEBUG: Passed lgdt3306a_probe 2357 238 | [ 560.585962] lgdt3306a 10-000e: LG Electronics LGDT3306A successfully identified 239 | [ 560.594141] DEBUG: Passed lgdt3306a_probe 2360 240 | [ 560.601410] si2157 12-0062: Silicon Labs Si2147/2148/2157/2158 successfully attached 241 | [ 560.610075] DVB: registering new adapter (em28174 #1) 242 | [ 560.615721] usb 1-3: DVB: registering adapter 1 frontend 0 (LG Electronics LGDT3306A VSB/QAM Frontend)... 243 | [ 560.627161] em28174 #1: DVB extension successfully initialized 244 | [ 562.882976] si2157 12-0062: found a 'Silicon Labs Si2157-A30' 245 | [ 562.939717] si2157 12-0062: firmware version: 3.0.5 246 | [ 562.945214] usb 1-3: DVB: adapter 1 frontend 0 frequency 0 out of range (55000000..858000000) 247 | ``` 248 | 249 | And the following USB devices with associated modules (ID may vary depending if connected using the front or back USB ports): 250 | ``` 251 | $ lsusb -Ic 252 | |__usb1 1d6b:0002:0404 09 2.00 480MBit/s 0mA 1IF (Linux 4.4.59+ xhci-hcd xHCI Host Controller 0000:00:15.0) 253 | 1-0:1.0 (IF) 09:00:00 1EP () hub 254 | |__1-1 2040:026d:0100 00 2.00 480MBit/s 500mA 1IF (HCW 955D 0011584195) 255 | 1-1:1.0 (IF) ff:00:00 2EPs () em28xx 256 | |__1-4 f400:f400:0100 00 2.00 480MBit/s 200mA 1IF (Synology DiskStation 6500794064E41636) 257 | 1-4:1.0 (IF) 08:06:50 2EPs () usb-storage host5 (synoboot) 258 | |__usb2 1d6b:0003:0404 09 3.00 5000MBit/s 0mA 1IF (Linux 4.4.59+ xhci-hcd xHCI Host Controller 0000:00:15.0) 259 | 2-0:1.0 (IF) 09:00:00 1EP () hub 260 | ``` 261 | 262 | Now reboot the NAS using the admin web page and confirm after reboot that the dmesg output and lsusb are still ok. 263 | 264 | In case you run into issue where your NAS refuses to fully shutdown (and thus reboot) with the power button led blinking, it is most probably due to tainted modules still in memory. Using the hauppauge-unload.sh script prior to shutdown/reboot will remove all the tainted modules from memory thus allowing the NAS to properly shutdown/reboot. 265 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # synology - th0ma7 2 | Synology personnal hack, info, tools & source code 3 | 4 | Donnations welcomed at: `0x522d164549E68681dfaC850A2cabdb95686C1fEC` 5 | 6 | # Hauppauge WinTV DualHD HWC 955D 7 | The following allows building kernel modules for the Hauppauge WinTV DualHD HWC 955D media adapter allowing to use TVheadEnd (TVH) natively within the NAS. 8 | * https://www.linuxtv.org/wiki/index.php/Hauppauge_WinTV-HVR-955Q 9 | 10 | In theory this procedure is also valid to build most supported DVB adaptors available from the Media Tree within the Linux Media Subsystem. 11 | * https://linuxtv.org/wiki/index.php/ATSC_USB_devices 12 | * https://linuxtv.org/wiki/index.php/DVB-C_USB_Devices 13 | 14 | Tested on the following hardware: 15 | * model: DS918+ 16 | * OS: DSM 6.2.2 build #24922 17 | * kernel: 4.4.59+ 18 | * arch: x86_64 19 | * core name: Apollo Lake 20 | 21 | Finding your running kernel: 22 | ``` 23 | $ uname -mvr 24 | 4.4.59+ #24922 SMP PREEMPT Thu Mar 28 11:07:03 CST 2019 x86_64 25 | ``` 26 | 27 | Finding your CPU type: 28 | * https://en.wikichip.org/wiki/intel/celeron/j3455 29 | ``` 30 | $ cat /proc/cpuinfo | grep model.name | head -1 31 | model name : Intel(R) Celeron(R) CPU J3455 @ 1.50GHz 32 | ``` 33 | 34 | ## Current status 35 | I had backported patches to the Synology DSM 6.x 4.4.59+ kernel but there where a few pending issues. Since then b-rad-NDi ended-up providing a backporting tool that allows rebuilding the media tree over the Synology DSM kernel. This solution as been playing really nicely on my NAS over the last months. _Big thanks to b-rad-NDi!!!_ 36 | 37 | For more details on b-rad-NDi project refer to: 38 | * https://github.com/b-rad-NDi/Embedded-MediaDrivers 39 | 40 | Working: 41 | - `em28xx`: both tuners detected & firmware loading OK 42 | - `lgdt3306a`: fully functional 43 | 44 | End result: 45 | - `tvheadend`: fully detects both tuners 46 | 47 | Instead of building your own I've made available a pre-built module package for Hauppauge 955D USB DVB dongle to work on Synology NAS 6.2.2 kernel 4.4.59+ with Apollolake CPU (e.g. DS918+): 48 | * https://github.com/th0ma7/synology/raw/master/hauppauge/hauppauge955D-SYNOApollolake-DSM622_24922-Kernel_4.4.59-20190520.tar.bz2 49 | 50 | ## Preparation 51 | Using a Ubuntu 18.04 OS to build the updated modules install a few essential packages: 52 | ``` 53 | $ sudo apt update 54 | $ sudo apt install build-essential ncurses-dev bc libssl-dev libc6-i386 curl libproc-processtable-perl 55 | ``` 56 | 57 | Clone b-rad-NDi git repository: 58 | ``` 59 | $ git clone https://github.com/b-rad-NDi/Embedded-MediaDrivers.git 60 | $ cd Embedded-MediaDrivers 61 | ~/Embedded-MediaDrivers$ 62 | ``` 63 | 64 | Create a `SYNO-Apollolake` download directory: 65 | ``` 66 | $ mkdir dl/SYNO-Apollolake 67 | ``` 68 | 69 | Download the toolchain 70 | * https://sourceforge.net/projects/dsgpl/files/DSM%206.2%20Tool%20Chains/ 71 | ``` 72 | $ wget --content-disposition https://sourceforge.net/projects/dsgpl/files/DSM%206.2%20Tool%20Chains/Intel%20x86%20Linux%204.4.59%20%28Apollolake%29/apollolake-gcc493_glibc220_linaro_x86_64-GPL.txz/download -P dl/SYNO-Apollolake/ 73 | ``` 74 | 75 | Download the Synology DSM kernel sources: 76 | * https://sourceforge.net/projects/dsgpl/files/Synology%20NAS%20GPL%20Source/22259branch/ 77 | ``` 78 | $ wget --content-disposition https://sourceforge.net/projects/dsgpl/files/Synology%20NAS%20GPL%20Source/22259branch/apollolake-source/linux-4.4.x.txz/download -P dl/SYNO-Apollolake/ 79 | ``` 80 | 81 | Initialize the repository: 82 | ``` 83 | $ ./md_builder.sh -i -d SYNO-Apollolake 84 | ``` 85 | 86 | Build a default Synology DSM kernel build (takes a while): 87 | ``` 88 | $ export MAKEOPTS="-j`nproc`" 89 | $ ./md_builder.sh -B media -d SYNO-Apollolake 90 | ``` 91 | 92 | Configure the media tree, get the latest media tree patches that applies over the default Synology DSM kernel and build the media drivers: 93 | ``` 94 | $ ./md_builder.sh -g -d SYNO-Apollolake 95 | $ cd build/SYNOAPOLLOLAKE/media_build 96 | build/SYNOAPOLLOLAKE/media_build$ ./build 97 | ``` 98 | 99 | ## Installation 100 | 101 | Using SSH login as admin on the synology NAS: 102 | ``` 103 | $ ssh admin@ 104 | ``` 105 | 106 | Create a new local module directory (name will match kernel version): 107 | ``` 108 | $ sudo mkdir -p /usr/local/lib/modules/$(uname -r) 109 | $ cd /usr/local/lib/modules/$(uname -r) 110 | ``` 111 | 112 | Download the updated media drivers modules over to the NAS (the following downloads not only the mandatory modules for Hauppauge WinTV but rather all the media tree modules): 113 | ``` 114 | $ cd /usr/local/lib/modules/$(uname -r) 115 | $ sudo scp "username@:~/Embedded-MediaDrivers/build/SYNOAPOLLOLAKE/media_build/v4l/*.ko" . 116 | ``` 117 | 118 | Copy the start/stop/load/reset script to the NAS (and make it executable): 119 | ``` 120 | $ cd /usr/local/lib/modules/$(uname -r) 121 | $ wget https://raw.githubusercontent.com/th0ma7/synology/master/hauppauge.sh 122 | $ chmod 755 hauppauge.sh 123 | ``` 124 | 125 | Create a symbolic link to `/opt/bin/hauppauge.sh` for ease of use: 126 | ``` 127 | $ sudo ln -s -T -f /usr/local/lib/modules/$(uname -r)/hauppauge.sh /opt/bin/hauppauge.sh 128 | ``` 129 | 130 | Create a local rc file locate at `/usr/local/etc/rc.d/media.sh` that will be executed at boot time: 131 | ``` 132 | $ cat << EOF | sudo tee /usr/local/etc/rc.d/media.sh 133 | #!/bin/sh 134 | /usr/local/lib/modules/$(uname -r)/hauppauge.sh load 135 | EOF 136 | $ sudo chmod 755 /usr/local/etc/rc.d/media.sh 137 | ``` 138 | 139 | Execute manually the rc script to confirm there is no error: 140 | ``` 141 | $ sudo /usr/local/etc/rc.d/media.sh 142 | ``` 143 | 144 | Validate the status: 145 | ``` 146 | $ sudo /opt/bin/hauppauge.sh status 147 | Status pkgctl-tvheadend... N/A 148 | kernel module status... 149 | em28xx_dvb OK 150 | em28xx OK 151 | lgdt3306a OK 152 | si2157 OK 153 | tveeprom OK 154 | v4l2_common OK 155 | dvb_usb OK 156 | rc_core OK 157 | dvb_core OK 158 | videobuf2_vmalloc OK 159 | videobuf2_memops OK 160 | videobuf2_v4l2 OK 161 | videobuf2_common OK 162 | videodev OK 163 | media OK 164 | kernel USB (1-3) autosuspend values... 165 | (1-3)autosuspend_delay_ms [-1000] -> OK 166 | (1-3)autosuspend [ -1] -> OK 167 | kernel sysctl values... 168 | vm.dirty_expire_centisecs [ 300] -> OK 169 | vm.swappiness [ 1] -> OK 170 | ``` 171 | 172 | Normally should see something similar in kernel `dmesg`: 173 | ``` 174 | [ 557.806644] em28xx: New device HCW 955D @ 480 Mbps (2040:026d, interface 0, class 0) 175 | [ 557.815308] em28xx: DVB interface 0 found: isoc 176 | [ 557.820423] em28xx: chip ID is em28174 177 | [ 558.939915] em28174 #0: EEPROM ID = 26 00 01 00, EEPROM hash = 0x3d790eca 178 | [ 558.947531] em28174 #0: EEPROM info: 179 | [ 558.951857] em28174 #0: microcode start address = 0x0004, boot configuration = 0x01 180 | [ 558.966683] em28174 #0: AC97 audio (5 sample rates) 181 | [ 558.972234] em28174 #0: 500mA max power 182 | [ 558.976620] em28174 #0: Table at offset 0x27, strings=0x0a72, 0x187c, 0x086a 183 | [ 558.984753] em28174 #0: Identified as Hauppauge WinTV-dualHD 01595 ATSC/QAM (card=100) 184 | [ 558.994647] tveeprom 8-0050: Hauppauge model 204101, rev B2I6, serial# 11584195 185 | [ 559.002824] tveeprom 8-0050: tuner model is SiLabs Si2157 (idx 186, type 4) 186 | [ 559.010649] tveeprom 8-0050: TV standards PAL(B/G) NTSC(M) PAL(I) SECAM(L/L') PAL(D/D1/K) ATSC/DVB Digital (eeprom 0xfc) 187 | [ 559.023133] tveeprom 8-0050: audio processor is None (idx 0) 188 | [ 559.029491] tveeprom 8-0050: has no radio, has IR receiver, has no IR transmitter 189 | [ 559.038167] em28174 #0: dvb set to isoc mode. 190 | [ 559.043177] em28xx: chip ID is em28174 191 | [ 560.162726] em28174 #1: EEPROM ID = 26 00 01 00, EEPROM hash = 0x3d790eca 192 | [ 560.170323] em28174 #1: EEPROM info: 193 | [ 560.174326] em28174 #1: microcode start address = 0x0004, boot configuration = 0x01 194 | [ 560.189064] em28174 #1: AC97 audio (5 sample rates) 195 | [ 560.194613] em28174 #1: 500mA max power 196 | [ 560.199009] em28174 #1: Table at offset 0x27, strings=0x0a72, 0x187c, 0x086a 197 | [ 560.207139] em28174 #1: Identified as Hauppauge WinTV-dualHD 01595 ATSC/QAM (card=100) 198 | [ 560.216915] tveeprom 10-0050: Hauppauge model 204101, rev B2I6, serial# 11584195 199 | [ 560.225192] tveeprom 10-0050: tuner model is SiLabs Si2157 (idx 186, type 4) 200 | [ 560.233070] tveeprom 10-0050: TV standards PAL(B/G) NTSC(M) PAL(I) SECAM(L/L') PAL(D/D1/K) ATSC/DVB Digital (eeprom 0xfc) 201 | [ 560.245327] tveeprom 10-0050: audio processor is None (idx 0) 202 | [ 560.251757] tveeprom 10-0050: has no radio, has IR receiver, has no IR transmitter 203 | [ 560.260220] em28xx: dvb ts2 set to isoc mode. 204 | [ 560.465298] em28174 #0: Binding DVB extension 205 | [ 560.476140] i2c i2c-8: Added multiplexed i2c bus 11 206 | [ 560.501921] lgdt3306a 8-0059: LG Electronics LGDT3306A successfully identified 207 | [ 560.509994] DEBUG: Passed lgdt3306a_probe 2360 208 | [ 560.517015] si2157 11-0060: Silicon Labs Si2147/2148/2157/2158 successfully attached 209 | [ 560.525695] DVB: registering new adapter (em28174 #0) 210 | [ 560.531352] usb 1-3: DVB: registering adapter 0 frontend 0 (LG Electronics LGDT3306A VSB/QAM Frontend)... 211 | [ 560.544142] em28174 #0: DVB extension successfully initialized 212 | [ 560.550672] em28174 #1: Binding DVB extension 213 | [ 560.560027] i2c i2c-10: Added multiplexed i2c bus 12 214 | [ 560.585962] lgdt3306a 10-000e: LG Electronics LGDT3306A successfully identified 215 | [ 560.601410] si2157 12-0062: Silicon Labs Si2147/2148/2157/2158 successfully attached 216 | [ 560.610075] DVB: registering new adapter (em28174 #1) 217 | [ 560.615721] usb 1-3: DVB: registering adapter 1 frontend 0 (LG Electronics LGDT3306A VSB/QAM Frontend)... 218 | [ 560.627161] em28174 #1: DVB extension successfully initialized 219 | [ 562.882976] si2157 12-0062: found a 'Silicon Labs Si2157-A30' 220 | [ 562.939717] si2157 12-0062: firmware version: 3.0.5 221 | [ 562.945214] usb 1-3: DVB: adapter 1 frontend 0 frequency 0 out of range (55000000..858000000) 222 | ``` 223 | 224 | And the following USB devices with associated modules (ID may vary depending if connected using the front or back USB ports): 225 | ``` 226 | $ lsusb -Ic 227 | |__usb1 1d6b:0002:0404 09 2.00 480MBit/s 0mA 1IF (Linux 4.4.59+ xhci-hcd xHCI Host Controller 0000:00:15.0) 228 | 1-0:1.0 (IF) 09:00:00 1EP () hub 229 | |__1-1 2040:026d:0100 00 2.00 480MBit/s 500mA 1IF (HCW 955D 0011584195) 230 | 1-1:1.0 (IF) ff:00:00 2EPs () em28xx 231 | |__1-4 f400:f400:0100 00 2.00 480MBit/s 200mA 1IF (Synology DiskStation 6500794064E41636) 232 | 1-4:1.0 (IF) 08:06:50 2EPs () usb-storage host5 (synoboot) 233 | |__usb2 1d6b:0003:0404 09 3.00 5000MBit/s 0mA 1IF (Linux 4.4.59+ xhci-hcd xHCI Host Controller 0000:00:15.0) 234 | 2-0:1.0 (IF) 09:00:00 1EP () hub 235 | ``` 236 | 237 | Now reboot the NAS using the admin web page and confirm after reboot that the dmesg output and lsusb are still ok. 238 | 239 | In case you run into issue where your NAS refuses to fully shutdown (and thus reboot) with the power button led blinking, it is most probably due to tainted modules still in memory. Running `hauppauge.sh stop` prior to shutdown/reboot will remove all the tainted modules from memory thus allowing the NAS to properly shutdown/reboot. 240 | 241 | --- 242 | 243 | # hauppauge.sh 244 | This script is intended to provide a simple method to start|stop|restart the various perequesites into getting media modules loaded onto the Synology NAS. 245 | 246 | Basicaly what the script does: 247 | 1. Load all the necessary modules 248 | 2. Disable USB autosuspend over the Hauppauge USB ID 249 | 3. Injects a few kernel `sysctl` for optmizations 250 | 4. Starts TVH (service name `pkgctl-tvheadend`) 251 | 252 | ## Modules 253 | The script uses `insmod` to load|unload the modules into the appropriate order. The `MODULES` parameter in the script can be adapted as needed for other DVB dongles than the Hauppauge WinTV 955D. 254 | 255 | |Order | Module | `rmmod` | 256 | |:----:|:----------------------:|:-------------------:| 257 | | 1 | `media.ko` | `media` | 258 | | 2 | `videodev.ko` | `videodev` | 259 | | 3 | `videobuf2-common.ko` | `videobuf2_common` | 260 | | 4 | `videobuf2-v4l2.ko` | `videobuf2_v4l2` | 261 | | 5 | `videobuf2-memops.ko` | `videobuf2_memops` | 262 | | 6 | `videobuf2-vmalloc.ko` | `videobuf2_vmalloc` | 263 | | 7 | `dvb-core.ko` | `dvb_core` | 264 | | 8 | `rc-core.ko` | `rc_core` | 265 | | 9 | `dvb-usb.ko` | `dvb_usb` | 266 | | 10 | `v4l2-common.ko` | `v4l2_common` | 267 | | 11 | `tveeprom.ko` | `tveeprom` | 268 | | 12 | `si2157.ko` | `si2157` | 269 | | 13 | `lgdt3306a.ko` | `lgdt3306a` | 270 | | 14 | `em28xx.ko` | `em28xx` | 271 | | 15 | `em28xx-dvb.ko` | `em28xx_dvb` | 272 | 273 | ## Options 274 | **start:** Does a full start including: 275 | 1. loading all the modules 276 | 2. disabling USB autosuspend 277 | 3. `sysctl` adjustments 278 | 4. TVH startup 279 | 280 | **stop:** Does a stop which basicaly is: 281 | 1. TVH shutdown 282 | 2. Unloading all the modules 283 | 284 | **restart:** Basically performs a `stop` then `start`. 285 | 286 | **reset:** This is usefull when hitting BUGS with TVH such as OOM killer where the tvheadend service is being killed by the system. The `reset` option reduces to the minimal the impact over the already loaded modules by resetting only the DVB frontend module such as: 287 | 1. TVH shutdown (forces it if needed) 288 | 2. unload `em28xx_dvb` 289 | 3. load of `em28xx-dvb.ko` 290 | 4. TVH startup 291 | 292 | **load:** This is the option to be used at NAS startup. It basically does all the same things as the `start` option without the TVH startup as it's being managed by the Synology DSM stack automatically. 293 | 294 | **status:** This provides a view on all things namely modules loaded into memory, USB autosuspend, `sysctl` adjustments and TVH service status including it's PID. 295 | -------------------------------------------------------------------------------- /hauppauge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #------------------------------------------- 4 | # hauppauge.sh 5 | # 6 | # by: Vincent Fortier 7 | # email: th0ma7_AT_gmail.com 8 | # 9 | # Simplify the status, start, stop, reset 10 | # of tvheadend service along with loading 11 | # and unloading of all necessary modules 12 | #------------------------------------------- 13 | 14 | SERVICE="pkgctl-tvheadend" 15 | MODULE_PATH=/usr/local/lib/modules/$(uname -r) 16 | MODULES="em28xx_dvb em28xx lgdt3306a si2157 tveeprom v4l2_common dvb_usb rc_core dvb_core videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_common videodev media" 17 | RESET=em28xx_dvb 18 | # 19 | declare -a SYSCTL_VAR=('vm.dirty_expire_centisecs' 'vm.swappiness') 20 | declare -a SYSCTL_VALUE=('300' '1') 21 | # 22 | NOAUTOSUSPEND=em28xx 23 | declare -a AUTOSUSPEND_VAR=('autosuspend_delay_ms' 'autosuspend') 24 | declare -a AUTOSUSPEND_VALUE=('-1000' '-1') 25 | 26 | USBAutoSuspend() { 27 | usbID=$(lsusb -i | grep $NOAUTOSUSPEND | awk '{print $1}' | cut -f1 -d:) 28 | if [ ! "$usbID" ]; then 29 | echo "kernel USB (none) autosuspend values N/A" 30 | else 31 | echo "kernel USB ($usbID) autosuspend values..." 32 | for index in "${!AUTOSUSPEND_VAR[@]}" 33 | do 34 | declare sys=/sys/bus/usb/devices/$usbID/power/${AUTOSUSPEND_VAR[$index]} 35 | declare -i current=$(cat $sys) 36 | declare -i new=${AUTOSUSPEND_VALUE[$index]} 37 | 38 | printf '\t(%s)%-25s' $usbID ${AUTOSUSPEND_VAR[$index]} 39 | 40 | if [ $current -eq $new ]; then 41 | printf '[%5s] -> OK\n' "$current" 42 | else 43 | [ "$1" = "check" ] || echo ${AUTOSUSPEND_VALUE[$index]} | sudo tee $sys 1>/dev/null 44 | printf '[%5s] -> [%5s]\n' "$current" "$new" 45 | fi 46 | done 47 | fi 48 | } 49 | 50 | Sysctl() { 51 | echo "kernel sysctl values... " 52 | for index in "${!SYSCTL_VAR[@]}" 53 | do 54 | declare -i current=$(sysctl -n ${SYSCTL_VAR[$index]}) 55 | declare -i new=${SYSCTL_VALUE[$index]} 56 | 57 | printf '\t%-30s' ${SYSCTL_VAR[$index]} 58 | if [ $current -eq $new ]; then 59 | printf '[%5s] -> OK\n' "$current" 60 | else 61 | [ "$1" = "check" ] || sysctl -w ${SYSCTL_VAR[$index]}=$new 2>/dev/null 1>&2 62 | printf '[%5s] -> [%5s]\n' "$current" "$new" 63 | fi 64 | done 65 | } 66 | 67 | ModuleLOAD() { 68 | echo "Loading kernel modules... " 69 | for item in $MODULES; do echo $item; done | tac | while read module 70 | do 71 | module_load=$(echo "${module}.ko" | sed 's/_/-/g') 72 | printf '\t%-30s' $module_load 73 | status=$(lsmod | grep "^$module ") 74 | 75 | if [ $? -eq 0 -a "status" ]; then 76 | echo "Loaded" 77 | else 78 | insmod $MODULE_PATH/$module_load 79 | [ $? -eq 0 ] && echo "OK" || echo "ERROR" 80 | fi 81 | done 82 | } 83 | 84 | ModuleUNLOAD() { 85 | # Unload Hauppauge updated drivers 86 | echo "Unloading kernel modules... " 87 | for module in $MODULES 88 | do 89 | printf '\t%-30s' $module 90 | 91 | status=$(lsmod | grep "^$module ") 92 | if [ $? -eq 0 -a "status" ]; then 93 | rmmod $module 94 | echo -ne "OK\n" 95 | else 96 | echo -ne "N/A\n" 97 | fi 98 | done 99 | } 100 | 101 | ModuleSTATUS() { 102 | # Unload Hauppauge updated drivers 103 | echo "kernel module status... " 104 | for module in $MODULES 105 | do 106 | printf '\t%-30s' $module 107 | 108 | status=$(lsmod | grep "^$module ") 109 | if [ $? -eq 0 -a "status" ]; then 110 | echo -ne "OK\n" 111 | else 112 | echo -ne "N/A\n" 113 | fi 114 | done 115 | } 116 | 117 | ModuleRESET() { 118 | reset=$1 119 | module=$(echo "${reset}.ko" | sed 's/_/-/g') 120 | rmmod $reset 121 | sleep 1 122 | insmod $MODULE_PATH/$module 123 | } 124 | 125 | ServiceSTATUS() { 126 | status=$(synoservice --status $SERVICE | grep "\[$SERVICE\] status" | awk -F"status=" '{print $2}' | sed -e 's/\[//g' -e 's/\]//g') 127 | running=$(synoservice --status $SERVICE | grep "\[$SERVICE\] is" | awk -F"is " '{print $2}' | sed -e 's/\.//g' -e 's/ //g') 128 | pid=$(pidof tvheadend) 129 | [ ! "$pid" ] && pid="---" 130 | 131 | case "$1" in 132 | "full" ) printf '%-38s' "Status $SERVICE..." 133 | echo $status,$running,$pid 134 | ;; 135 | * ) echo $running;; 136 | esac 137 | } 138 | 139 | ServiceSTART() { 140 | status=$(ServiceSTATUS) 141 | #echo $status 1>&2 142 | printf '%-38s' "Starting $SERVICE..." 143 | 144 | module=$(lsmod | grep "^$RESET ") 145 | if [ $? -ne 0 -a ! "module" ]; then 146 | echo "ERROR module $RESET not found!" 147 | return 148 | fi 149 | 150 | if [ "$status" = "stop" ]; then 151 | synoservice --start $SERVICE 152 | echo "OK" 153 | elif [ "$status" = "start" ]; then 154 | # Check if sevice isn't already started! 155 | if [ "$(pidof tvheadend)" ]; then 156 | echo "Started" 157 | else 158 | synoservice --restart $SERVICE 2>/dev/null 1>&2 159 | echo "Restart" 160 | fi 161 | else 162 | echo "N/A" 163 | fi 164 | } 165 | 166 | ServiceSTOP() { 167 | status=$(ServiceSTATUS) 168 | #echo $status 1>&2 169 | printf '%-38s' "Stopping $SERVICE..." 170 | if [ "$status" = "start" ]; then 171 | #synoservice --disable $SERVICE 172 | synoservice --stop $SERVICE 2>/dev/null 1>&2 173 | echo "OK" 174 | else 175 | echo "N/A" 176 | fi 177 | 178 | # Is it really off? 179 | if [ "`pidof tvheadend`" ]; then 180 | printf '%-33s' "Killing $SERVICE..." 181 | kill -9 $(pidof tvheadend) 182 | echo "killed" 183 | fi 184 | } 185 | 186 | Usage() { 187 | echo "$0 - Usage: start, stop, status, reset, restart, load" 188 | } 189 | 190 | case $1 in 191 | start ) ModuleLOAD 192 | USBAutoSuspend 193 | Sysctl 194 | ServiceSTART 195 | ;; 196 | stop ) ServiceSTOP 197 | ModuleUNLOAD 198 | ;; 199 | status ) ServiceSTATUS full 200 | ModuleSTATUS 201 | USBAutoSuspend check 202 | Sysctl check 203 | ;; 204 | restart ) ServiceSTOP 205 | ModuleUNLOAD 206 | sleep 1 207 | ModuleLOAD 208 | USBAutoSuspend 209 | Sysctl 210 | ServiceSTART 211 | ;; 212 | reset ) ServiceSTOP 213 | ModuleRESET $RESET 214 | ServiceSTART 215 | ServiceSTATUS full 216 | ModuleSTATUS 217 | ;; 218 | load ) ModuleLOAD 219 | USBAutoSuspend 220 | Sysctl 221 | ;; 222 | * ) Usage 223 | ;; 224 | esac 225 | 226 | exit 0 227 | -------------------------------------------------------------------------------- /hauppauge/001-Hauppauge955D-lgdt3306a-v3.patch: -------------------------------------------------------------------------------- 1 | diff -uprN linux-4.4.x-orig/drivers/media/dvb-frontends/lgdt3306a.c linux-4.4.x-new/drivers/media/dvb-frontends/lgdt3306a.c 2 | --- linux-4.4.x-orig/drivers/media/dvb-frontends/lgdt3306a.c 2017-10-30 17:45:14.000000000 -0400 3 | +++ linux-4.4.x-new/drivers/media/dvb-frontends/lgdt3306a.c 2019-05-13 20:41:32.123976946 -0400 4 | @@ -16,17 +16,31 @@ 5 | * GNU General Public License for more details. 6 | */ 7 | 8 | +#undef pr_fmt 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 | 11 | #include 12 | +#include 13 | #include 14 | #include "dvb_math.h" 15 | #include "lgdt3306a.h" 16 | +#include 17 | 18 | static int debug; 19 | module_param(debug, int, 0644); 20 | MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))"); 21 | 22 | +/* 23 | + * Older drivers treated QAM64 and QAM256 the same; that is the HW always 24 | + * used "Auto" mode during detection. Setting "forced_manual"=1 allows 25 | + * the user to treat these modes as separate. For backwards compatibility, 26 | + * it's off by default. QAM_AUTO can now be specified to achive that 27 | + * effect even if "forced_manual"=1 28 | + */ 29 | +static int forced_manual; 30 | +module_param(forced_manual, int, 0644); 31 | +MODULE_PARM_DESC(forced_manual, "if set, QAM64 and QAM256 will only lock to modulation specified"); 32 | + 33 | #define DBG_INFO 1 34 | #define DBG_REG 2 35 | #define DBG_DUMP 4 /* FGR - comment out to remove dump code */ 36 | @@ -55,6 +69,8 @@ MODULE_PARM_DESC(debug, "set debug level 37 | __ret; \ 38 | }) 39 | 40 | +#define MHz 1000000 41 | + 42 | struct lgdt3306a_state { 43 | struct i2c_adapter *i2c_adap; 44 | const struct lgdt3306a_config *cfg; 45 | @@ -558,7 +574,12 @@ static int lgdt3306a_set_qam(struct lgdt 46 | /* 3. : 64QAM/256QAM detection(manual, auto) */ 47 | ret = lgdt3306a_read_reg(state, 0x0009, &val); 48 | val &= 0xfc; 49 | - val |= 0x02; /* STDOPDETCMODE[1:0]=1=Manual 2=Auto */ 50 | + /* Check for forced Manual modulation modes; otherwise always "auto" */ 51 | + if(forced_manual && (modulation != QAM_AUTO)){ 52 | + val |= 0x01; /* STDOPDETCMODE[1:0]= 1=Manual */ 53 | + } else { 54 | + val |= 0x02; /* STDOPDETCMODE[1:0]= 2=Auto */ 55 | + } 56 | ret = lgdt3306a_write_reg(state, 0x0009, val); 57 | if (lg_chkerr(ret)) 58 | goto fail; 59 | @@ -590,6 +611,28 @@ static int lgdt3306a_set_qam(struct lgdt 60 | if (lg_chkerr(ret)) 61 | goto fail; 62 | 63 | + /* 5.1 V0.36 SRDCHKALWAYS : For better QAM detection */ 64 | + ret = lgdt3306a_read_reg(state, 0x000a, &val); 65 | + val &= 0xfd; 66 | + val |= 0x02; 67 | + ret = lgdt3306a_write_reg(state, 0x000a, val); 68 | + if (lg_chkerr(ret)) 69 | + goto fail; 70 | + 71 | + /* 5.2 V0.36 Control of "no signal" detector function */ 72 | + ret = lgdt3306a_read_reg(state, 0x2849, &val); 73 | + val &= 0xdf; 74 | + ret = lgdt3306a_write_reg(state, 0x2849, val); 75 | + if (lg_chkerr(ret)) 76 | + goto fail; 77 | + 78 | + /* 5.3 Fix for Blonder Tongue HDE-2H-QAM and AQM modulators */ 79 | + ret = lgdt3306a_read_reg(state, 0x302b, &val); 80 | + val &= 0x7f; /* SELFSYNCFINDEN_CQS=0; disable auto reset */ 81 | + ret = lgdt3306a_write_reg(state, 0x302b, val); 82 | + if (lg_chkerr(ret)) 83 | + goto fail; 84 | + 85 | /* 6. Reset */ 86 | ret = lgdt3306a_soft_reset(state); 87 | if (lg_chkerr(ret)) 88 | @@ -612,10 +655,9 @@ static int lgdt3306a_set_modulation(stru 89 | ret = lgdt3306a_set_vsb(state); 90 | break; 91 | case QAM_64: 92 | - ret = lgdt3306a_set_qam(state, QAM_64); 93 | - break; 94 | case QAM_256: 95 | - ret = lgdt3306a_set_qam(state, QAM_256); 96 | + case QAM_AUTO: 97 | + ret = lgdt3306a_set_qam(state, p->modulation); 98 | break; 99 | default: 100 | return -EINVAL; 101 | @@ -642,6 +684,7 @@ static int lgdt3306a_agc_setup(struct lg 102 | break; 103 | case QAM_64: 104 | case QAM_256: 105 | + case QAM_AUTO: 106 | break; 107 | default: 108 | return -EINVAL; 109 | @@ -696,6 +739,7 @@ static int lgdt3306a_spectral_inversion( 110 | break; 111 | case QAM_64: 112 | case QAM_256: 113 | + case QAM_AUTO: 114 | /* Auto ok for QAM */ 115 | ret = lgdt3306a_set_inversion_auto(state, 1); 116 | break; 117 | @@ -719,6 +763,7 @@ static int lgdt3306a_set_if(struct lgdt3 118 | break; 119 | case QAM_64: 120 | case QAM_256: 121 | + case QAM_AUTO: 122 | if_freq_khz = state->cfg->qam_if_khz; 123 | break; 124 | default: 125 | @@ -727,7 +772,7 @@ static int lgdt3306a_set_if(struct lgdt3 126 | 127 | switch (if_freq_khz) { 128 | default: 129 | - pr_warn("IF=%d KHz is not supportted, 3250 assumed\n", 130 | + pr_warn("IF=%d KHz is not supported, 3250 assumed\n", 131 | if_freq_khz); 132 | /* fallthrough */ 133 | case 3250: /* 3.25Mhz */ 134 | @@ -1577,6 +1622,7 @@ static int lgdt3306a_read_status(struct 135 | switch (state->current_modulation) { 136 | case QAM_256: 137 | case QAM_64: 138 | + case QAM_AUTO: 139 | if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) { 140 | *status |= FE_HAS_VITERBI; 141 | *status |= FE_HAS_SYNC; 142 | @@ -1619,6 +1665,7 @@ static int lgdt3306a_read_signal_strengt 143 | * Calculate some sort of "strength" from SNR 144 | */ 145 | struct lgdt3306a_state *state = fe->demodulator_priv; 146 | + u8 val; 147 | u16 snr; /* snr_x10 */ 148 | int ret; 149 | u32 ref_snr; /* snr*100 */ 150 | @@ -1631,11 +1678,15 @@ static int lgdt3306a_read_signal_strengt 151 | ref_snr = 1600; /* 16dB */ 152 | break; 153 | case QAM_64: 154 | - ref_snr = 2200; /* 22dB */ 155 | - break; 156 | case QAM_256: 157 | - ref_snr = 2800; /* 28dB */ 158 | - break; 159 | + case QAM_AUTO: 160 | + /* need to know actual modulation to set proper SNR baseline */ 161 | + lgdt3306a_read_reg(state, 0x00a6, &val); 162 | + if(val & 0x04) 163 | + ref_snr = 2800; /* QAM-256 28dB */ 164 | + else 165 | + ref_snr = 2200; /* QAM-64 22dB */ 166 | + break; 167 | default: 168 | return -EINVAL; 169 | } 170 | @@ -1729,27 +1780,19 @@ static int lgdt3306a_get_tune_settings(s 171 | return 0; 172 | } 173 | 174 | -static int lgdt3306a_search(struct dvb_frontend *fe) 175 | +static enum dvbfe_search lgdt3306a_search(struct dvb_frontend *fe) 176 | { 177 | enum fe_status status = 0; 178 | - int i, ret; 179 | + int ret; 180 | 181 | /* set frontend */ 182 | ret = lgdt3306a_set_parameters(fe); 183 | if (ret) 184 | goto error; 185 | 186 | - /* wait frontend lock */ 187 | - for (i = 20; i > 0; i--) { 188 | - dbg_info(": loop=%d\n", i); 189 | - msleep(50); 190 | - ret = lgdt3306a_read_status(fe, &status); 191 | - if (ret) 192 | - goto error; 193 | - 194 | - if (status & FE_HAS_LOCK) 195 | - break; 196 | - } 197 | + ret = lgdt3306a_read_status(fe, &status); 198 | + if (ret) 199 | + goto error; 200 | 201 | /* check if we have a valid signal */ 202 | if (status & FE_HAS_LOCK) 203 | @@ -1770,7 +1813,7 @@ static void lgdt3306a_release(struct dvb 204 | kfree(state); 205 | } 206 | 207 | -static struct dvb_frontend_ops lgdt3306a_ops; 208 | +static const struct dvb_frontend_ops lgdt3306a_ops; 209 | 210 | struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config, 211 | struct i2c_adapter *i2c_adap) 212 | @@ -2072,7 +2115,7 @@ static const short regtab[] = { 213 | 0x30aa, /* MPEGLOCK */ 214 | }; 215 | 216 | -#define numDumpRegs (sizeof(regtab)/sizeof(regtab[0])) 217 | +#define numDumpRegs (ARRAY_SIZE(regtab)) 218 | static u8 regval1[numDumpRegs] = {0, }; 219 | static u8 regval2[numDumpRegs] = {0, }; 220 | 221 | @@ -2104,14 +2147,14 @@ static void lgdt3306a_DumpRegs(struct lg 222 | } 223 | #endif /* DBG_DUMP */ 224 | 225 | -static struct dvb_frontend_ops lgdt3306a_ops = { 226 | +static const struct dvb_frontend_ops lgdt3306a_ops = { 227 | .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B }, 228 | .info = { 229 | .name = "LG Electronics LGDT3306A VSB/QAM Frontend", 230 | - .frequency_min = 54000000, 231 | - .frequency_max = 858000000, 232 | - .frequency_stepsize = 62500, 233 | - .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB 234 | + .frequency_min = 54 * MHz, 235 | + .frequency_max = 858 * MHz, 236 | + .frequency_stepsize = 62500, 237 | + .caps = FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB 238 | }, 239 | .i2c_gate_ctrl = lgdt3306a_i2c_gate_ctrl, 240 | .init = lgdt3306a_init, 241 | @@ -2132,6 +2175,234 @@ static struct dvb_frontend_ops lgdt3306a 242 | .search = lgdt3306a_search, 243 | }; 244 | 245 | +/* 246 | + * I2C gate logic 247 | + * We must use unlocked I2C I/O because I2C adapter lock is already taken 248 | + * by the caller (usually tuner driver). 249 | + * select/unselect are unlocked versions of lgdt3306a_i2c_gate_ctrl 250 | + */ 251 | +static int lgdt3306a_select(struct i2c_adapter *adap, void *mux_priv, u32 chan) 252 | +{ 253 | + struct i2c_client *client = mux_priv; 254 | + int ret; 255 | + u8 val; 256 | + u8 buf[3]; 257 | + 258 | + struct i2c_msg read_msg_1 = { 259 | + .addr = client->addr, 260 | + .flags = 0, 261 | + .buf = "\x00\x02", 262 | + .len = 2, 263 | + }; 264 | + struct i2c_msg read_msg_2 = { 265 | + .addr = client->addr, 266 | + .flags = I2C_M_RD, 267 | + .buf = &val, 268 | + .len = 1, 269 | + }; 270 | + 271 | + struct i2c_msg write_msg = { 272 | + .addr = client->addr, 273 | + .flags = 0, 274 | + .len = 3, 275 | + .buf = buf, 276 | + }; 277 | + 278 | + ret = __i2c_transfer(client->adapter, &read_msg_1, 1); 279 | + if (ret != 1) 280 | + { 281 | + pr_err("error (addr %02x reg 0x002 error (ret == %i)\n", 282 | + client->addr, ret); 283 | + if (ret < 0) 284 | + return ret; 285 | + else 286 | + return -EREMOTEIO; 287 | + } 288 | + 289 | + ret = __i2c_transfer(client->adapter, &read_msg_2, 1); 290 | + if (ret != 1) 291 | + { 292 | + pr_err("error (addr %02x reg 0x002 error (ret == %i)\n", 293 | + client->addr, ret); 294 | + if (ret < 0) 295 | + return ret; 296 | + else 297 | + return -EREMOTEIO; 298 | + } 299 | + 300 | + buf[0] = 0x00; 301 | + buf[1] = 0x02; 302 | + val &= 0x7F; 303 | + val |= LG3306_TUNERI2C_ON; 304 | + buf[2] = val; 305 | + ret = __i2c_transfer(client->adapter, &write_msg, 1); 306 | + if (ret != 1) { 307 | + pr_err("error (addr %02x %02x <- %02x, err = %i)\n", 308 | + write_msg.buf[0], write_msg.buf[1], write_msg.buf[2], ret); 309 | + if (ret < 0) 310 | + return ret; 311 | + else 312 | + return -EREMOTEIO; 313 | + } 314 | + return 0; 315 | +} 316 | + 317 | +static int lgdt3306a_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan) 318 | +{ 319 | + struct i2c_client *client = mux_priv; 320 | + int ret; 321 | + u8 val; 322 | + u8 buf[3]; 323 | + 324 | + struct i2c_msg read_msg_1 = { 325 | + .addr = client->addr, 326 | + .flags = 0, 327 | + .buf = "\x00\x02", 328 | + .len = 2, 329 | + }; 330 | + struct i2c_msg read_msg_2 = { 331 | + .addr = client->addr, 332 | + .flags = I2C_M_RD, 333 | + .buf = &val, 334 | + .len = 1, 335 | + }; 336 | + 337 | + struct i2c_msg write_msg = { 338 | + .addr = client->addr, 339 | + .flags = 0, 340 | + .len = 3, 341 | + .buf = buf, 342 | + }; 343 | + 344 | + ret = __i2c_transfer(client->adapter, &read_msg_1, 1); 345 | + if (ret != 1) 346 | + { 347 | + pr_err("error (addr %02x reg 0x002 error (ret == %i)\n", 348 | + client->addr, ret); 349 | + if (ret < 0) 350 | + return ret; 351 | + else 352 | + return -EREMOTEIO; 353 | + } 354 | + 355 | + ret = __i2c_transfer(client->adapter, &read_msg_2, 1); 356 | + if (ret != 1) 357 | + { 358 | + pr_err("error (addr %02x reg 0x002 error (ret == %i)\n", 359 | + client->addr, ret); 360 | + if (ret < 0) 361 | + return ret; 362 | + else 363 | + return -EREMOTEIO; 364 | + } 365 | + 366 | + buf[0] = 0x00; 367 | + buf[1] = 0x02; 368 | + val &= 0x7F; 369 | + val |= LG3306_TUNERI2C_OFF; 370 | + buf[2] = val; 371 | + ret = __i2c_transfer(client->adapter, &write_msg, 1); 372 | + if (ret != 1) { 373 | + pr_err("error (addr %02x %02x <- %02x, err = %i)\n", 374 | + write_msg.buf[0], write_msg.buf[1], write_msg.buf[2], ret); 375 | + if (ret < 0) 376 | + return ret; 377 | + else 378 | + return -EREMOTEIO; 379 | + } 380 | + return 0; 381 | +} 382 | + 383 | +static int lgdt3306a_probe(struct i2c_client *client, 384 | + const struct i2c_device_id *id) 385 | +{ 386 | + struct lgdt3306a_config *config; 387 | + struct lgdt3306a_state *state; 388 | + struct dvb_frontend *fe; 389 | + int ret; 390 | + 391 | + config = kmemdup(client->dev.platform_data, 392 | + sizeof(struct lgdt3306a_config), GFP_KERNEL); 393 | + if (config == NULL) { 394 | + ret = -ENOMEM; 395 | + goto fail; 396 | + } 397 | + 398 | + config->i2c_addr = client->addr; 399 | + fe = lgdt3306a_attach(config, client->adapter); 400 | + if (fe == NULL) { 401 | + ret = -ENODEV; 402 | + goto err_fe; 403 | + } 404 | + 405 | + i2c_set_clientdata(client, fe->demodulator_priv); 406 | + state = fe->demodulator_priv; 407 | + state->frontend.ops.release = NULL; 408 | + 409 | + /* create mux i2c adapter for tuner */ 410 | + state->i2c_adap = i2c_add_mux_adapter(client->adapter, &client->dev, 411 | + client, 0, 0, 0, lgdt3306a_select, lgdt3306a_deselect); 412 | + if (state->i2c_adap == NULL) { 413 | + ret = -ENODEV; 414 | + goto err_kfree; 415 | + } 416 | + 417 | + /* create dvb_frontend */ 418 | + printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); 419 | + fe->ops.i2c_gate_ctrl = NULL; 420 | + printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); 421 | + *config->i2c_adapter = state->i2c_adap; 422 | + printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); 423 | + *config->fe = fe; 424 | + printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); 425 | + 426 | + dev_info(&client->dev, "LG Electronics LGDT3306A successfully identified\n"); 427 | + printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); 428 | + 429 | + return 0; 430 | + 431 | +err_kfree: 432 | + kfree(state); 433 | +err_fe: 434 | + kfree(config); 435 | +fail: 436 | + dev_warn(&client->dev, "probe failed = %d\n", ret); 437 | + return ret; 438 | +} 439 | + 440 | +static int lgdt3306a_remove(struct i2c_client *client) 441 | +{ 442 | + struct lgdt3306a_state *state = i2c_get_clientdata(client); 443 | + 444 | + i2c_del_mux_adapter(state->i2c_adap); 445 | + 446 | + state->frontend.ops.release = NULL; 447 | + state->frontend.demodulator_priv = NULL; 448 | + 449 | + kfree(state->cfg); 450 | + kfree(state); 451 | + 452 | + return 0; 453 | +} 454 | + 455 | +static const struct i2c_device_id lgdt3306a_id_table[] = { 456 | + {"lgdt3306a", 0}, 457 | + {} 458 | +}; 459 | +MODULE_DEVICE_TABLE(i2c, lgdt3306a_id_table); 460 | + 461 | +static struct i2c_driver lgdt3306a_driver = { 462 | + .driver = { 463 | + .name = "lgdt3306a", 464 | + .suppress_bind_attrs = true, 465 | + }, 466 | + .probe = lgdt3306a_probe, 467 | + .remove = lgdt3306a_remove, 468 | + .id_table = lgdt3306a_id_table, 469 | +}; 470 | + 471 | +module_i2c_driver(lgdt3306a_driver); 472 | + 473 | MODULE_DESCRIPTION("LG Electronics LGDT3306A ATSC/QAM-B Demodulator Driver"); 474 | MODULE_AUTHOR("Fred Richter "); 475 | MODULE_LICENSE("GPL"); 476 | diff -uprN linux-4.4.x-orig/drivers/media/dvb-frontends/lgdt3306a.h linux-4.4.x-new/drivers/media/dvb-frontends/lgdt3306a.h 477 | --- linux-4.4.x-orig/drivers/media/dvb-frontends/lgdt3306a.h 2017-10-30 17:45:15.000000000 -0400 478 | +++ linux-4.4.x-new/drivers/media/dvb-frontends/lgdt3306a.h 2019-05-13 20:39:59.778870885 -0400 479 | @@ -21,6 +21,9 @@ 480 | #include 481 | #include "dvb_frontend.h" 482 | 483 | +#define LG3306_TUNERI2C_ON 0x00 484 | +#define LG3306_TUNERI2C_OFF 0x80 485 | + 486 | enum lgdt3306a_mpeg_mode { 487 | LGDT3306A_MPEG_PARALLEL = 0, 488 | LGDT3306A_MPEG_SERIAL = 1, 489 | @@ -55,6 +58,10 @@ struct lgdt3306a_config { 490 | 491 | /* demod clock freq in MHz; 24 or 25 supported */ 492 | int xtalMHz; 493 | + 494 | + /* returned by driver if using i2c bus multiplexing */ 495 | + struct dvb_frontend **fe; 496 | + struct i2c_adapter **i2c_adapter; 497 | }; 498 | 499 | #if IS_REACHABLE(CONFIG_DVB_LGDT3306A) 500 | -------------------------------------------------------------------------------- /hauppauge/002-Hauppauge955D-em28xx-Tuner1.patch: -------------------------------------------------------------------------------- 1 | diff -uprN linux-4.4.x-orig/Documentation/video4linux/CARDLIST.em28xx linux-4.4.x-new/Documentation/video4linux/CARDLIST.em28xx 2 | --- linux-4.4.x-orig/Documentation/video4linux/CARDLIST.em28xx 2017-09-25 22:52:52.000000000 -0400 3 | +++ linux-4.4.x-new/Documentation/video4linux/CARDLIST.em28xx 2019-05-04 08:16:31.909682143 -0400 4 | @@ -96,3 +96,5 @@ 5 | 95 -> Leadtek VC100 (em2861) [0413:6f07] 6 | 96 -> Terratec Cinergy T2 Stick HD (em28178) 7 | 97 -> Elgato EyeTV Hybrid 2008 INT (em2884) [0fd9:0018] 8 | + 98 -> PLEX PX-BCUD (em28178) [3275:0085] 9 | + 99 -> Hauppauge WinTV-dualHD DVB (em28174) [2040:0265] 10 | diff -uprN linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-cards.c linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-cards.c 11 | --- linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-cards.c 2017-10-30 17:46:49.000000000 -0400 12 | +++ linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-cards.c 2019-05-04 08:20:03.092511255 -0400 13 | @@ -492,6 +492,31 @@ static struct em28xx_reg_seq terratec_t2 14 | }; 15 | 16 | /* 17 | + * 2040:0265 Hauppauge WinTV-dualHD DVB 18 | + * 2040:026d Hauppauge WinTV-dualHD ATSC/QAM 19 | + * reg 0x80/0x84: 20 | + * GPIO_0: Yellow LED tuner 1, 0=on, 1=off 21 | + * GPIO_1: Green LED tuner 1, 0=on, 1=off 22 | + * GPIO_2: Yellow LED tuner 2, 0=on, 1=off 23 | + * GPIO_3: Green LED tuner 2, 0=on, 1=off 24 | + * GPIO_5: Reset #2, 0=active 25 | + * GPIO_6: Reset #1, 0=active 26 | + */ 27 | +static struct em28xx_reg_seq hauppauge_dualhd_dvb[] = { 28 | + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0}, 29 | + {0x0d, 0xff, 0xff, 200}, 30 | + {0x50, 0x04, 0xff, 300}, 31 | + {EM2874_R80_GPIO_P0_CTRL, 0xbf, 0xff, 100}, /* demod 1 reset */ 32 | + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100}, 33 | + {EM2874_R80_GPIO_P0_CTRL, 0xdf, 0xff, 100}, /* demod 2 reset */ 34 | + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100}, 35 | + {EM2874_R5F_TS_ENABLE, 0x44, 0xff, 50}, 36 | + {EM2874_R5D_TS1_PKT_SIZE, 0x05, 0xff, 50}, 37 | + {EM2874_R5E_TS2_PKT_SIZE, 0x05, 0xff, 50}, 38 | + {-1, -1, -1, -1}, 39 | +}; 40 | + 41 | +/* 42 | * Button definitions 43 | */ 44 | static struct em28xx_button std_snapshot_button[] = { 45 | @@ -560,6 +585,22 @@ static struct em28xx_led pctv_80e_leds[] 46 | {-1, 0, 0, 0}, 47 | }; 48 | 49 | +static struct em28xx_led hauppauge_dualhd_leds[] = { 50 | + { 51 | + .role = EM28XX_LED_DIGITAL_CAPTURING, 52 | + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, 53 | + .gpio_mask = EM_GPIO_1, 54 | + .inverted = 1, 55 | + }, 56 | + { 57 | + .role = EM28XX_LED_DIGITAL_CAPTURING_TS2, 58 | + .gpio_reg = EM2874_R80_GPIO_P0_CTRL, 59 | + .gpio_mask = EM_GPIO_3, 60 | + .inverted = 1, 61 | + }, 62 | + {-1, 0, 0, 0}, 63 | +}; 64 | + 65 | /* 66 | * Board definitions 67 | */ 68 | @@ -2288,6 +2329,36 @@ struct em28xx_board em28xx_boards[] = { 69 | .has_dvb = 1, 70 | .ir_codes = RC_MAP_TERRATEC_SLIM_2, 71 | }, 72 | + /* 73 | + * 2040:0265 Hauppauge WinTV-dualHD (DVB version). 74 | + * Empia EM28274, 2x Silicon Labs Si2168, 2x Silicon Labs Si2157 75 | + */ 76 | + [EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB] = { 77 | + .name = "Hauppauge WinTV-dualHD DVB", 78 | + .def_i2c_bus = 1, 79 | + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | 80 | + EM28XX_I2C_FREQ_400_KHZ, 81 | + .tuner_type = TUNER_ABSENT, 82 | + .tuner_gpio = hauppauge_dualhd_dvb, 83 | + .has_dvb = 1, 84 | + .ir_codes = RC_MAP_HAUPPAUGE, 85 | + .leds = hauppauge_dualhd_leds, 86 | + }, 87 | + /* 88 | + * 2040:026d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM). 89 | + * Empia EM28274, 2x LG LGDT3306A, 2x Silicon Labs Si2157 90 | + */ 91 | + [EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595] = { 92 | + .name = "Hauppauge WinTV-dualHD 01595 ATSC/QAM", 93 | + .def_i2c_bus = 1, 94 | + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | 95 | + EM28XX_I2C_FREQ_400_KHZ, 96 | + .tuner_type = TUNER_ABSENT, 97 | + .tuner_gpio = hauppauge_dualhd_dvb, 98 | + .has_dvb = 1, 99 | + .ir_codes = RC_MAP_HAUPPAUGE, 100 | + .leds = hauppauge_dualhd_leds, 101 | + }, 102 | }; 103 | EXPORT_SYMBOL_GPL(em28xx_boards); 104 | 105 | @@ -2411,6 +2482,10 @@ struct usb_device_id em28xx_id_table[] = 106 | .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, 107 | { USB_DEVICE(0x2040, 0x651f), 108 | .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 }, 109 | + { USB_DEVICE(0x2040, 0x0265), 110 | + .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB }, 111 | + { USB_DEVICE(0x2040, 0x026d), 112 | + .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 }, 113 | { USB_DEVICE(0x0438, 0xb002), 114 | .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, 115 | { USB_DEVICE(0x2001, 0xf112), 116 | @@ -2804,6 +2879,8 @@ static void em28xx_card_setup(struct em2 117 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: 118 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: 119 | case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: 120 | + case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB: 121 | + case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595: 122 | { 123 | struct tveeprom tv; 124 | 125 | diff -uprN linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-dvb.c linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-dvb.c 126 | --- linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-dvb.c 2017-10-30 17:46:44.000000000 -0400 127 | +++ linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-dvb.c 2019-05-04 08:20:03.092511255 -0400 128 | @@ -36,6 +36,7 @@ 129 | 130 | #include "lgdt330x.h" 131 | #include "lgdt3305.h" 132 | +#include "lgdt3306a.h" 133 | #include "zl10353.h" 134 | #include "s5h1409.h" 135 | #include "mt352.h" 136 | @@ -858,6 +859,17 @@ static struct tda18271_config pinnacle_8 137 | .role = TDA18271_MASTER, 138 | }; 139 | 140 | +static struct lgdt3306a_config hauppauge_01595_lgdt3306a_config = { 141 | + .qam_if_khz = 4000, 142 | + .vsb_if_khz = 3250, 143 | + .spectral_inversion = 0, 144 | + .deny_i2c_rptr = 0, 145 | + .mpeg_mode = LGDT3306A_MPEG_SERIAL, 146 | + .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, 147 | + .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, 148 | + .xtalMHz = 25, 149 | +}; 150 | + 151 | /* ------------------------------------------------------------------ */ 152 | 153 | static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) 154 | @@ -1717,6 +1729,132 @@ static int em28xx_dvb_init(struct em28xx 155 | if (!try_module_get(client->dev.driver->owner)) { 156 | i2c_unregister_device(client); 157 | module_put(dvb->i2c_client_demod->dev.driver->owner); 158 | + i2c_unregister_device(dvb->i2c_client_demod); 159 | + result = -ENODEV; 160 | + goto out_free; 161 | + } 162 | + 163 | + dvb->i2c_client_tuner = client; 164 | + } 165 | + break; 166 | + case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB: 167 | + { 168 | + struct i2c_adapter *adapter; 169 | + struct i2c_client *client; 170 | + struct i2c_board_info info; 171 | + struct si2168_config si2168_config; 172 | + struct si2157_config si2157_config; 173 | + 174 | + /* attach demod */ 175 | + memset(&si2168_config, 0, sizeof(si2168_config)); 176 | + si2168_config.i2c_adapter = &adapter; 177 | + si2168_config.fe = &dvb->fe[0]; 178 | + si2168_config.ts_mode = SI2168_TS_SERIAL; 179 | + memset(&info, 0, sizeof(struct i2c_board_info)); 180 | + strlcpy(info.type, "si2168", I2C_NAME_SIZE); 181 | + info.addr = 0x64; 182 | + info.platform_data = &si2168_config; 183 | + request_module(info.type); 184 | + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); 185 | + if (client == NULL || client->dev.driver == NULL) { 186 | + result = -ENODEV; 187 | + goto out_free; 188 | + } 189 | + 190 | + if (!try_module_get(client->dev.driver->owner)) { 191 | + i2c_unregister_device(client); 192 | + result = -ENODEV; 193 | + goto out_free; 194 | + } 195 | + 196 | + dvb->i2c_client_demod = client; 197 | + 198 | + /* attach tuner */ 199 | + memset(&si2157_config, 0, sizeof(si2157_config)); 200 | + si2157_config.fe = dvb->fe[0]; 201 | + si2157_config.if_port = 1; 202 | +#ifdef CONFIG_MEDIA_CONTROLLER_DVB 203 | + si2157_config.mdev = dev->media_dev; 204 | +#endif 205 | + memset(&info, 0, sizeof(struct i2c_board_info)); 206 | + strlcpy(info.type, "si2157", I2C_NAME_SIZE); 207 | + info.addr = 0x60; 208 | + info.platform_data = &si2157_config; 209 | + request_module(info.type); 210 | + client = i2c_new_device(adapter, &info); 211 | + if (client == NULL || client->dev.driver == NULL) { 212 | + module_put(dvb->i2c_client_demod->dev.driver->owner); 213 | + i2c_unregister_device(dvb->i2c_client_demod); 214 | + result = -ENODEV; 215 | + goto out_free; 216 | + } 217 | + 218 | + if (!try_module_get(client->dev.driver->owner)) { 219 | + i2c_unregister_device(client); 220 | + module_put(dvb->i2c_client_demod->dev.driver->owner); 221 | + i2c_unregister_device(dvb->i2c_client_demod); 222 | + result = -ENODEV; 223 | + goto out_free; 224 | + } 225 | + 226 | + dvb->i2c_client_tuner = client; 227 | + 228 | + } 229 | + break; 230 | + case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595: 231 | + { 232 | + struct i2c_adapter *adapter; 233 | + struct i2c_client *client; 234 | + struct i2c_board_info info = {}; 235 | + struct lgdt3306a_config lgdt3306a_config; 236 | + struct si2157_config si2157_config = {}; 237 | + 238 | + /* attach demod */ 239 | + lgdt3306a_config = hauppauge_01595_lgdt3306a_config; 240 | + lgdt3306a_config.fe = &dvb->fe[0]; 241 | + lgdt3306a_config.i2c_adapter = &adapter; 242 | + strlcpy(info.type, "lgdt3306a", sizeof(info.type)); 243 | + info.addr = 0x59; 244 | + info.platform_data = &lgdt3306a_config; 245 | + request_module(info.type); 246 | + client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], 247 | + &info); 248 | + if (client == NULL || client->dev.driver == NULL) { 249 | + result = -ENODEV; 250 | + goto out_free; 251 | + } 252 | + 253 | + if (!try_module_get(client->dev.driver->owner)) { 254 | + i2c_unregister_device(client); 255 | + result = -ENODEV; 256 | + goto out_free; 257 | + } 258 | + 259 | + dvb->i2c_client_demod = client; 260 | + 261 | + /* attach tuner */ 262 | + si2157_config.fe = dvb->fe[0]; 263 | + si2157_config.if_port = 1; 264 | + si2157_config.inversion = 1; 265 | +#ifdef CONFIG_MEDIA_CONTROLLER_DVB 266 | + si2157_config.mdev = dev->media_dev; 267 | +#endif 268 | + memset(&info, 0, sizeof(struct i2c_board_info)); 269 | + strlcpy(info.type, "si2157", sizeof(info.type)); 270 | + info.addr = 0x60; 271 | + info.platform_data = &si2157_config; 272 | + request_module(info.type); 273 | + 274 | + client = i2c_new_device(adapter, &info); 275 | + if (client == NULL || client->dev.driver == NULL) { 276 | + module_put(dvb->i2c_client_demod->dev.driver->owner); 277 | + i2c_unregister_device(dvb->i2c_client_demod); 278 | + result = -ENODEV; 279 | + goto out_free; 280 | + } 281 | + if (!try_module_get(client->dev.driver->owner)) { 282 | + i2c_unregister_device(client); 283 | + module_put(dvb->i2c_client_demod->dev.driver->owner); 284 | i2c_unregister_device(dvb->i2c_client_demod); 285 | result = -ENODEV; 286 | goto out_free; 287 | diff -uprN linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx.h linux-4.4.x-new/drivers/media/usb/em28xx/em28xx.h 288 | --- linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx.h 2017-10-30 17:46:43.000000000 -0400 289 | +++ linux-4.4.x-new/drivers/media/usb/em28xx/em28xx.h 2019-05-04 08:20:03.092511255 -0400 290 | @@ -145,6 +145,9 @@ 291 | #define EM2861_BOARD_LEADTEK_VC100 95 292 | #define EM28178_BOARD_TERRATEC_T2_STICK_HD 96 293 | #define EM2884_BOARD_ELGATO_EYETV_HYBRID_2008 97 294 | +#define EM28178_BOARD_PLEX_PX_BCUD 98 295 | +#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB 99 296 | +#define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 100 297 | 298 | /* Limits minimum and default number of buffers */ 299 | #define EM28XX_MIN_BUF 4 300 | @@ -412,6 +415,7 @@ enum em28xx_adecoder { 301 | enum em28xx_led_role { 302 | EM28XX_LED_ANALOG_CAPTURING = 0, 303 | EM28XX_LED_DIGITAL_CAPTURING, 304 | + EM28XX_LED_DIGITAL_CAPTURING_TS2, 305 | EM28XX_LED_ILLUMINATION, 306 | EM28XX_NUM_LED_ROLES, /* must be the last */ 307 | }; 308 | diff -uprN linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-reg.h linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-reg.h 309 | --- linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-reg.h 2017-10-30 17:46:42.000000000 -0400 310 | +++ linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-reg.h 2019-05-04 08:15:10.896596159 -0400 311 | @@ -193,6 +193,19 @@ 312 | /* em2874 registers */ 313 | #define EM2874_R50_IR_CONFIG 0x50 314 | #define EM2874_R51_IR 0x51 315 | +#define EM2874_R5D_TS1_PKT_SIZE 0x5d 316 | +#define EM2874_R5E_TS2_PKT_SIZE 0x5e 317 | + /* 318 | + * For both TS1 and TS2, In isochronous mode: 319 | + * 0x01 188 bytes 320 | + * 0x02 376 bytes 321 | + * 0x03 564 bytes 322 | + * 0x04 752 bytes 323 | + * 0x05 940 bytes 324 | + * In bulk mode: 325 | + * 0x01..0xff total packet count in 188-byte 326 | + */ 327 | + 328 | #define EM2874_R5F_TS_ENABLE 0x5f 329 | 330 | /* em2874/174/84, em25xx, em276x/7x/8x GPIO registers */ 331 | -------------------------------------------------------------------------------- /hauppauge/003-Hauppauge955D-em28xx-Tuner2-v6.patch: -------------------------------------------------------------------------------- 1 | diff -uprN linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-cards.c linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-cards.c 2 | --- linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-cards.c 2019-05-06 20:53:45.596707923 -0400 3 | +++ linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-cards.c 2019-05-06 20:55:37.646304153 -0400 4 | @@ -2341,6 +2341,7 @@ struct em28xx_board em28xx_boards[] = { 5 | .tuner_type = TUNER_ABSENT, 6 | .tuner_gpio = hauppauge_dualhd_dvb, 7 | .has_dvb = 1, 8 | + .has_dual_ts = 1, 9 | .ir_codes = RC_MAP_HAUPPAUGE, 10 | .leds = hauppauge_dualhd_leds, 11 | }, 12 | @@ -2356,6 +2357,7 @@ struct em28xx_board em28xx_boards[] = { 13 | .tuner_type = TUNER_ABSENT, 14 | .tuner_gpio = hauppauge_dualhd_dvb, 15 | .has_dvb = 1, 16 | + .has_dual_ts = 1, 17 | .ir_codes = RC_MAP_HAUPPAUGE, 18 | .leds = hauppauge_dualhd_leds, 19 | }, 20 | @@ -3090,6 +3092,8 @@ static void flush_request_modules(struct 21 | */ 22 | static void em28xx_release_resources(struct em28xx *dev) 23 | { 24 | + struct usb_device *udev; 25 | + 26 | /*FIXME: I2C IR should be disconnected */ 27 | 28 | mutex_lock(&dev->lock); 29 | @@ -3098,7 +3102,8 @@ static void em28xx_release_resources(str 30 | em28xx_i2c_unregister(dev, 1); 31 | em28xx_i2c_unregister(dev, 0); 32 | 33 | - usb_put_dev(dev->udev); 34 | + if (dev->ts == PRIMARY_TS) 35 | + usb_put_dev(udev); 36 | 37 | /* Mark device as unused */ 38 | clear_bit(dev->devno, em28xx_devused); 39 | @@ -3297,6 +3302,35 @@ static int em28xx_init_dev(struct em28xx 40 | return 0; 41 | } 42 | 43 | +int em28xx_duplicate_dev(struct em28xx *dev) 44 | +{ 45 | + int nr; 46 | + struct em28xx *sec_dev = kzalloc(sizeof(*sec_dev), GFP_KERNEL); 47 | + 48 | + if (sec_dev == NULL) { 49 | + dev->dev_next = NULL; 50 | + return -ENOMEM; 51 | + } 52 | + memcpy(sec_dev, dev, sizeof(sizeof(*sec_dev))); 53 | + /* Check to see next free device and mark as used */ 54 | + do { 55 | + nr = find_first_zero_bit(em28xx_devused, EM28XX_MAXBOARDS); 56 | + if (nr >= EM28XX_MAXBOARDS) { 57 | + /* No free device slots */ 58 | + dev_warn(&dev->udev->dev, ": Supports only %i em28xx boards.\n", 59 | + EM28XX_MAXBOARDS); 60 | + kfree(sec_dev); 61 | + dev->dev_next = NULL; 62 | + return -ENOMEM; 63 | + } 64 | + } while (test_and_set_bit(nr, em28xx_devused)); 65 | + sec_dev->devno = nr; 66 | + snprintf(sec_dev->name, 28, "em28xx #%d", nr); 67 | + sec_dev->dev_next = NULL; 68 | + dev->dev_next = sec_dev; 69 | + return 0; 70 | +} 71 | + 72 | /* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ 73 | #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) 74 | 75 | @@ -3417,6 +3451,17 @@ static int em28xx_usb_probe(struct usb_i 76 | } 77 | } 78 | break; 79 | + case 0x85: 80 | + if (usb_endpoint_xfer_isoc(e)) { 81 | + if (size > dev->dvb_max_pkt_size_isoc_ts2) { 82 | + dev->dvb_ep_isoc_ts2 = e->bEndpointAddress; 83 | + dev->dvb_max_pkt_size_isoc_ts2 = size; 84 | + dev->dvb_alt_isoc = i; 85 | + } 86 | + } else { 87 | + dev->dvb_ep_bulk_ts2 = e->bEndpointAddress; 88 | + } 89 | + break; 90 | } 91 | } 92 | /* NOTE: 93 | @@ -3431,6 +3476,8 @@ static int em28xx_usb_probe(struct usb_i 94 | * 0x83 isoc* => audio 95 | * 0x84 isoc => digital 96 | * 0x84 bulk => analog or digital** 97 | + * 0x85 isoc => digital TS2 98 | + * 0x85 bulk => digital TS2 99 | * (*: audio should always be isoc) 100 | * (**: analog, if ep 0x82 is isoc, otherwise digital) 101 | * 102 | @@ -3499,6 +3546,10 @@ static int em28xx_usb_probe(struct usb_i 103 | dev->has_video = has_video; 104 | dev->ifnum = ifnum; 105 | 106 | + dev->ts = PRIMARY_TS; 107 | + snprintf(dev->name, 28, "em28xx"); 108 | + dev->dev_next = NULL; 109 | + 110 | if (has_vendor_audio) { 111 | printk(KERN_INFO DRIVER_NAME ": Audio interface %i found %s\n", 112 | ifnum, "(Vendor Class)"); 113 | @@ -3568,6 +3619,65 @@ static int em28xx_usb_probe(struct usb_i 114 | dev->dvb_xfer_bulk ? "bulk" : "isoc"); 115 | } 116 | 117 | + if (dev->board.has_dual_ts && em28xx_duplicate_dev(dev) == 0) { 118 | + dev->dev_next->ts = SECONDARY_TS; 119 | + dev->dev_next->alt = -1; 120 | + dev->dev_next->is_audio_only = has_vendor_audio && 121 | + !(has_video || has_dvb); 122 | + dev->dev_next->has_video = false; 123 | + dev->dev_next->ifnum = ifnum; 124 | + dev->dev_next->model = id->driver_info; 125 | + 126 | + mutex_init(&dev->dev_next->lock); 127 | + retval = em28xx_init_dev(dev->dev_next, udev, interface, 128 | + dev->dev_next->devno); 129 | + if (retval) 130 | + goto err_free; 131 | + 132 | + dev->dev_next->board.ir_codes = NULL; /* No IR for 2nd tuner */ 133 | + dev->dev_next->board.has_ir_i2c = 0; /* No IR for 2nd tuner */ 134 | + 135 | + if (usb_xfer_mode < 0) { 136 | + if (dev->dev_next->board.is_webcam) 137 | + try_bulk = 1; 138 | + else 139 | + try_bulk = 0; 140 | + } else { 141 | + try_bulk = usb_xfer_mode > 0; 142 | + } 143 | + 144 | + /* Select USB transfer types to use */ 145 | + if (has_dvb) { 146 | + if (!dev->dvb_ep_isoc_ts2 || 147 | + (try_bulk && dev->dvb_ep_bulk_ts2)) 148 | + dev->dev_next->dvb_xfer_bulk = 1; 149 | + printk(KERN_INFO DRIVER_NAME ": dvb ts2 set to %s mode.\n", 150 | + dev->dev_next->dvb_xfer_bulk ? "bulk" : "isoc"); 151 | + } 152 | + 153 | + dev->dev_next->dvb_ep_isoc = dev->dvb_ep_isoc_ts2; 154 | + dev->dev_next->dvb_ep_bulk = dev->dvb_ep_bulk_ts2; 155 | + dev->dev_next->dvb_max_pkt_size_isoc = dev->dvb_max_pkt_size_isoc_ts2; 156 | + dev->dev_next->dvb_alt_isoc = dev->dvb_alt_isoc; 157 | + 158 | + /* Configuare hardware to support TS2*/ 159 | + if (dev->dvb_xfer_bulk) { 160 | + /* The ep4 and ep5 are configuared for BULK */ 161 | + em28xx_write_reg(dev, 0x0b, 0x96); 162 | + mdelay(100); 163 | + em28xx_write_reg(dev, 0x0b, 0x80); 164 | + mdelay(100); 165 | + } else { 166 | + /* The ep4 and ep5 are configuared for ISO */ 167 | + em28xx_write_reg(dev, 0x0b, 0x96); 168 | + mdelay(100); 169 | + em28xx_write_reg(dev, 0x0b, 0x82); 170 | + mdelay(100); 171 | + } 172 | + 173 | + kref_init(&dev->dev_next->ref); 174 | + } 175 | + 176 | kref_init(&dev->ref); 177 | 178 | request_modules(dev); 179 | @@ -3605,6 +3715,13 @@ static void em28xx_usb_disconnect(struct 180 | if (!dev) 181 | return; 182 | 183 | + if (dev->dev_next != NULL) { 184 | + dev->dev_next->disconnected = 1; 185 | + printk(KERN_INFO DRIVER_NAME ": Disconnecting %s\n", 186 | + dev->dev_next->name); 187 | + flush_request_modules(dev->dev_next); 188 | + } 189 | + 190 | dev->disconnected = 1; 191 | 192 | em28xx_info("Disconnecting %s\n", dev->name); 193 | @@ -3613,7 +3730,14 @@ static void em28xx_usb_disconnect(struct 194 | 195 | em28xx_close_extension(dev); 196 | 197 | + if (dev->dev_next != NULL) 198 | + em28xx_release_resources(dev->dev_next); 199 | em28xx_release_resources(dev); 200 | + 201 | + if (dev->dev_next != NULL) { 202 | + kref_put(&dev->dev_next->ref, em28xx_free_device); 203 | + dev->dev_next = NULL; 204 | + } 205 | kref_put(&dev->ref, em28xx_free_device); 206 | } 207 | 208 | diff -uprN linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-core.c linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-core.c 209 | --- linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-core.c 2017-10-30 17:46:43.000000000 -0400 210 | +++ linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-core.c 2019-05-06 20:55:37.642304096 -0400 211 | @@ -636,10 +636,18 @@ int em28xx_capture_start(struct em28xx * 212 | dev->chip_id == CHIP_ID_EM28174 || 213 | dev->chip_id == CHIP_ID_EM28178) { 214 | /* The Transport Stream Enable Register moved in em2874 */ 215 | - rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, 216 | - start ? 217 | - EM2874_TS1_CAPTURE_ENABLE : 0x00, 218 | - EM2874_TS1_CAPTURE_ENABLE); 219 | + if (dev->ts == PRIMARY_TS) 220 | + rc = em28xx_write_reg_bits(dev, 221 | + EM2874_R5F_TS_ENABLE, 222 | + start ? 223 | + EM2874_TS1_CAPTURE_ENABLE : 0x00, 224 | + EM2874_TS1_CAPTURE_ENABLE); 225 | + else 226 | + rc = em28xx_write_reg_bits(dev, 227 | + EM2874_R5F_TS_ENABLE, 228 | + start ? 229 | + EM2874_TS2_CAPTURE_ENABLE : 0x00, 230 | + EM2874_TS2_CAPTURE_ENABLE); 231 | } else { 232 | /* FIXME: which is the best order? */ 233 | /* video registers are sampled by VREF */ 234 | @@ -1073,7 +1081,11 @@ int em28xx_register_extension(struct em2 235 | mutex_lock(&em28xx_devlist_mutex); 236 | list_add_tail(&ops->next, &em28xx_extension_devlist); 237 | list_for_each_entry(dev, &em28xx_devlist, devlist) { 238 | - ops->init(dev); 239 | + if (ops->init) { 240 | + ops->init(dev); 241 | + if (dev->dev_next != NULL) 242 | + ops->init(dev->dev_next); 243 | + } 244 | } 245 | mutex_unlock(&em28xx_devlist_mutex); 246 | printk(KERN_INFO "em28xx: Registered (%s) extension\n", ops->name); 247 | @@ -1087,7 +1099,11 @@ void em28xx_unregister_extension(struct 248 | 249 | mutex_lock(&em28xx_devlist_mutex); 250 | list_for_each_entry(dev, &em28xx_devlist, devlist) { 251 | - ops->fini(dev); 252 | + if (ops->fini) { 253 | + if (dev->dev_next != NULL) 254 | + ops->fini(dev->dev_next); 255 | + ops->fini(dev); 256 | + } 257 | } 258 | list_del(&ops->next); 259 | mutex_unlock(&em28xx_devlist_mutex); 260 | @@ -1102,8 +1118,11 @@ void em28xx_init_extension(struct em28xx 261 | mutex_lock(&em28xx_devlist_mutex); 262 | list_add_tail(&dev->devlist, &em28xx_devlist); 263 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { 264 | - if (ops->init) 265 | + if (ops->init) { 266 | ops->init(dev); 267 | + if (dev->dev_next != NULL) 268 | + ops->init(dev->dev_next); 269 | + } 270 | } 271 | mutex_unlock(&em28xx_devlist_mutex); 272 | } 273 | @@ -1114,8 +1133,11 @@ void em28xx_close_extension(struct em28x 274 | 275 | mutex_lock(&em28xx_devlist_mutex); 276 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { 277 | - if (ops->fini) 278 | + if (ops->fini) { 279 | + if (dev->dev_next != NULL) 280 | + ops->fini(dev->dev_next); 281 | ops->fini(dev); 282 | + } 283 | } 284 | list_del(&dev->devlist); 285 | mutex_unlock(&em28xx_devlist_mutex); 286 | @@ -1130,6 +1152,8 @@ int em28xx_suspend_extension(struct em28 287 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { 288 | if (ops->suspend) 289 | ops->suspend(dev); 290 | + if (dev->dev_next != NULL) 291 | + ops->suspend(dev->dev_next); 292 | } 293 | mutex_unlock(&em28xx_devlist_mutex); 294 | return 0; 295 | @@ -1144,6 +1168,8 @@ int em28xx_resume_extension(struct em28x 296 | list_for_each_entry(ops, &em28xx_extension_devlist, next) { 297 | if (ops->resume) 298 | ops->resume(dev); 299 | + if (dev->dev_next != NULL) 300 | + ops->resume(dev->dev_next); 301 | } 302 | mutex_unlock(&em28xx_devlist_mutex); 303 | return 0; 304 | diff -uprN linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-dvb.c linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-dvb.c 305 | --- linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx-dvb.c 2019-05-06 20:53:45.600707980 -0400 306 | +++ linux-4.4.x-new/drivers/media/usb/em28xx/em28xx-dvb.c 2019-05-06 20:55:37.646304153 -0400 307 | @@ -212,7 +212,6 @@ static int em28xx_start_streaming(struct 308 | dvb_alt = dev->dvb_alt_isoc; 309 | } 310 | 311 | - usb_set_interface(dev->udev, dev->ifnum, dvb_alt); 312 | rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); 313 | if (rc < 0) 314 | return rc; 315 | @@ -1042,8 +1041,9 @@ static void em28xx_unregister_dvb(struct 316 | 317 | static int em28xx_dvb_init(struct em28xx *dev) 318 | { 319 | - int result = 0; 320 | + int result = 0, dvb_alt = 0; 321 | struct em28xx_dvb *dvb; 322 | + /* struct usb_device *udev; */ 323 | 324 | if (dev->is_audio_only) { 325 | /* Shouldn't initialize IR for this interface */ 326 | @@ -1631,7 +1631,10 @@ static int em28xx_dvb_init(struct em28xx 327 | si2168_config.ts_mode = SI2168_TS_PARALLEL; 328 | memset(&info, 0, sizeof(struct i2c_board_info)); 329 | strlcpy(info.type, "si2168", I2C_NAME_SIZE); 330 | - info.addr = 0x64; 331 | + if (dev->ts == PRIMARY_TS) 332 | + info.addr = 0x64; 333 | + else 334 | + info.addr = 0x67; 335 | info.platform_data = &si2168_config; 336 | request_module(info.type); 337 | client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info); 338 | @@ -1654,7 +1657,10 @@ static int em28xx_dvb_init(struct em28xx 339 | si2157_config.if_port = 1; 340 | memset(&info, 0, sizeof(struct i2c_board_info)); 341 | strlcpy(info.type, "si2157", I2C_NAME_SIZE); 342 | - info.addr = 0x60; 343 | + if (dev->ts == PRIMARY_TS) 344 | + info.addr = 0x60; 345 | + else 346 | + info.addr = 0x63; 347 | info.platform_data = &si2157_config; 348 | request_module(info.type); 349 | client = i2c_new_device(adapter, &info); 350 | @@ -1814,7 +1820,10 @@ static int em28xx_dvb_init(struct em28xx 351 | lgdt3306a_config.fe = &dvb->fe[0]; 352 | lgdt3306a_config.i2c_adapter = &adapter; 353 | strlcpy(info.type, "lgdt3306a", sizeof(info.type)); 354 | - info.addr = 0x59; 355 | + if (dev->ts == PRIMARY_TS) 356 | + info.addr = 0x59; 357 | + else 358 | + info.addr = 0x0e; 359 | info.platform_data = &lgdt3306a_config; 360 | request_module(info.type); 361 | client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], 362 | @@ -1841,7 +1850,10 @@ static int em28xx_dvb_init(struct em28xx 363 | #endif 364 | memset(&info, 0, sizeof(struct i2c_board_info)); 365 | strlcpy(info.type, "si2157", sizeof(info.type)); 366 | - info.addr = 0x60; 367 | + if (dev->ts == PRIMARY_TS) 368 | + info.addr = 0x60; 369 | + else 370 | + info.addr = 0x62; 371 | info.platform_data = &si2157_config; 372 | request_module(info.type); 373 | 374 | @@ -1884,6 +1896,15 @@ static int em28xx_dvb_init(struct em28xx 375 | if (result < 0) 376 | goto out_free; 377 | 378 | + if (dev->dvb_xfer_bulk) { 379 | + dvb_alt = 0; 380 | + } else { /* isoc */ 381 | + dvb_alt = dev->dvb_alt_isoc; 382 | + } 383 | + 384 | + /* udev = interface_to_usbdev(dev->intf); */ 385 | + usb_set_interface(dev->udev, dev->ifnum, dvb_alt); 386 | + /* usb_set_interface(udev, dev->ifnum, dvb_alt); */ 387 | em28xx_info("DVB extension successfully initialized\n"); 388 | 389 | kref_get(&dev->ref); 390 | diff -uprN linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx.h linux-4.4.x-new/drivers/media/usb/em28xx/em28xx.h 391 | --- linux-4.4.x-orig/drivers/media/usb/em28xx/em28xx.h 2019-05-06 20:53:45.600707980 -0400 392 | +++ linux-4.4.x-new/drivers/media/usb/em28xx/em28xx.h 2019-05-06 20:55:37.646304153 -0400 393 | @@ -216,6 +216,9 @@ 394 | /* max. number of button state polling addresses */ 395 | #define EM28XX_NUM_BUTTON_ADDRESSES_MAX 5 396 | 397 | +#define PRIMARY_TS 0 398 | +#define SECONDARY_TS 1 399 | + 400 | enum em28xx_mode { 401 | EM28XX_SUSPEND, 402 | EM28XX_ANALOG_MODE, 403 | @@ -462,6 +465,7 @@ struct em28xx_board { 404 | unsigned int mts_firmware:1; 405 | unsigned int max_range_640_480:1; 406 | unsigned int has_dvb:1; 407 | + unsigned int has_dual_ts:1; 408 | unsigned int is_webcam:1; 409 | unsigned int valid:1; 410 | unsigned int has_ir_i2c:1; 411 | @@ -612,7 +616,6 @@ struct em28xx { 412 | struct em28xx_IR *ir; 413 | 414 | /* generic device properties */ 415 | - char name[30]; /* name (including minor) of the device */ 416 | int model; /* index in the device_data struct */ 417 | int devno; /* marks the number of this device */ 418 | enum em28xx_chip_id chip_id; 419 | @@ -623,6 +626,7 @@ struct em28xx { 420 | unsigned int is_audio_only:1; 421 | enum em28xx_int_audio_type int_audio_type; 422 | enum em28xx_usb_audio_type usb_audio_type; 423 | + unsigned char name[32]; 424 | 425 | struct em28xx_board board; 426 | 427 | @@ -684,6 +688,8 @@ struct em28xx { 428 | u8 ifnum; /* number of the assigned usb interface */ 429 | u8 analog_ep_isoc; /* address of isoc endpoint for analog */ 430 | u8 analog_ep_bulk; /* address of bulk endpoint for analog */ 431 | + u8 dvb_ep_isoc_ts2; /* address of isoc endpoint for DVB TS2*/ 432 | + u8 dvb_ep_bulk_ts2; /* address of bulk endpoint for DVB TS2*/ 433 | u8 dvb_ep_isoc; /* address of isoc endpoint for DVB */ 434 | u8 dvb_ep_bulk; /* address of bulk endpoint for DVB */ 435 | int alt; /* alternate setting */ 436 | @@ -697,6 +703,8 @@ struct em28xx { 437 | int dvb_alt_isoc; /* alternate setting for DVB isoc transfers */ 438 | unsigned int dvb_max_pkt_size_isoc; /* isoc max packet size of the 439 | selected DVB ep at dvb_alt */ 440 | + unsigned int dvb_max_pkt_size_isoc_ts2; /* isoc max packet size of the 441 | + selected DVB ep at dvb_alt */ 442 | unsigned int dvb_xfer_bulk:1; /* use bulk instead of isoc 443 | transfers for DVB */ 444 | char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ 445 | @@ -722,6 +730,9 @@ struct em28xx { 446 | /* Snapshot button input device */ 447 | char snapshot_button_path[30]; /* path of the input dev */ 448 | struct input_dev *sbutton_input_dev; 449 | + 450 | + struct em28xx *dev_next; 451 | + int ts; 452 | }; 453 | 454 | #define kref_to_dev(d) container_of(d, struct em28xx, ref) 455 | -------------------------------------------------------------------------------- /hauppauge/hauppauge955D-SYNOApollolake-DSM622_24922-Kernel_4.4.59-20190520.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/hauppauge/hauppauge955D-SYNOApollolake-DSM622_24922-Kernel_4.4.59-20190520.tar.bz2 -------------------------------------------------------------------------------- /images/antenne-omnidirectionnelle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/antenne-omnidirectionnelle.jpg -------------------------------------------------------------------------------- /images/antenne-unidirectionnelle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/antenne-unidirectionnelle.jpg -------------------------------------------------------------------------------- /images/ds918.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/ds918.jpg -------------------------------------------------------------------------------- /images/fireTV-network.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/fireTV-network.jpg -------------------------------------------------------------------------------- /images/fireTV.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/fireTV.jpg -------------------------------------------------------------------------------- /images/firetv-downloader-kodiweb-download-android-armv7a32bit-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-downloader-kodiweb-download-android-armv7a32bit-download.png -------------------------------------------------------------------------------- /images/firetv-downloader-kodiweb-download-android-armv7a32bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-downloader-kodiweb-download-android-armv7a32bit.png -------------------------------------------------------------------------------- /images/firetv-downloader-kodiweb-download-androidrobot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-downloader-kodiweb-download-androidrobot.png -------------------------------------------------------------------------------- /images/firetv-downloader-kodiweb-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-downloader-kodiweb-download.png -------------------------------------------------------------------------------- /images/firetv-downloader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-downloader.png -------------------------------------------------------------------------------- /images/firetv-kodi-install-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-kodi-install-01.png -------------------------------------------------------------------------------- /images/firetv-kodi-install-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-kodi-install-02.png -------------------------------------------------------------------------------- /images/firetv-kodi-install-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-kodi-install-03.png -------------------------------------------------------------------------------- /images/firetv-kodi-install-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-kodi-install-04.png -------------------------------------------------------------------------------- /images/firetv-kodi-install-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-kodi-install-05.png -------------------------------------------------------------------------------- /images/firetv-menu-parametres-mafiretv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-menu-parametres-mafiretv.png -------------------------------------------------------------------------------- /images/firetv-menu-parametres.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-menu-parametres.png -------------------------------------------------------------------------------- /images/firetv-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-menu.png -------------------------------------------------------------------------------- /images/firetv-parametres-mafiretv-aproposde-reseau.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-parametres-mafiretv-aproposde-reseau.png -------------------------------------------------------------------------------- /images/firetv-parametres-mafiretv-aproposde.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-parametres-mafiretv-aproposde.png -------------------------------------------------------------------------------- /images/firetv-parametres-mafiretv-optiondev-adb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-parametres-mafiretv-optiondev-adb.png -------------------------------------------------------------------------------- /images/firetv-parametres-mafiretv-optiondev-sources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-parametres-mafiretv-optiondev-sources.png -------------------------------------------------------------------------------- /images/firetv-parametres-mafiretv-optiondev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/firetv-parametres-mafiretv-optiondev.png -------------------------------------------------------------------------------- /images/hdhomerun.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/hdhomerun.jpeg -------------------------------------------------------------------------------- /images/kodi-addiciel-tvheadend-configuration-avance-async_EPG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-addiciel-tvheadend-configuration-avance-async_EPG.png -------------------------------------------------------------------------------- /images/kodi-addiciel-tvheadend-configuration-connexion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-addiciel-tvheadend-configuration-connexion.png -------------------------------------------------------------------------------- /images/kodi-addiciel-tvheadend-configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-addiciel-tvheadend-configuration.png -------------------------------------------------------------------------------- /images/kodi-parametre-interface-habillage-configurer-elements_menus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametre-interface-habillage-configurer-elements_menus.png -------------------------------------------------------------------------------- /images/kodi-parametre-interface-habillage-configurer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametre-interface-habillage-configurer.png -------------------------------------------------------------------------------- /images/kodi-parametre-interface-habillage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametre-interface-habillage.png -------------------------------------------------------------------------------- /images/kodi-parametre-interface-region_heure_langue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametre-interface-region_heure_langue.png -------------------------------------------------------------------------------- /images/kodi-parametre-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametre-interface.png -------------------------------------------------------------------------------- /images/kodi-parametre-systeme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametre-systeme.png -------------------------------------------------------------------------------- /images/kodi-parametres-addiciels-kodi_repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametres-addiciels-kodi_repo.png -------------------------------------------------------------------------------- /images/kodi-parametres-addiciels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametres-addiciels.png -------------------------------------------------------------------------------- /images/kodi-parametres-numeriscope-guide-14jours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametres-numeriscope-guide-14jours.png -------------------------------------------------------------------------------- /images/kodi-parametres-numeriscope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametres-numeriscope.png -------------------------------------------------------------------------------- /images/kodi-parametres.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-parametres.png -------------------------------------------------------------------------------- /images/kodi-start-firstrun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-start-firstrun.png -------------------------------------------------------------------------------- /images/kodi-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/kodi-start.png -------------------------------------------------------------------------------- /images/synology-configuration-group-media-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-group-media-01.png -------------------------------------------------------------------------------- /images/synology-configuration-group-media-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-group-media-02.png -------------------------------------------------------------------------------- /images/synology-configuration-group-media-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-group-media-03.png -------------------------------------------------------------------------------- /images/synology-configuration-group-media-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-group-media-04.png -------------------------------------------------------------------------------- /images/synology-configuration-group-media-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-group-media-05.png -------------------------------------------------------------------------------- /images/synology-configuration-group-media-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-group-media-06.png -------------------------------------------------------------------------------- /images/synology-configuration-groupe-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-groupe-icon.png -------------------------------------------------------------------------------- /images/synology-configuration-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-icon.png -------------------------------------------------------------------------------- /images/synology-configuration-user-kodi-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-user-kodi-01.png -------------------------------------------------------------------------------- /images/synology-configuration-user-kodi-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-user-kodi-02.png -------------------------------------------------------------------------------- /images/synology-configuration-user-kodi-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-user-kodi-03.png -------------------------------------------------------------------------------- /images/synology-configuration-user-kodi-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-user-kodi-04.png -------------------------------------------------------------------------------- /images/synology-configuration-user-kodi-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-user-kodi-05.png -------------------------------------------------------------------------------- /images/synology-configuration-user-kodi-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-user-kodi-06.png -------------------------------------------------------------------------------- /images/synology-configuration-user-kodi-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-user-kodi-07.png -------------------------------------------------------------------------------- /images/synology-configuration-utilisateur-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-configuration-utilisateur-icon.png -------------------------------------------------------------------------------- /images/synology-packagecenter-add_source-synocommunity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-add_source-synocommunity.png -------------------------------------------------------------------------------- /images/synology-packagecenter-beta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-beta.png -------------------------------------------------------------------------------- /images/synology-packagecenter-entware-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-entware-01.png -------------------------------------------------------------------------------- /images/synology-packagecenter-entware-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-entware-02.png -------------------------------------------------------------------------------- /images/synology-packagecenter-entware-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-entware-03.png -------------------------------------------------------------------------------- /images/synology-packagecenter-entware-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-entware-04.png -------------------------------------------------------------------------------- /images/synology-packagecenter-entware-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-entware-05.png -------------------------------------------------------------------------------- /images/synology-packagecenter-ffmpeg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-ffmpeg.png -------------------------------------------------------------------------------- /images/synology-packagecenter-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-icon.png -------------------------------------------------------------------------------- /images/synology-packagecenter-parametres.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-parametres.png -------------------------------------------------------------------------------- /images/synology-packagecenter-perl-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-perl-01.png -------------------------------------------------------------------------------- /images/synology-packagecenter-sources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-sources.png -------------------------------------------------------------------------------- /images/synology-packagecenter-tvheadend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-packagecenter-tvheadend.png -------------------------------------------------------------------------------- /images/synology-taskscheduler-tvh_backup-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-taskscheduler-tvh_backup-01.png -------------------------------------------------------------------------------- /images/synology-taskscheduler-tvh_backup-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-taskscheduler-tvh_backup-02.png -------------------------------------------------------------------------------- /images/synology-taskscheduler-tvh_backup-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-taskscheduler-tvh_backup-03.png -------------------------------------------------------------------------------- /images/synology-taskscheduler-zap2xml-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-taskscheduler-zap2xml-01.png -------------------------------------------------------------------------------- /images/synology-taskscheduler-zap2xml-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-taskscheduler-zap2xml-02.png -------------------------------------------------------------------------------- /images/synology-taskscheduler-zap2xml-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/synology-taskscheduler-zap2xml-03.png -------------------------------------------------------------------------------- /images/tvheadend-configuration-epg-chaines-liste-chaine_epg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-configuration-epg-chaines-liste-chaine_epg.png -------------------------------------------------------------------------------- /images/tvheadend-configuration-epg-modules_epg-general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-configuration-epg-modules_epg-general.png -------------------------------------------------------------------------------- /images/tvheadend-configuration-epg-modules_epg-internal_grabber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-configuration-epg-modules_epg-internal_grabber.png -------------------------------------------------------------------------------- /images/tvheadend-configuration-epg-modules_epg-run_internal_grabbers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-configuration-epg-modules_epg-run_internal_grabbers.png -------------------------------------------------------------------------------- /images/tvheadend-configuration-epg-modules_epg-tv_grab_file-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-configuration-epg-modules_epg-tv_grab_file-settings.png -------------------------------------------------------------------------------- /images/tvheadend-configuration-epg-modules_epg-tv_grab_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-configuration-epg-modules_epg-tv_grab_file.png -------------------------------------------------------------------------------- /images/tvheadend-configuration-general-base-icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-configuration-general-base-icons.png -------------------------------------------------------------------------------- /images/tvheadend-kodi_label_formatting_support.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-kodi_label_formatting_support.png -------------------------------------------------------------------------------- /images/tvheadend-menu-configuration-epg-chaines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-menu-configuration-epg-chaines.png -------------------------------------------------------------------------------- /images/tvheadend-menu-configuration-epg-collecteur_epg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-menu-configuration-epg-collecteur_epg.png -------------------------------------------------------------------------------- /images/tvheadend-menu-configuration-epg-modules_epg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-menu-configuration-epg-modules_epg.png -------------------------------------------------------------------------------- /images/tvheadend-menu-configuration-general-base-Web_Interface_Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-menu-configuration-general-base-Web_Interface_Settings.png -------------------------------------------------------------------------------- /images/tvheadend-menu-configuration-general-base.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvheadend-menu-configuration-general-base.png -------------------------------------------------------------------------------- /images/tvlisting.zap2it-favoris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/th0ma7/synology/ddf793ec22222b3c4f25a9e4e5c914dcf3d035a5/images/tvlisting.zap2it-favoris.png -------------------------------------------------------------------------------- /kernel/synocli-kernelmodule.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ######################################################################### 4 | # Written by: th0ma7@gmail.com 5 | # Part of SynoCommunity Developpers 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | ######################################################################### 20 | 21 | #------------------------------------------------ 22 | # Make sure an argument was passed 23 | #------------------------------------------------ 24 | usage() { 25 | echo 26 | printf '%10s %s\n' "Usage :" "$0 [-s|--spk ] [] module1.ko module2.ko ..." 27 | printf '%20s %s\n' "Optional :" "[-c|--config :,,...]" 28 | printf '%20s %s\n' "" "[-u|--udev ]" 29 | echo 30 | printf '%40s %s\n' "[-s|--spk ] : " "SynoCommunity package name containing kernel modules" 31 | printf '%40s %s\n' "[] : " "Action to be performed" 32 | printf '%40s %s\n' "[-h|--help] : " "Print this help" 33 | printf '%40s %s\n' "[-v|--verbose] : " "Verbose mode" 34 | echo 35 | printf '%10s %s\n' "" "Examples :" 36 | printf '%20s %s\n' "" "$0 --spk synokernel-cdrom --verbose cdrom sr_mod status" 37 | printf '%20s %s\n' "" "$0 --spk synokernel-cdrom --config synokernel-cdrom.cfg:default status" 38 | printf '%20s %s\n' "" "$0 --spk synokernel-usbserial --udev 60-synokernel-usbserial.rules usbserial ch341 cp210x status" 39 | printf '%20s %s\n' "" "$0 --spk synokernel-usbserial --config synokernel-usbserial.cfg:ch341,cp210x status" 40 | echo 41 | } 42 | 43 | #------------------------------------------------ 44 | # Print detailed information for debugging 45 | #------------------------------------------------ 46 | verbose() { 47 | printf '%20s %s\n' "" "$0 (verbose)" 48 | printf '%60s %s\n' "SynoCommunity kernel driver package name (SPK)" "[${SPK}]" 49 | printf '%60s %s\n' "SynoCommunity configuration file (SPK_CFG)" "[${SPK_CFG}]" 50 | printf '%60s %s\n' "SynoCommunity configuration path (SPK_CFG_PATH)" "[${SPK_CFG_PATH}]" 51 | printf '%60s %s\n' "SynoCommunity configuration option (SPK_CFG_OPT)" "[${SPK_CFG_OPT}]" 52 | printf '%60s %s\n' "Synology NAS arch (ARCH)" "[${ARCH}]" 53 | printf '%60s %s\n' "Synology DSM version (DSM_VERSION)" "[${DSM_VERSION}]" 54 | printf '%60s %s\n' "Running kernel version (KVER)" "[${KVER}]" 55 | printf '%60s %s\n' "Module action insmod|rmmod|reload|status (ACTION)" "[${ACTION}]" 56 | printf '%60s %s\n' "Kernel modules path (MPATH)" "[${MPATH}]" 57 | printf '%60s %s\n' "Full kernel modules path (KPATH)" "[${KPATH}]" 58 | printf '%60s %s\n' "Device firmware path (FPATH)" "[${FPATH}]" 59 | printf '%60s %s\n' "udev rules.d path (UPATH)" "[${UPATH}]" 60 | printf '%60s %s\n' "udev rules.d file (URULE)" "[${URULE}]" 61 | printf '%60s %s\n' "Kernel objects list (KO_LIST)" "[${KO_LIST}]" 62 | printf '%60s %s\n' "Kernel objects found (KO_PATH)" "[${KO_PATH}]" 63 | } 64 | 65 | 66 | #------------------------------------------------ 67 | # Get all kernel modules from configuration file 68 | # based on passed configuration option 69 | #------------------------------------------------ 70 | get_ko_list() { 71 | ko_list_cfg="" 72 | 73 | if [ "${SPK_CFG}" ]; then 74 | # Check that configuration exists (if requested) 75 | if [ ! -f ${SPK_CFG_PATH}/${SPK_CFG} ]; then 76 | usage 77 | echo -ne "\nERROR: Configuration file [${SPK_CFG_PATH}/${SPK_CFG}] does not exist or inaccessible...\n\n" 78 | exit 1 79 | fi 80 | 81 | # Always include default first 82 | ko_list_cfg=$(sed -n "s/^default:\(.*\)/\1/p" ${SPK_CFG_PATH}/${SPK_CFG}) 83 | if [ ! "${ko_list_cfg}" ]; then 84 | usage 85 | echo -ne "\nERROR: Configuration option [default] not found in file [${SPK_CFG_PATH}/${SPK_CFG}]...\n\n" 86 | exit 1 87 | fi 88 | 89 | IFS="," 90 | for config in ${SPK_CFG_OPT} 91 | do 92 | ko_list_cfg_tmp=$(sed -n "s/^${config}:\(.*\)/\1/p" ${SPK_CFG_PATH}/${SPK_CFG}) 93 | if [ ! "${ko_list_cfg}" ]; then 94 | usage 95 | echo -ne "\nERROR: Configuration option [${config}:] not found in file [${SPK_CFG_PATH}/${SPK_CFG}]...\n\n" 96 | exit 1 97 | fi 98 | ko_list_cfg+="${ko_list_cfg_tmp} " 99 | done 100 | IFS=" " 101 | fi 102 | 103 | # Return merged module list from config file and 104 | # parameters passed as arguments but keep its order, 105 | # starting with the config file followed by args 106 | echo ${ko_list_cfg} ${KO_LIST_ARG} | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}' | xargs 107 | } 108 | 109 | 110 | #------------------------------------------------ 111 | # Modules can be passed as: 112 | # 113 | # .ko 114 | # //* 115 | # The following find the right module as needed 116 | #------------------------------------------------ 117 | ko_path_match() { 118 | ko_find="" 119 | ko_path="" 120 | ko_missing="" 121 | 122 | for ko in $KO_LIST 123 | do 124 | # first check if the name 125 | # matches to a path 126 | if [ ! "$(echo $ko | grep '/')" ]; then 127 | # Ensure to add .ko if needed 128 | [ ! "$(echo $ko | grep '.ko$')" ] && ko=$ko.ko 129 | # Replace any '-' or '_' by '[-_] 130 | ko=$(echo ${ko} | sed -r 's/[-_]/[-_]/g') 131 | # Find full module kernel object path 132 | ko_find=$(find $KPATH -name $ko) 133 | [ ! "$ko_find" ] && ko_missing+="$ko " 134 | fi 135 | ko_path+="${ko_find##*${KVER}} " 136 | done 137 | 138 | # Return missing modules in case of error 139 | # else return the list of found modules 140 | [ ! "${ko_missing}" ] \ 141 | && echo "$ko_path" | xargs \ 142 | || echo "missing: ${ko_missing}" | xargs 143 | } 144 | 145 | # exit if no parameters passed 146 | [ $# -eq 0 ] && usage && exit 1 147 | 148 | # must be root to load/unload kernel modules 149 | if [ ! "$(id -un)" = "root" ]; then 150 | verbose && usage 151 | echo 152 | echo "ERROR: Must have root or sudo priviledges..." 153 | echo 154 | exit 1 155 | fi 156 | 157 | 158 | ### 159 | ### Global variables 160 | ### 161 | SPK="" # SynoCommunity kernel driver package name 162 | SPK_CFG="" # SynoCommunity configuration file 163 | SPK_CFG_OPT="" # SynoCommunity configuration option 164 | SPK_CFG_PATH="" # SynoCommunity configuration path 165 | ACTION="" # Module action insmod|rmmod|reload|status 166 | VERBOSE="FALSE" # Set verbose mode 167 | HELP="FALSE" # Print help 168 | URULE="FALSE" # Set udev rules to false by default 169 | 170 | while [ $# -gt 0 ] 171 | do 172 | case $1 in 173 | -s|--spk ) shift 1 174 | SPK=$1;; 175 | -c|--config ) shift 1 176 | SPK_CFG=$(echo $1 | cut -f1 -d:) 177 | SPK_CFG_OPT=$(echo $1 | cut -f2 -d:);; 178 | -u|--udev ) shift 1 179 | URULE=$(echo $1 | cut -f1 -d:);; 180 | -h|--help ) HELP="TRUE";; 181 | insmod|rmmod|reload|start|stop|restart|status ) ACTION=$1;; 182 | -v|--verbose ) VERBOSE="TRUE";; 183 | * ) KO_LIST_ARG+="$1 ";; 184 | esac 185 | shift 1; 186 | done 187 | 188 | ### 189 | ### Other global variables 190 | ### 191 | ARCH=$(uname -a | awk '{print $NF}' | cut -f2 -d_) # Synology NAS arch 192 | DSM_VERSION=$(sed -n 's/^productversion="\(.*\)"/\1/p' /etc/VERSION) # Synology DSM version 193 | FPATH_SYS="/sys/module/firmware_class/parameters/path" # System module firmware path file index 194 | KVER=$(uname -r | awk -F. '{print $1 "." $2 "." $3}') # Running kernel version 195 | FPATH="" # Device firmware path 196 | KPATH="" # Full kernel modules path 197 | MPATH="" # Kernel modules path 198 | KO_LIST="" # List of kernel objects to enable|disable (includes config+args) 199 | KO_LIST_ARG=$(echo ${KO_LIST_ARG} | xargs) # List of kernel objects passed in argument 200 | KO_PATH="" # List of found kernel objects (*.ko) with path (includes config+args) 201 | SYNOLOG_PATH=/var/log/packages # Default log output file 202 | SYNOLOG=${SYNOLOG_PATH}/synocli-kernelmodule.log # Default log output file 203 | 204 | # If SPK is set reassign variables 205 | if [ -n "${SPK}" ]; then 206 | SPK_CFG_PATH="/var/packages/${SPK}/target/etc" 207 | FPATH="/var/packages/${SPK}/target/lib/firmware" 208 | MPATH="/var/packages/${SPK}/target/lib/modules" 209 | UPATH="/var/packages/${SPK}/target/rules.d" 210 | KPATH="${MPATH}/${ARCH}-${DSM_VERSION}/${KVER}" 211 | SYNOLOG="${SYNOLOG_PATH}/synocli-kernelmodule-${SPK}.log" 212 | fi 213 | 214 | # All output to SYNOLOG, STDOUT to the screen 215 | exec > >(tee -a ${SYNOLOG}) 2> >(tee -a ${SYNOLOG} >/dev/null) 216 | 217 | 218 | # Get list of kernel objects from 219 | # both the configuration file and 220 | # arguments passed on cmd line 221 | KO_LIST=$(get_ko_list) 222 | 223 | # Find resulting kernel object (*.ko) full path 224 | KO_PATH=$(ko_path_match) 225 | 226 | # exit if modules are missing/not found 227 | if [ "$(echo $KO_PATH | cut -f1 -d:)" = "missing" ]; then 228 | verbose && usage 229 | echo 230 | echo "ERROR: Missing kernel modules: [$(echo $KO_PATH | cut -f2 -d: | xargs)]" 231 | echo 232 | exit 1 233 | fi 234 | 235 | # If verbose is set print default arguments 236 | [ ${VERBOSE} = "TRUE" ] && verbose 237 | 238 | [ ${HELP} = "TRUE" ] && usage && exit 0 239 | 240 | # If module path does not exists, exit 241 | if [ ! -d ${MPATH} ]; then 242 | usage 243 | echo -ne "\nERROR: Module path [${MPATH}] does not exist or inaccessible...\n\n" 244 | exit 1 245 | fi 246 | 247 | # Set kernel module .ko object base path 248 | # If does not exists, exit 249 | if [ ! -d ${KPATH} ]; then 250 | usage 251 | echo -ne "\nERROR: Kernel modules base path [${KPATH}] does not exist or inaccessible...\n\n" 252 | exit 1 253 | fi 254 | 255 | # Check that udev rules file exist 256 | if [ ! ${URULE} "FALSE" -a ! -f ${UPATH}/${URULE} ]; then 257 | usage 258 | echo -ne "\nERROR: udev rules.d file [${UPATH}/${URULE}] does not exist or inaccessible...\n\n" 259 | exit 1 260 | fi 261 | 262 | # load the requested modules 263 | load () 264 | { 265 | error=0 266 | 267 | if [ "{URULE}" ]; then 268 | echo -ne "\t[enable] optional udev rules...\n" 269 | printf '%40s %-34s' "" "[$URULE]" 270 | ln -s ${UPATH}/${URULE} /lib/udev/rules.d/${URULE} 271 | udevadm control --reload-rules 272 | if [ $? -eq 0 ]; then 273 | echo -ne " OK\n" 274 | else 275 | error=1 276 | echo -ne " N/A\n" 277 | fi 278 | fi 279 | 280 | # Add firmware path to running kernel 281 | if [ -d "${FPATH}" ]; then 282 | echo -ne "\t[loading] optional firmware path...\n" 283 | printf '%65s' "[${FPATH}]" 284 | echo "${FPATH}" > ${FPATH_SYS} 285 | if [ $? -eq 0 ]; then 286 | echo -ne " OK\n" 287 | else 288 | error=1 289 | echo -ne " N/A\n" 290 | fi 291 | fi 292 | 293 | echo -ne "\t[insmod] kernel modules...\n" 294 | for ko in $KO_PATH 295 | do 296 | module=$(echo "${ko}" | sed -e 's/.*\///' -e 's/-/_/' -e 's/\.ko//') 297 | printf '%40s %-35s' $ko "[$module]" 298 | 299 | status=$(lsmod | grep "^$module ") 300 | if [ $? -eq 0 -a "status" ]; then 301 | echo "Already Loaded" 302 | else 303 | if [ -f $KPATH/$ko ]; then 304 | insmod $KPATH/$ko 305 | [ $? -eq 0 ] && echo "OK" || echo "ERROR" 306 | else 307 | echo "ERROR: Module $KPATH/$ko not found!" 308 | error=1 309 | fi 310 | fi 311 | done 312 | 313 | return $error 314 | } 315 | 316 | 317 | # unload the requested modules in a reversed order 318 | unload () 319 | { 320 | error=0 321 | 322 | # Unload drivers in reverse order 323 | echo -ne "\t[rmmod] kernel modules...\n" 324 | for item in $KO_PATH; do echo $item; done | tac | while read ko 325 | do 326 | module=$(echo "${ko}" | sed -e 's/.*\///' -e 's/-/_/g' -e 's/\.ko//') 327 | printf '%40s %-35s' $ko "[$module]" 328 | status=$(lsmod | grep "^$module ") 329 | if [ $? -eq 0 -a "status" ]; then 330 | rmmod $module 331 | echo -ne "N/A\n" 332 | else 333 | echo -ne "ERROR\n" 334 | error=1 335 | fi 336 | done 337 | 338 | # Remove firmware path to running kernel 339 | if [ -d "${FPATH}" ]; then 340 | echo -ne "\t[unloading] optional firmware path...\n" 341 | echo "" > ${FPATH_SYS} 342 | error=$? 343 | fi 344 | 345 | # Remove udev rules 346 | if [ "{URULE}" ]; then 347 | echo -ne "\t[remove] optional udev rules...\n" 348 | printf '%40s %-34s' "" "[$URULE]" 349 | rm -f /lib/udev/rules.d/${URULE} 350 | udevadm control --reload-rules 351 | if [ $? -eq 0 ]; then 352 | echo -ne " N/A\n" 353 | else 354 | error=1 355 | echo -ne " ERROR\n" 356 | fi 357 | fi 358 | 359 | return $error 360 | } 361 | 362 | 363 | # Provide a status of the loaded modules 364 | status () 365 | { 366 | error=0 367 | 368 | echo -ne "\t[status] kernel modules...\n" 369 | for ko in $KO_PATH 370 | do 371 | module=$(echo "${ko}" | sed -e 's/.*\///' -e 's/-/_/g' -e 's/\.ko//') 372 | printf '%40s %-35s' $ko "[$module]" 373 | 374 | status=$(lsmod | grep "^$module ") 375 | if [ $? -eq 0 -a "status" ]; then 376 | echo -ne "OK\n" 377 | else 378 | error=1 379 | echo -ne "N/A\n" 380 | fi 381 | done 382 | 383 | # Validate option firmware path 384 | if [ -d "${FPATH}" ]; then 385 | echo -ne "\t[status] of optional firmware path...\n" 386 | printf '%65s' "[${FPATH}]" 387 | 388 | grep -q ${FPATH} ${FPATH_SYS} 389 | if [ $? -eq 0 ]; then 390 | echo -ne " OK\n" 391 | else 392 | error=1 393 | echo -ne " N/A\n" 394 | fi 395 | fi 396 | 397 | # Validate udev rules (not much can be done) 398 | if [ "{URULE}" ]; then 399 | echo -ne "\t[status] of optional udev rules...\n" 400 | printf '%40s %-34s' "" "[$URULE]" 401 | if [ -h /lib/udev/rules.d/${URULE} ]; then 402 | echo -ne " OK\n" 403 | else 404 | error=1 405 | echo -ne " N/A\n" 406 | fi 407 | fi 408 | 409 | return $error 410 | } 411 | 412 | 413 | case $ACTION in 414 | insmod|start) 415 | if status; then 416 | echo ${SPK} is already running 417 | exit 0 418 | else 419 | echo Starting ${SPK} ... 420 | load 421 | exit $? 422 | fi 423 | ;; 424 | rmmod|stop) 425 | if status; then 426 | echo Stopping ${SPK} ... 427 | unload 428 | exit $? 429 | else 430 | echo ${SPK} is not running 431 | exit 0 432 | fi 433 | ;; 434 | reload|restart) 435 | echo -ne "---\nReloading ${SPK} package...\n" 436 | unload 437 | load 438 | exit $? 439 | ;; 440 | status) 441 | echo -ne "---\nStatus of ${SPK} package...\n" 442 | if status; then 443 | echo ${SPK} is running 444 | exit 0 445 | else 446 | echo ${SPK} is not running 447 | exit 1 448 | fi 449 | ;; 450 | *) usage 451 | exit 1 452 | ;; 453 | esac 454 | -------------------------------------------------------------------------------- /tvheadend-backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DEST=/volume1/backup/tvheadend 4 | DATE=`date +%Y%m%d-%H%M` 5 | 6 | tar -C /var/packages/tvheadend/target -jcvf - \ 7 | --exclude='.lock' \ 8 | --exclude='tvheadend.pid' \ 9 | cache var \ 10 | bin/tv_grab_file bin/zap2xml.pl bin/zap2xml.sh perl5 .cpan .xmltv \ 11 | share/tvheadend/data/dvb-scan/atsc/ca-QC-saint-jean-sur-richelieu \ 12 | > $DEST/tvheadend-backup-$DATE.tar.bz2 13 | --------------------------------------------------------------------------------