Using the UT-100 DVB-T modulator on Linux

In October last year I learned about the UT-100 series of DVB-T modulators available from a company in Taiwan. At that time I have already been working with software defined video broadcasting; however, I still found the idea of a small USB-stick modulator very appealing for use with embedded devices. In this post I have collected my notes about setting up and testing the UT-100 modulator on Linux.

There are four models of the UT-100 suffixed with A/B/C/D:

  • UT-100A: TX supporting 2-8 MHz and RX supporting 5-8 MHz bandwidth
  • UT-100B: TX supporting 2-8 MHz and RX supporting 2-4 MHz bandwidth
  • UT-100C: TX only supporting 2-8 MHz bandwidth
  • UT-100D: RX only supporting 2-4 MHz bandwidth

All four models work in the 50 – 950 MHz frequency range for RX and additionally in 1200 – 1350 MHz frequency range for TX. There is also an OpenCaster edition which contains an UT-100C and a special edition of OpenCaster. Since OpenCaster is open source software I highly recommend supporting the project by purchasing the OpenCaster bundle.

I got the UT-100C TX-only version (with the OpenCaster bundle) because I figured I could use the device with an RTL2832 dongle as receiver. Note, however, that RTL2832U receivers only work at 6, 7 and 8 MHz bandwidth and you will not be able to take advantage of the narrow band mode of the device.

Smoke test

You can test your device by plugging it in to a USB port and check the syslog. My UT-100C produces the following output:

$ cat /var/log/kern.log
Mar 27 22:14:07 atlantis kernel: [680631.092261] usb 6-1.4: new high-speed USB device number 25 using xhci_hcd
Mar 27 22:14:07 atlantis kernel: [680631.115851] usb 6-1.4: New USB device found, idVendor=048d, idProduct=9507
Mar 27 22:14:07 atlantis kernel: [680631.115860] usb 6-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Mar 27 22:14:07 atlantis kernel: [680631.115865] usb 6-1.4: Product: DTV Modulator
Mar 27 22:14:07 atlantis kernel: [680631.115869] usb 6-1.4: Manufacturer: GKB
Mar 27 22:14:07 atlantis kernel: [680631.115872] usb 6-1.4: SerialNumber: UT100CV2201309170031

Note that this is before the driver is installed. Installing and loading the driver will produce additional output in the log.

Installing the driver

Making the device work in Linux is actually quite straightforward thanks to the driver and SDK included in the package. Basically, you just copy the driver directory SDK_Linux/it950x_linux_v13.09.13.1/it950x_driver to your hard drive and type “make” (without the quotes). If you have gcc and the linux-headers installed, it will build without error. You will see a few warnings though.

Now you can choose to install the driver using “sudo make install”. This will copy the kernel module usb-it950x.ko to /lib/modules/kernel-version/kernel/drivers/media/ and the module will be loaded automatically by the kernel whenever the UT-100 is plugged in to the computer. However, note that the driver is installed in a version specific directory and you will have to re-install whenever you upgrade your kernel.

An alternative to the “make install” is to simply keep the driver where it is and load it manually when you need it using:

$ sudo insmod ./usb-it950x.ko

and unload it when you no longer need it using:

$ sudo rmmod ./usb-it950x.ko

Personally, I prefer the last method for now. It also allows playing with different versions of the driver.

Testing the device

The device can be tested using the sample TX application located in SDK_Linux/it950x_linux_v13.09.13.1/it950x_testkit/ it950x_testkit_tx/ . Like the driver, the test application is built by typing “make” in the directory.

First, you set up the TX parameters, then you can choose an MPEG-TS file to transmit. The TS file should be constant bitrate and fit into the channel capacity. There are a few suitable TS files included in the package. You can check them yourself using VLC to get an idea of their bitrates:

  • Wildlife.D1.H264_PC.TS is around 2.5 Mbps.
  • Wildlife.HD.H264_CB.TS is around 10 Mbps though it peaks out at 14.

The SDK document included in the kit contains formulas and tables with channel capacity based on modulator settings. To transmit Wildlife.D1.H264_PC.TS we can use QPSK in a 6 MHz channel, code rate 1/2 and guard interval 1/4. You can also use narrower channel if you have a receiver capable of receiving it.

On the receiver side we can use an RTL2832U-based receiver and VLC (or cvlc):

$ vlc dvb://frequency=730000000:bandwidth=6

Of course, this should work with any other DVB-T receiver supported by Linux. Many of the RTL2832U-based receivers are capable of working in the 1.2 GHz amateur radio band. This is true for devices with E4000 and R820T tuners, except that the DVB driver in the linux kernel limits the frequency to 862 MHz. Clayton Smith has posted a way to patch the driver.


If you got the OpenCaster bundle you should also have an application called tsrfsend on the USB disk. This application does more or less the same as the it950x_testkit_tx, except that the TX parameters are given as command line options rather by interacting with the program. This application is thus suitable to be included in pipelines.

I got v1.0c which needs to be patched to work properly. You can read the details in my forum post here. The license of this application is not quite clear to me, which is why I don’t have a modified version available for download.

Type tsrfsend without any options to get info about how to use it:

$ ./tsrfsend 
Usage: ./tsrfsend file.ts device_id frequency bandwitdh fec gi kmode qam cell_id output_gain
Example: ./tsrfsend test.ts 1 810000 8000 16 2/3 1/4 8 0 0
means: send file test.ts on device 1 at 810MHz frequency, 8MHz bandwidth, 16qam, 2/3 fec, 1/4 gi, 8k mode, 0 cell id, 0 gain
possible values are:
N device_number
KHz Frequency
2000-8000 KHz bandwidth
4|16|32 qpsk, 16qam, 32qam
1/2|2/3|3/4|5/6|7/8 fec
1/16|1/32|1/4|1/8 guard interval
2|8 2k or 8k mode
id tps-cell_id
gain output gain

Note that the TPS-cell id parameter is ignored at the moment.

To transmit the Wildlife.D1.H264_PC.TS file using tsrfsend use:

$ sudo ./tsrfsend Wildlife.D1.H264_PC.TS 0 730000 6000 4 1/2 1/4 8 0 0

The playback will not be smooth because the TS bitrate is much below the channel capacity and the tsrfsend utility does not have any rate control. I believe this is what the g_ITEAPI_TxSendCustomPacketOnce() API call is for.

You can also try the more complete OpenCaster demo file available from Avalpa (warning: almost 1 GB file). To transmit this file using tsrfsend:

$ sudo ./tsrfsend OC3.demo.ts 0 730000 8000 16 1/2 1/4 8 0 0

Udev rule

If you get tired of typing sudo all the time, you can create an udev rule with the following contents and place it in /etc/udev/rules.d/ :

SUBSYSTEMS=="usb", ATTRS{idVendor}=="048d", ATTRS{idProduct}=="9507", GROUP:="users", MODE:="0660", SYMLINK+="usb-it950x%"

The above rule will create the device owned by root:users so please ensure that you are member of the “users” group. Also make sure to use the correct vendor and product ID (look in the syslog). In particular the product ID may vary from product to product.

When the rule is created you must re-initialize the device by re-inserting it. You can now run any application using the UT-100 without sudo.

Alternate driver

I noticed that there is an alternate driver: . This is based on an older ITE driver and should have several advantages over the original driver as described in the README file.

While the small size of this driver is very appealing, I did not have much luck using it. The driver builds and loads fine; however, the test application will run only once. The second time it will report “Device or resource busy”. Perhaps a file handle is left open somewhere.

Follow-up articles

Turn your Raspberry Pi into a live HDTV transmitter

  • Gábor Benitsch

    Hi guys,

    I have an UT-100 DVB-T dongle and I would like to create a DVB-T „transmodulator” with this product. I connected the UT-100 to RPi3. If I use the original testkit separately the receive and the modulation is working fine.
    I thought I create a fifo called DVB.ts and in the RX testkit I save the received stream to the fifo. After this I create a second fifo, called dvbsend.ts and I’m redirecting the stream to this. Then I use the tsrfsend to send the data stream, but some problems appeared.

    The whole command list:
    mkfifo DVB.ts &
    mkfifo dvbsend.ts &
    tsstamp 22394048 DVB.ts > dvbsend.ts &
    I opened RX testkit program and locked channel, then saved stream to the DVB.ts.

    In other terminal which opened in tx testkit folder:
    ln -s /…./dvbsend.ts dvbsending.ts &
    I opened the TX testkit program, I set the modulation parameters and I send the file called dvbsending.ts

    Immediately errors are appeared in both sides.
    In the receiver’s side I got this error:
    desync (43, 44, 1e, fe) – 188
    desync (9f, 36, 4d, 61) – 188
    [11]+ broken data channel tsstamp DVB.ts 22394000 > dvbsend.ts

    In the modulator’s side I got this error:
    segmentation error

    I tried another way with a professional dvb-t receiver. The receiver send the received data to the Raspberry Pi via UDP. In the Raspberry Pi I use tsudpreceive, tsstamp and tsrfsend programs.
    The command list:
    mkfifo dvbrec.ts &
    mkfifo dvbsend.ts &
    tsstamp dvbrec.ts 22394048 > dvbsend.ts &
    tsudpreceive 58001 > dvbrec.ts &
    tsrfsend dvbsend.ts 0 666000 8000 64 ¾ ¼ 8 0 0

    This is running without error, but in the receiver’s side I get „desync” error.

    What do you mean, where is the problem?

    Sorry for my bad english.