Kernel - DVB-S2 Tuner Driver Patch - help request - Technisat SkyStar USB 2 HD CI



I’m running OSMC on a Pi0 and would like to connect my DVB-S2 adapter to it and use tvheadend to stream on localhost. I’ll compile tvheadend on my own (start it too) and in Kodi I already have installed the PVR HTS tvheadend plugin, which is working good when used for tvheadend streams from another systems.

My DVB adapter has an unsupported patch and I’m not able to recompile it for the kernel that comes with OSMC - OSMC_TGT_rbp1_20170803.img
I’d be thankful if some of the developers could help me and recompile the attached patched tuner file.

Since I’m not able to attach it to this post, I’ve uploaded the source file at:

stb0899_drv.c - 45kb
md5sum - b87d73227fa6579969098cf6ecd91ddc

This driver (frontend) will be created in:

Thank you in advance!


I might be able to help myself if I know where to get the kernel headers. Not sure I’ll be able to compile anything under the pi0 since OSMC is really stripped down and I don’t have any toolchain.

I’ve found a kernel build script at:

And by looking at it I learned that for rpi1 it’s using the Kernel 4.9.29
test $1 == rbp1 && VERSION=“4.9.29”

In order to get the kernel headers, can I then just download the kernel source for 4.9.29 form and just use it ?
Will I be able to get the necessary toolchain components (c/c++/perl… etc) directly from Debian with apt-get ?

Thanks again for any help!


You can build on a Pi 0, albeit a little slowly.
I recommend stopping Kodi.

Here’s how:

git clone
cd osmc/package/kernel-osmc
make rbp1




Thank you very much for your confirmation and hint.

Since the kernel is compiled with CONFIG_MODVERSIONS enabled, I was looking for the kernel headers and Module.symvers only and considered to build only the module I need, or, use the media_build and rebuild only the media dirivers and not the whole kernel. This is why I was referring to perl - it is used by the media_build:

Compiling the whole kernel again with the patched driver will indeed take a lot of time on a pi0. I could use a spare Pi2/Pi3 but I’m afraid that the resulting code won’t be armv6 compatible. I have no Idea what these new Linux Distributions have hidden in their build scripts. I’m used to compile everything by hand (more like BSD style) and I think I’ll use the pi0 for the kernel compilation, at least I’m sure that these Debian build automation scripts will take the correct platform architecture (armv6) for the build.

Problem resolved. Consider this thread closed / resolved.


A Pi2/Pi3 will be able to build the kernel for Pi0 and we
pick the correct toolchain automatically.

The reason I’d recommend building with OSMC’s build system is so that we can
get the patch included in OSMC proper and in turn, in the next update. We don’t
recommend using DKMS, and compiling the driver every update would be rather
frustating for you



Thanks again! I much appreciate your help!
I’ll use a Pi2/3 for the compilation then. Sorry, I’m not used with Debian - never used it (& never will).

I don’t know if the patch is interesting enough for other people. There was an old Technisat SkyStar USB 2 CI DVB-S2 adapter sold everywhere in Europe by the time DVB-S2 was “hot” and this adapter has 2 internal tuners (DVB & DVB-S2) and an unsupported patch:

Following the patch instructions from there won’t work anymore, only a manual patch (manual editing - copy/paste) will. The source file attached in my original post is already patched and working (using it for 2-3 years).


On the kernel update Frustration - I’d like to elaborate a little bit. THIS is exactly my problem now. I used to update the kernel from Raspbian on every new release, by taking the kernel headers and recompiling the media_build with the patched driver. A process that I already automated on my beloved Linux distro and which takes only 40 minutes on a Pi2B. The most frustrating part was to boot the Rasbian itself in order to take the kernel headers for the new and running kernel.
I came across OSMC and got wondered that it is able to reproduce FullHD at 50FPS on the pi0 - some new DVB-S2 channels use this demanding format. My beloved Linux distro has only a SoftFloat port for the already obsolete armv6 and under SoftFloat the FPU (VFP code) is not used optimally, thus at FullHD 50FPS I get frame drops in Kodi. I’m considering now to patch the OSMC on the pi0 and embed the pi0 in my USB DVB-S2 adapter (plenty of space inside the plastic case and enough internal electric power to feed it through a 5V positive regulator) and forget it there until the tuner itself dies. No more frustrating updates! :slight_smile:


Any chances to get a kernel pre 4.4.8 for Raspberry Pi ?

There are issues with DVB over USB starting from 4.4.8:

I personally had those DVB Stream continuity issues on my actual (non-OSMC) system and I’m using the 4.4.50 ATM. While I started the compilation on my pi0, I’m afraid that the result will not work. I tried to modify the script:
test $1 == rbp1 && VERSION=“4.9.29” && REV=“11” && FLAGS_INITRAMFS=$(($INITRAMFS_BUILD + $INITRAMFS_EMBED)) && IMG_TYPE=“zImage”


test $1 == rbp1 && VERSION=“4.4.0” && REV=“13” && FLAGS_INITRAMFS=$(($INITRAMFS_BUILD + $INITRAMFS_EMBED)) && IMG_TYPE=“zImage”

but ran into patch/build issues.



Sorry - 4.4 is EOL on OSMC for some time now


I’m really sorry, I made a mistake with the version of the kernel I’m looking after. I was really tired.
It’s not 4.4.x, but:

kernel 4.8.13 or below

Is there any version that you’ve used in a previous OSMC release and on which the current patches / kernel config will apply and I’m able to substitute in the build script?
test $1 == rbp1 && VERSION=“4.9.29” && REV=“11”

Thanks again!



You can use 4.4, but Pi firmware and Kodi is quite coupled to newer firmware versions.

git log with grep will show you when I moved from 4.4 to 4.9, which was around May and let you check out a 4.4 commit with appropriate config and patches



Just for the record, I managed to recompile the 4.9.29 kernel with my tuner patch. It took around 30 hours !! on a pi0 with an external HDD attached (where the compilation - working directory took place).

Unfortunately I couldn’t achieve what I was looking after. The pi0 CPU is way too weak for handling both tvheadend and Kodi and I was able to only watch DVB-S (MPEG2 - 700x500@25FPS) and DVB-S2 (MPEG4-FullHD@25FPS). However, on DVB-S2 - FullHD@25FPS Kodi’s UI was almost unusable - very slow and tvheadend was eating up around 45% of the CPU. DVB-S2 - FullHD at 50FPS (those more exotic channels) were unwatchable - the system was also unresponsive / almost crashing.
While the pi0 might work OK for FullHD@25FPS as a player device only, using it as a DVB FullHD tuner seems to not be possible due to its weak single-core CPU (the GPU is powerful enough to take the load).

@sam_nazarko - thank you again for all the help provided!


Can we have the patch anyway? Might benefit some



Of course you can have it! Happy to help!

I’m sorry but I got totally confused with the kernel compilation under Debian, a weird full-automated experience that did a lot of things I didn’t want it to (deleted Module.Symvers, cleaned the kernel source tree, packed the kernel source tree - it took 1 hour). Horrifying!
I was not sure if my generated patched driver (stb0899.ko) file would have the same module symbols as the 4.9.29-11 kernel that comes with OSMC and considered that uploading the compiled driver won’t benefit anyone, but having the source code of the patched driver, uploaded in the first post, would suffice.

I just tested now my resulted stb0899.ko - substituted the files - in the 4.9.29-11 kernel that comes with OSMC, loaded the driver (connected the DVB-USB adapter) and haven’t got any module versions mismatch (kernel was happy).

Here you can find (links are only 30 days available) the patched and compiled stb0899.ko driver for the 4.9.29-11 kernel:

md5sum stb0899.ko

To make the USB DVB adapter work, you need to follow the instructions from:

Just for helping out, this is what I did on my Linux system (not Debian - file locations might differ):
Disable DVB USB - Power Management:
ACTION==“add”, SUBSYSTEM==“usb”, ATTR{product}==“SkyStar 2 HD CI”, ATTR{power/control}=“on”

Disable the DVB USB - IR reciever (I couldn’t make it work and used an IR sensor connected to the Pi’s GPIO instead):
options dvb_usb disable_rc_polling=1

  • then these 2 IR related lines should disappear form your dmesg output:
    [ 8158.178642] input: IR-receiver inside an USB DVB receiver as /devices/platform/soc/20980000.usb/usb1/1-1/1-1.4/input/input0
    [ 8158.178676] dvb-usb: schedule remote query interval to 400 msecs.

dmesg - normal (successful) modules&firmware load:
[ 8150.367283] usb 1-1.4: new high-speed USB device number 5 using dwc_otg
[ 8150.539320] usb 1-1.4: New USB device found, idVendor=14f7, idProduct=0001
[ 8150.539385] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 8150.539400] usb 1-1.4: Product: UDST70XX
[ 8150.539412] usb 1-1.4: Manufacturer: DTV-DVB
[ 8150.539422] usb 1-1.4: SerialNumber: XXXXXXXXXXXXX
[ 8156.277439] dvb-usb: found a ‘Technisat SkyStar USB 2 HD CI’ in cold state, will try to load a firmware
[ 8157.072236] dvb-usb: downloading firmware from file ‘dvb-usb-az6027-03.fw’
[ 8157.175178] dvb-usb: found a ‘Technisat SkyStar USB 2 HD CI’ in warm state.
[ 8157.183998] dvb-usb: will pass the complete MPEG2 transport stream to the software demuxer.
[ 8157.393316] DVB: registering new adapter (Technisat SkyStar USB 2 HD CI)
[ 8158.154708] stb0899_attach: Attaching STB0899
[ 8158.154750] stb6100_attach: Attaching STB6100
[ 8158.177702] usb 1-1.4: DVB: registering adapter 0 frontend 0 (STB0899 Multistandard)…
[ 8158.178689] dvb-usb: Technisat SkyStar USB 2 HD CI successfully initialized and connected.
[ 8158.183303] usbcore: registered new interface driver dvb_usb_az6027

If you switch the channels too fast - mainly between DVB-S and DVB-S2 channels you might lock the adapter/USB bus and your system log files will be populated with the errors below. You might want to play with tvheadend’s tuning delays, if any, I haven’t got time to investigate too much.
The ONLY RESOLUTION is to restart the system (Linux).
Disconnecting/reconnecting the adapter won’t help! It hapens to me once a week or so…

Sep 10 17:42:19 bnk tvheadend[1470]: linuxdvb: STB0899 Multistandard : DVB-S #0 - retune nodata
Sep 10 17:42:24 bnk tvheadend[1470]: linuxdvb: STB0899 Multistandard : DVB-S #0 - poll TIMEOUT
Sep 10 17:42:29 bnk tvheadend[1470]: linuxdvb: STB0899 Multistandard : DVB-S #0 - retune nodata
Sep 10 17:42:32 bnk tvheadend[1470]: linuxdvb: STB0899 Multistandard : DVB-S #0 - poll TIMEOUT
Sep 10 17:42:34 bnk tvheadend[1470]: linuxdvb: STB0899 Multistandard : DVB-S #0 - retune nodata
Sep 10 17:42:39 bnk tvheadend[1470]: linuxdvb: STB0899 Multistandard : DVB-S #0 - poll TIMEOUT
Sep 10 17:42:47 bnk tvheadend[1470]: linuxdvb: STB0899 Multistandard : DVB-S #0 - poll TIMEOUT

You could use irexec (script execution utility that comes with lirc) and allocate a button on your remote control to restart the system:
prog = irexec
remote = Technisat_TTS35AI.conf
button = EXT
config = /sbin/shutdown -r now
repeat = 0

Have Fun!



No need for a compiled driver.
Send us the patch / changes please.

git diff in your tree will be fine


I don’t have my OSMC working directory / modified images anymore - cleaned everything and only got a kernel.deb file left. As previously reported it’s useless in my scenario and I already have optimized/stripped self-compiled FFmpeg & Kodi under my Linux arm distro - SoftFloat that are performing better/faster than OSMC.
Sorry, I cannot:

Ever since I originally patched stb0899_drv.c I was using the source from the media_tree and not the
one from the official kernel tree - which has some more modifications, but still doesn’t work without the patch.
The patch itself was created for the source from media_tree!
Every time (in the last 2 years or so) I was upgrading the kernel I just substituted the stb0899_drv.c that came with the kernel with my patched one, then recompiled the stb0899_drv.c driver only.

Original file from media_tree that I was first patching and still using:
It hasn’t been modified since 2014:

And here is the patch (diff):
diff -u stb0899_drv.c stb0899_drv-PATCHED_OK.c > stb0899_drv.patch
cat stb0899_drv.patch

--- stb0899_drv.c       2017-09-12 23:19:21.000000000 +0300
+++ stb0899_drv-PATCHED_OK.c    2017-09-12 23:11:01.184163331 +0300
@@ -306,19 +306,22 @@
                .len    = 6

-       struct i2c_msg msg_1 = {
-               .addr   = state->config->demod_address,
-               .flags  = 0,
-               .buf    = buf_1,
-               .len    = 2
-       };

-       struct i2c_msg msg_r = {
-               .addr   = state->config->demod_address,
-               .flags  = I2C_M_RD,
-               .buf    = buf,
-               .len    = 4
-       };
+       struct i2c_msg msg[] = {
+               {
+                       .addr   = state->config->demod_address,
+                       .flags  = 0,
+                       .buf    = buf_1,
+                       .len    = 2
+               }, {
+                       .addr   = state->config->demod_address,
+                       .flags  = I2C_M_RD,
+                       .buf    = buf,
+                       .len    = 4
+               }
+       };

        tmpaddr = stb0899_reg_offset & 0xff00;
        if (!(stb0899_reg_offset & 0x8))
@@ -327,6 +330,8 @@
        buf_1[0] = GETBYTE(tmpaddr, BYTE1);
        buf_1[1] = GETBYTE(tmpaddr, BYTE0);

+       /* Write address        */
        status = i2c_transfer(state->i2c, &msg_0, 1);
        if (status < 1) {
                if (status != -ERESTARTSYS)
@@ -337,28 +342,16 @@

        /* Dummy        */
-       status = i2c_transfer(state->i2c, &msg_1, 1);
-       if (status < 1)
-               goto err;
-       status = i2c_transfer(state->i2c, &msg_r, 1);
-       if (status < 1)
+       status = i2c_transfer(state->i2c, msg, 2);
+       if (status < 2)
                goto err;

        buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
        buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);

        /* Actual       */
-       status = i2c_transfer(state->i2c, &msg_1, 1);
-       if (status < 1) {
-               if (status != -ERESTARTSYS)
-                       printk(KERN_ERR "%s ERR(2), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
-                              __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
-               goto err;
-       }
-       status = i2c_transfer(state->i2c, &msg_r, 1);
-       if (status < 1) {
+       status = i2c_transfer(state->i2c, msg, 2);
+       if (status < 2) {
                if (status != -ERESTARTSYS)
                        printk(KERN_ERR "%s ERR(3), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
                               __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
@@ -485,8 +478,15 @@
            (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
                _stb0899_read_reg(state, (reg | 0x00ff));

-       dprintk(state->verbose, FE_DEBUGREG, 1,
-               "%s [0x%04x]: %*ph", __func__, reg, count, buf);
+       if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+               int i;
+               printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+               for (i = 0; i < count; i++) {
+                       printk(" %02x", buf[i]);
+               }
+               printk("\n");
+       }

        return 0;
@@ -515,8 +515,14 @@
        buf[1] = reg & 0xff;
        memcpy(&buf[2], data, count);

-       dprintk(state->verbose, FE_DEBUGREG, 1,
-               "%s [0x%04x]: %*ph", __func__, reg, count, data);
+       if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+               int i;
+               printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+               for (i = 0; i < count; i++)
+                       printk(" %02x", data[i]);
+               printk("\n");
+       }
        ret = i2c_transfer(state->i2c, &i2c_msg, 1);

@@ -601,19 +607,13 @@
        return 0;

-static void stb0899_detach(struct dvb_frontend *fe)
-       struct stb0899_state *state = fe->demodulator_priv;
-       /* post process event */
-       stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
 static void stb0899_release(struct dvb_frontend *fe)
        struct stb0899_state *state = fe->demodulator_priv;

        dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
+       /* post process event */
+       stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);

@@ -1579,7 +1579,7 @@
        return DVBFE_ALGO_CUSTOM;

-static const struct dvb_frontend_ops stb0899_ops = {
+static struct dvb_frontend_ops stb0899_ops = {
        .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
        .info = {
                .name                   = "STB0899 Multistandard",
@@ -1596,7 +1596,6 @@

-       .detach                         = stb0899_detach,
        .release                        = stb0899_release,
        .init                           = stb0899_init,
        .sleep                          = stb0899_sleep,

The official kernel tree driver file was modified 2016 and I’ve never used it, actually it doesn’t work with the Technisat DVB adapter, nor did I attempt to patch it! The patch is rejected and I’m not a maintainer but just a simple (happy too - got a working DVB adapter) user :slight_smile: