Skip to content

FAQ SynocliKernel (usbserial, linuxtv)

Vincent Fortier edited this page Feb 24, 2021 · 7 revisions

SynoCommunity packages Kernel specific FAQ

Packaging

synocli-kernel

A package called synocli-kernel provides lower-level USB helpers and scripts to help upon module loading and unloading. This package should normally be a hard dependency to any other kernel module related package. To do so in spk/<package>/Makefile should include SPK_DEPENDS = synocli-kernel variable.

synokernel-usbserial

This is a basic simple kernel module package that can used as example. As all its dependencies are within the kernel itself (e.g. it does not refers to any cross/*, i.e. DEPENDS = variable is kept empty).

synokernel-linuxtv

This package applies https://linuxtv.org/ media-tree backport code over Synology's kernel source code in order to produce updated USB DVB driver modules. This allows compatibility with newer USB DVB devices with recent Synology NAS (more information below).

IMPORTANT: synokernel-linuxtv package is not compatible with VideoStation DTV advanced function.

You must disable the option in VideoStation under Settings (tab) -> DTV -> Advanced -> Disable the DTV function. Otherwise this will change the value of /lib/udev/script/DTV_enabled to yes and trigger /lib/udev/script/usb-dvb-util.sh to load all Synology default DVB modules. Theses modules will conflict with synokernel-linuxtv and may result in kernel crash.

If this option is already set:

  1. activate the checkbox in order to disable the option (yes, you enable disabling of...)
  2. reboot your system to flush out any default Synology DVB loaded modules from memory
  3. install or activate synokernel-linuxtv
  4. check out the logs under /tmp/synocli-kernelmodule-synokernel-linuxtv.log
  5. if you require assistance provide output from script /var/packages/synocli-kernel/target/bin/synocli-kernelmodule-dbg.sh that will result in a log file under the /tmp directory such as synocli-kernelmodule-dbg.20210224-0118.log

Building

Synology provides source code for the running kernel only after the release of the subsequent DSM version. Therefore in order to build kernel driver modules matching running kernel you must be running an older version of DSM (for instance continue using 6.2.3 while 6.2.4/7.0 are out).

While building is automated under the hood the package creation process is rather complex as it:

  1. Invoke REQUIRE_KERNEL=1 to prepare the kernel for module building
  2. Refers to DEPENDS=cross/linuxtv from where it download the media-tree based on the kernel version (TC_KERNEL). As of January 2021 the oldest supported kernel is version 4.4 (e.g. newest offered by Synology as of DSM-6.2.3 and DSM-7.0). Older kernel support up to version 3.10 was removed in Jan2021. Therefore, depending of the kernel version the package will be built either using the latest snapshot (>=4.4) or using latest compatible version as of 2021-01-13 (=3.10)
  3. Downloads latest DVB firmware snapshot (https://www.linuxtv.org/downloads/firmware/)
  4. Downloads latest backport patches to be applied over the media-tree for kernel compatibility (https://linuxtv.org/downloads/drivers/)
  5. Applies various patches over the resulting media-tree snapshot so it is compatible with Synology's modified kernel version
  6. Use a BLACKLIST to avoid building any PCI devices or drivers that result in build failures
  7. Use a WHITELIST to add additional USB DVB modules otherwise left aside
  8. Build all the configured modules (as per v4l2/.config)
  9. Install the modules and generate a dynamic PLIST to match resulting modules
  10. Create packages

Adding devices

The process of adding your devices the list of supported USB DVB devices shouldn't be to much of an issue for Linux enthusiast. Basically all it requires is to:

  1. Install synocli-kernel and synokernel-linuxtv packages
  2. using insmod and rmmod to load the various modules (located under /var/packages/synokernel-linuxtv/target/lib/modules/) needed to make your device to be detected. List of devices available here:
  1. once the proper set of modules and right order is found, it can be applied to the configuration files. First you need to STOP SynoKernel LinuxTV media drivers package from the Package Center
  2. adjust the configuration file for necessary modules to be loaded in: /var/packages/synokernel-linuxtv/target/etc/synokernel-linuxtv.cfg
  3. set an equivalent variable name to "true" under: /var/packages/synokernel-linuxtv/target/etc/synokernel-linuxtv.ini
  4. test the START|STOP of the package from the Package Center
  5. follow the log output under /tmp/synocli-kernelmodule-synokernel-linuxtv.log

Configuration

Kernel dependency usage is called using REQUIRE_KERNEL = 1. Automated building of modules is done through REQUIRE_KERNEL_MODULE such as:

REQUIRE_KERNEL_MODULE  = CONFIG_USB_SERIAL_OPTION:drivers/usb/serial:usbserial
REQUIRE_KERNEL_MODULE += CONFIG_USB_SERIAL_CH341:drivers/usb/serial:ch341
...

Each configuration option is a result of 3x sub-variables:

  1. Kernel configuration option
  2. Kernel directory tree where this module is located
  3. Actual module name (ending .ko omited)

When REQUIRE_KERNEL_MODULE is not empty, kernel modules ends-up being compiled & installed by spksrc.kernel.mk spksrc framework makefile helper. The installation location reflects a default kernel installation path (normally under /lib/modules) being package under install/var/packages/synokernel-usbserial/target/lib/modules under a sub-directory corresponding to the kernel version (i.e. equivalent to uname -r on NAS) such as :

modules
└── 4.4.59+
    └── kernel
        └── drivers
            └── usb
                ├── class
                │   └── cdc-acm.ko
                └── serial
                    ├── ch341.ko
                    ├── cp210x.ko
                    ├── ...

Installation/Upgrade checkbox dialog

In order at installation time to select the modules needing to be loaded, an installation/upgrade helper is being demonstrated within the synokernel-usbserial package. It consists of two main configuration files:

  1. src/synokernel-usbserial.cfg : Consists of all the modules including their directory tree starting under kernel/drivers/ path.
  2. src/synokernel-usbserial.ini : Consists of all modules required status, enabled or not (i.e. true or false). This file is being generated automatically from the GUI selection through the service-setup.sh scripts as called by SERVICE_SETUP = src/service-setup.sh variable.

There are two DSM dialog configuration files:

  1. src/wizard/install_uifile : Contains each checkbox configuration so the DSM shows the dialog window.

  2. src/wizard/upgrade_uifile.sh : Almost identical to install_uifile but in a for of a script where "defaultValue": $<variable> are being set to their previous values.

And one service script:

  1. src/service-setup.sh : Script being called at installation time (pre/post install/upgrade). This script will gather the DSM GUI selector variable values and write them to synokernel-usbserial.ini configuration file.

Variable names must match in all resulting files (.cfg, .ini and *uifile*) for it to work properly.

DSM Installation/Upgrade GUI selector

At installation time, DSM will output a module selection window allowing to check each modules to be loaded. This GUI is configured through the spk/<package>/src/wizard directory through the install_uifile file such as:

[{
    "step_title": "SynoKernel USB Serial kernel module configuration",
    "items": [{
        "type": "multiselect",
        "subitems": [{
            "key": "default",
            "desc": "USB Serial (usbserial.ko)",
            "disabled": true,
            "defaultValue": true
        },
        {
            "key": "ch341",
            "desc": "Winchiphead CH341 USB-RS232 Converter (ch341.ko)",
            "defaultValue": false
        },
        {
            "key": "cdc_acm",
            "desc": "CDC-ACM - Communication Device Class Abstract Control Model (cdc-acm.ko)",
            "defaultValue": false
        }]
    }]
}]

At upgrade time the file is slightly different as ran as a script upgrade_uifile.sh in order to adjust all the defaultValue to its corresponding real value from the previous installation:

#!/bin/sh
set +x

CFG_FILE="/usr/local/${SYNOPKG_PKGNAME}/etc/${SYNOPKG_PKGNAME}.ini"
. ${CFG_FILE}

FIRST=`/bin/cat<<EOF
{
    "step_title": "SynoKernel USB Serial kernel module configuration",
    "items": [{
        "type": "multiselect",
        "subitems": [{
            "key": "default",
            "desc": "USB Serial (usbserial.ko)",
            "disabled": true,
            "defaultValue": true
        },
        {
            "key": "ch341",
            "desc": "Winchiphead CH341 USB-RS232 Converter (ch341.ko)",
            "defaultValue": false
        },
        {
            "key": "cdc_acm",
            "desc": "CDC-ACM - Communication Device Class Abstract Control Model (cdc-acm.ko)",
            "defaultValue": false
        }]
    }]
}

EOF`

echo "[$FIRST]" > $SYNOPKG_TEMP_LOGFILE

exit 0

Post installation the updated variables will be written to /usr/local/${SYNOPKG_PKGNAME}/etc/${SYNOPKG_PKGNAME}.ini. This action is triggered by the service-setup.sh script being called post-installation and post-upgrade:

write_config() {
   echo "default=true" > ${INI}
   for option in $(cat ${CFG}); do
      var=${option%%=*}
      echo "${var}=${!var}" >> ${INI}
   done
}

Helper Scripts

start-stop-status

The default service helper script is assigned through the variable SSS_SCRIPT = src/dsm-control.sh in the spk Makefile. The script at packaging time is being renamed to /var/packages/synokernel-<package>/scripts/start-stop-status.

It will look for each variable being set to true in the .ini file and load a $KO variable with all corresponding kernel objects found in the .cfg file, always starting with default in terms of ordering. This script then calls /usr/local/bin/synocli-kernelmodule with all the necessary arguments (part of synocli-kernel package).

This script is intended to be as generic as possible so it works as-is for other kernel packages uses cases (currently being used for both synokernel-usbserial and synokernel-linuxtv).

synocli-kernelmodule

The synocli-kernel package provides the generic /usr/local/bin/synocli-kernelmodule script to help at loading/unloading/status of each modules. This script expects all modules to be provided as argument in the appropriate order and ensures to keep that order for loading and reverse it for unloading of modules. Help output:

Usage : /usr/local/bin/synocli-kernelmodule [-m <path> ] [-a <load|unload|status>] module1.ko module2.ko ...
Optional : [-f <path>] [-k <version> ] [-n <name>]

               [-m <path> ] :  Kernel module base path (OPTIONAL if -n <package> is provided)
               [-f <path> ] :  Additional firmware base path (OPTIONAL)
               [-k <path> ] :  Kernel version (OPTIONAL: uses `uname -r` if not provided)
            [-n <package> ] :  Name of the SynoCommunity package invoking this script for logging purpose
 [-a <load|unload|status> ] :  Action to be performed

           Example :
/usr/local/bin/synocli-kernelmodule -a load -k 4.4.59+ \ 
                                    -m /var/package/synokernel-usbserial/target/lib/modules \
                                       usb/serial/usbserial.ko usb/serial/ftdi_sio.ko

The output is always being redirected for DEBUG purpose into /tmp/synocli-kernelmodule-<package-name>.log such as:

	Status of kernel modules...
                           usb/serial/usbserial.ko [usbserial]              OK
                               usb/serial/ch341.ko [ch341]                  OK
                              usb/class/cdc-acm.ko [cdc_acm]                OK
                    usb/serial/ti_usb_3410_5052.ko [ti_usb_3410_5052]       OK
synokernel-usbserial is running

It can manage the addition of alternate firmware loading path such as for synokernel-linuxtv:

synokernel-linuxtv is running
	Status of kernel modules...
                               media/rc/rc-core.ko [rc_core]                OK
                                    media/mc/mc.ko [mc]                     OK
                       media/v4l2-core/videodev.ko [videodev]               OK
                          media/common/tveeprom.ko [tveeprom]               OK
        media/common/videobuf2/videobuf2-common.ko [videobuf2_common]       OK
          media/common/videobuf2/videobuf2-v4l2.ko [videobuf2_v4l2]         OK
        media/common/videobuf2/videobuf2-memops.ko [videobuf2_memops]       OK
       media/common/videobuf2/videobuf2-vmalloc.ko [videobuf2_vmalloc]      OK
                        media/dvb-core/dvb-core.ko [dvb_core]               OK
                            media/tuners/si2157.ko [si2157]                 OK
                  media/dvb-frontends/lgdt3306a.ko [lgdt3306a]              OK
                        media/usb/em28xx/em28xx.ko [em28xx]                 OK
                    media/usb/em28xx/em28xx-dvb.ko [em28xx_dvb]             OK
	Status of optional firmware path...
                    [/var/packages/synokernel-linuxtv/target/lib/firmware/] OK
synokernel-linuxtv is running
Clone this wiki locally