FAQ SynocliKernel (usbserial, linuxtv) - SynoCommunity/spksrc GitHub Wiki

SynoCommunity packages Kernel specific FAQ

Packages

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. Module loading helper script can be called with --help --verbose in order to get additional details:

./synocli-kernelmodule.sh --spk synokernel-usbserial --config synokernel-usbserial.cfg:ch341,cp210x --verbose --udev 60-synokernel-usbserial.rules status --help
                     ./synocli-kernelmodule.sh (verbose)
              SynoCommunity kernel driver package name (SPK) [synokernel-usbserial]
                  SynoCommunity configuration file (SPK_CFG) [synokernel-usbserial.cfg]
             SynoCommunity configuration path (SPK_CFG_PATH) [/var/packages/synokernel-usbserial/target/etc]
            SynoCommunity configuration option (SPK_CFG_OPT) [ch341,cp210x]
                                    Synology NAS arch (ARCH) [apollolake]
                          Synology DSM version (DSM_VERSION) [6.2.4]
                               Running kernel version (KVER) [4.4.59+]
           Module action insmod|rmmod|reload|status (ACTION) [status]
                                 Kernel modules path (MPATH) [/var/packages/synokernel-usbserial/target/lib/modules]
                            Full kernel modules path (KPATH) [/var/packages/synokernel-usbserial/target/lib/modules/apollolake-6.2.4/4.4.59+]
                                Device firmware path (FPATH) [/var/packages/synokernel-usbserial/target/lib/firmware]
                                   udev rules.d path (UPATH) [/var/packages/synokernel-usbserial/target/rules.d]
                                   udev rules.d file (URULE) [60-synokernel-usbserial.rules]
                               Kernel objects list (KO_LIST) [usbserial ch341 cp210x]
                              Kernel objects found (KO_PATH) [/drivers/usb/serial/usbserial.ko /drivers/usb/serial/ch341.ko /drivers/usb/serial/cp210x.ko]

   Usage : ./synocli-kernelmodule.sh [-s|--spk <package>] [<insmod,start|rmmod,stop|reload,restart|status>] module1.ko module2.ko ...
          Optional : [-c|--config <file>:<option1>,<option2>,...]
                     [-u|--udev <file>]

                 [-s|--spk <package>] :  SynoCommunity package name containing kernel modules
       [<insmod|rmmod|reload|status>] :  Action to be performed
                          [-h|--help] :  Print this help
                       [-v|--verbose] :  Verbose mode

           Examples :
                     ./synocli-kernelmodule.sh --spk synokernel-cdrom --verbose cdrom sr_mod status
                     ./synocli-kernelmodule.sh --spk synokernel-cdrom --config synokernel-cdrom.cfg:default status
                     ./synocli-kernelmodule.sh --spk synokernel-usbserial --udev 60-synokernel-usbserial.rules usbserial ch341 cp210x status
                     ./synocli-kernelmodule.sh --spk synokernel-usbserial --config synokernel-usbserial.cfg:ch341,cp210x status

synokernel-cdrom

This is a basic simple kernel module package that can used as example. It provides cdrom.ko and sr_mod.ko kernel modules that can be used to connect USB based CD-ROM to your NAS using the synocli-kernel helper script such as:

./synocli-kernelmodule.sh --spk synokernel-cdrom --config synokernel-cdrom.cfg:default insmod

dmesg output should provide something similar to:

[3553418.051365] usb 2-1: new SuperSpeed USB device number 2 using xhci_hcd
[3553418.069471] usb 2-1: LPM exit latency is zeroed, disabling LPM.
[3553418.077353] usb-storage 2-1:1.0: USB Mass Storage device detected
[3553418.084541] scsi host6: usb-storage 2-1:1.0
[3553419.104008] scsi 6:0:0:0: CD-ROM            PIONEER  BD-RW   BDR-XD05         3.01 PQ: 0 ANSI: 0
[3553419.114808] scsi 6:0:0:0: Attached scsi generic sg5 type 5
[3790953.029269] sr 6:0:0:0: [sr0] scsi3-mmc drive: 62x/62x writer dvd-ram cd/rw xa/form2 cdda tray
[3790953.039237] cdrom: Uniform CD-ROM driver Revision: 3.20
[3790953.045785] sr 6:0:0:0: Attached scsi CD-ROM sr0

Unloading the module using:

./synocli-kernelmodule.sh --spk synokernel-cdrom --config synokernel-cdrom.cfg:default rmmod

Will produce following output to dmesg:

[3790963.004714] cdrom: Uniform CD-ROM driver unloaded

synokernel-usbserial

This relatively simple kernel module package also includes udev rules to get access to the needed device file with proper permissions. It provides usbserial.ko, ch341.ko, cp210x.ko, pl2303.ko, ti_usb3410_5052.ko and ftdi_sio.ko kernel modules that can be used to connect a USB-Serial adapter. synocli-kernel helper script can be used such as:

./synocli-kernelmodule.sh --spk synokernel-usbserial --config synokernel-usbserial.cfg:ch341,cp210x --udev 60-synokernel-usbserial.rules start

dmesg output should provide something similar to:

[3994283.661384] usbcore: registered new interface driver usbserial
[3994283.695707] usbcore: registered new interface driver ch341
[3994283.702615] usbserial: USB Serial support registered for ch341-uart
[3994283.731617] usbcore: registered new interface driver cp210x
[3994283.738064] usbserial: USB Serial support registered for cp210x

Unloading the module using:

./synocli-kernelmodule.sh --spk synokernel-usbserial --config synokernel-usbserial.cfg:ch341,cp210x rmmod

Will produce following output to dmesg:

[3994653.045224] usbserial: USB Serial deregistering driver cp210x
[3994653.052259] usbcore: deregistering interface driver cp210x
[3994653.080559] usbserial: USB Serial deregistering driver ch341-uart
[3994653.087806] usbcore: deregistering interface driver ch341
[3994653.113854] usbcore: deregistering interface driver usbserial

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
⚠️ **GitHub.com Fallback** ⚠️