Wallpaper / desktop background + other stuff on Linux Mint 18.1 / Cinnamon

Desktop wallpaper setting

Get the current one:

$ gsettings get org.cinnamon.desktop.background picture-uri
'file:///usr/share/backgrounds/linuxmint/default_background.jpg'

And set it to another:

$ gsettings set org.cinnamon.desktop.background picture-uri 'file:///usr/share/backgrounds/linuxmint/edesigner_linuxmint.png'

Notes:

  • The “file://” prefix is mandatory.
  • There also an org.gnome.desktop.background attribute. Apparently, org.cinnamon.desktop.background overrides the former.
  • For an effect on the screen, the “set” command must be run on the active console (i.e. it doesn’t work from an remote ssh session)
  • If the URI property is faulty, the actual desktop background reverts to the default, but the faulty value is shown as is with the “get” command. This is somewhat confusing. In particular, omitting the file:// prefix makes a faulty value.

A bit more with gsettings

List all keys and values related to the desktop background:

$ gsettings list-recursively org.cinnamon.desktop.background
org.cinnamon.desktop.background picture-uri 'file:///usr/share/backgrounds/linuxmint/edesigner_linuxmint.png'
org.cinnamon.desktop.background color-shading-type 'solid'
org.cinnamon.desktop.background primary-color '#000000'
org.cinnamon.desktop.background picture-options 'zoom'
org.cinnamon.desktop.background picture-opacity 100
org.cinnamon.desktop.background secondary-color '#000000'

Or org.cinnamon, for that matter

$ gsettings list-recursively org.cinnamon

And there’s also “reset” for resetting a value to its default, and “monitor”, which prints a line each time the value of a key is changing.

The “org.cinnamon.desktop.background” strings is called a “schema”. These can be listed with:

$ gsettings list-schemas

Or the list of relocatable schemas (don’t ask me what “relocatable” means):

$ gsettings list-relocatable-schemas

These schemas can be found in /usr/share/glib-2.0/schemas/. For example, the schema for the desktop background properties can be found as /usr/share/glib-2.0/schemas/org.cinnamon.desktop.background.gschema.xml.

However  the XML files are not in effect directly. Rather, it’s the compiled file, /usr/share/glib-2.0/schemas/gschemas, generated with glib-compile-schemas.

dconf

gsetting is dconf-based, and accesses ~/.config/dconf/user binary database for obtaining non-default values. To dump all values in this database, install the dconf command-line tool:

$ sudo apt-get install dconf-cli

and then

$ dconf dump /

Or shall I be more specific?

$ dconf dump /org/cinnamon/desktop/background/
[/]
picture-uri='file:///usr/share/backgrounds/linuxmint/default_background.jpg'

Note that running “gsettings reset” on a key removes it from the dconf database:

$ gsettings reset org.cinnamon.desktop.background picture-uri
$ dconf dump /org/cinnamon/desktop/background/
$

(no output)

Messing up with other Window Manager

One way to completely mess up is running /etc/X11/Xsession through an ssh -X session with another computer. This will cause an attempt to start a full desktop session on the ssh client’s  X server, where an existing desktop already exists. A whole lot of attributes will be changed, for example the wallpaper, font settings and the windows’ title bars become rock-bottom basic and ugly. Apparently, these settings are made directly on the X server, so restarting Cinnamon doesn’t help. It’s the X server that needs restarting.

So the good news is that a messup of this sort doesn’t affect the permanent setting. A simple reboot fixes this. The bad news are, of course, that a reboot is necessary. Or maybe restarting the X server will be enough. Didn’t check this option.

Why I would run /etc/X11/Xsession is a different story. If I do, it’s best not to forget the DISPLAY= assignment…

Linux / DVB: Playing with command-line utilities

General

Yet another collection of jots as I try out stuff. In this post, I’m playing with a Sin Hon DVB dongle, trying but failing to receive terrestrial TV with it. The OS is Linux Mint 18.1. I had also Kodi and Tvheadend installed on the system, but they aren’t discussed here.

There’s no coherent say here. The dongle I used  was mostly likely defective, and I got myself another model, that worked better. This post repeats some of the stages below, with the new dongle.

Install

# apt-get install dvb-tools dtv-scan-tables
# apt-get install w-scan

Note so self: Turn off tvheadend service before trying command-line utilities, as the former holds the resources, quite naturally.

Immediately after plugging in the DVB stick

Getting some general info:

$ dvb-fe-tool
Device Silicon Labs Si2168 (/dev/dvb/adapter0/frontend0) capabilities:
     CAN_2G_MODULATION
     CAN_FEC_1_2
     CAN_FEC_2_3
     CAN_FEC_3_4
     CAN_FEC_5_6
     CAN_FEC_7_8
     CAN_FEC_AUTO
     CAN_GUARD_INTERVAL_AUTO
     CAN_HIERARCHY_AUTO
     CAN_INVERSION_AUTO
     CAN_MULTISTREAM
     CAN_MUTE_TS
     CAN_QAM_16
     CAN_QAM_32
     CAN_QAM_64
     CAN_QAM_128
     CAN_QAM_256
     CAN_QAM_AUTO
     CAN_QPSK
     CAN_TRANSMISSION_MODE_AUTO
DVB API Version 5.10, Current v5 delivery system: DVBT
Supported delivery systems:
    [DVBT]
     DVBT2
     DVBC/ANNEX_A

What’s the status?

$ dvb-fe-tool -g
FREQUENCY = 0
MODULATION = QAM/AUTO
BANDWIDTH_HZ = 0
INVERSION = OFF
CODE_RATE_HP = AUTO
CODE_RATE_LP = AUTO
GUARD_INTERVAL = AUTO
TRANSMISSION_MODE = AUTO
HIERARCHY = AUTO
DELIVERY_SYSTEM = DVBT

Weird fact: dvb-fe-tool shows status output when executed immediately after tvheadend has set up the DVB stick, but not after dvbv5-scan

$ dvb-fe-tool -m
ERROR    FE_READ_STATUS: Resource temporarily unavailable
ERROR    FE_READ_STATUS: Resource temporarily unavailable
ERROR    FE_READ_STATUS: Resource temporarily unavailable

Scanning for channels

$ dvbv5-scan /usr/share/dvb/dvb-t/il-All
Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet).
Scanning frequency #1 514000000
       (0x00) Signal= -89.00dBm
Scanning frequency #2 538000000
Lock   (0x1f) Signal= -89.00dBm C/N= 18.75dB UCB= 0 postBER= 1.00
Service Ch 1, provider Idan +: digital television
Service Ch 2, provider Idan +: digital television
Service Ch 10, provider Idan +: digital television
Service Ch 33, provider Idan +: digital television
Service Ch 99, provider Idan +: digital television
Service Ch 23, provider Idan +: digital television
Service Idan+test_2, provider Idan+: digital television
WARNING  Channel Idan+test_2 (service ID 7) not found on PMT. Skipping it.
Service Aleph, provider Idan +: digital radio
Service Bet, provider Idan +: digital radio
Service Gimmel, provider Idan +: digital radio
Service Dalet, provider Idan +: digital radio
Service Moreshet, provider Idan +: digital radio
Service 88FM, provider Idan +: digital radio
Service Musica, provider Idan +: digital radio
Service Reka, provider Idan +: digital radio
Service Galatz, provider Idan +: digital radio
Service Galgalatz, provider Idan +: digital radio
Service Radios, provider Idan +: digital radio
Service Kol Barama, provider Idan +: digital radio
Service Lev HaMdina, provider Idan +: digital radio
Service CLASSICAL bu, provider Idan +: digital radio

A dvb_channel.conf file was created, listed at the end of this post.

Don’t get too encouraged by the channel list: It’s detected even if the signal is extremely poor. Or if something is horribly wrong. Don’t know. I never managed to get this working.

Pay more attention to the postBER=1 (or if it says something like UCB= 2686 postBER= 625x10^-3). Even more discouraging is the fact that the signal levels are the same where it locked and where it didn’t. In other words, almost all signal that arrives to the tuner is noise.

After scanning, the frequency is set, but it’s not tuned in yet:

$ dvb-fe-tool -g
FREQUENCY = 538000000
MODULATION = QAM/16
BANDWIDTH_HZ = 8000000
INVERSION = OFF
CODE_RATE_HP = 2/3
CODE_RATE_LP = AUTO
GUARD_INTERVAL = 1/4
TRANSMISSION_MODE = 8K
HIERARCHY = NONE
DELIVERY_SYSTEM = DVBT
$ dvb-fe-tool -m
ERROR    FE_READ_STATUS: Resource temporarily unavailable
ERROR    FE_READ_STATUS: Resource temporarily unavailable

The regional configuration file, /usr/share/dvb/dvb-t/il-All, is part of the dtv-scan-tables:

$ cat /usr/share/dvb/dvb-t/il-All 
# Israel, Israel Broadcasting Authority's transmitters
# Generated from list in http://www.iba.org.il/reception/
[CHANNEL]
	DELIVERY_SYSTEM = DVBT
	FREQUENCY = 514000000
	BANDWIDTH_HZ = 8000000
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = NONE
	MODULATION = QAM/16
	TRANSMISSION_MODE = 8K
	GUARD_INTERVAL = 1/4
	HIERARCHY = NONE
	INVERSION = AUTO

[CHANNEL]
	DELIVERY_SYSTEM = DVBT
	FREQUENCY = 538000000
	BANDWIDTH_HZ = 8000000
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = NONE
	MODULATION = QAM/16
	TRANSMISSION_MODE = 8K
	GUARD_INTERVAL = 1/4
	HIERARCHY = NONE
	INVERSION = AUTO

This file represents the two frequencies at which DVB-T is broadcast in Israel (same stream, different frequencies in different regions of Israel).

Watching TV

One day, when I find a proper dongle, this will work. For now, I get this:

$ dvbv5-zap -c dvb_channel.conf -r 'Ch 10'
using demux '/dev/dvb/adapter0/demux0'
reading channels from file 'dvb_channel.conf'
service has pid type 06:  2642 2641 2640
tuning to 538000000 Hz
video pid 2625
  dvb_set_pesfilter 2625
audio pid 2626
  dvb_set_pesfilter 2626
       (0x00)
Lock   (0x1f) C/N= 25.25dB UCB= 0 postBER= 1.00
Lock   (0x1f) C/N= 25.25dB UCB= 0 postBER= 1.00
DVR interface '/dev/dvb/adapter0/dvr0' can now be opened
Lock   (0x1f) C/N= 25.25dB UCB= 0 postBER= 1.00

Some explanations:

  • The ‘Ch 10′ string is the identifier found in dvb_channel.conf for Israeli Channel 10 (see full listing at the end of this post)
  • The (0x00) part says that the demodulator isn’t locked (odds are that the firmware was loaded as a result of running dvbv5-zap, so it took a short while)
  • The (0x1f) part says that all demodulator locks were obtained, and the “Lock” before says it.
  • The PostBER = 1.00 clearly indicates I have a problem, and is there reason I can’t watch anything. And by the way, BER can never exceed 0.5, because if you get more than half the bits wrong, read the NOT of all bits, and the BER will go down. So BER=1 actually means no errors. But not being a schmuck about it, it’s clear that the demodulator wants to say something’s not good.
  • UCB = 0, number of uncorrected data transport blocks so far. Zero isn’t really encouraging, as it’s most likely a result of no data blocks detected at all.

To actually see the channel, go e.g.

$ mplayer -cache 800 /dev/dvb/adapter0/dvr0

Need I say that I got nothing? Mplayer ran nicely, tried to fish some info, but never got as far as opening an image window.

By the way, the BER info capability of the si2168 chip I used was due to a feature that is due for addition in kernel 4.11 (I patched mine manually). So without that, it looks like this:

$ dvbv5-zap -c dvb_channel.conf -r 'Ch 10'
using demux '/dev/dvb/adapter0/demux0'
reading channels from file 'dvb_channel.conf'
service has pid type 06:  2642 2641 2640
tuning to 538000000 Hz
video pid 2625
  dvb_set_pesfilter 2625
audio pid 2626
  dvb_set_pesfilter 2626
       (0x00)
Lock   (0x1f) C/N= 25.50dB
Lock   (0x1f) C/N= 25.50dB
DVR interface '/dev/dvb/adapter0/dvr0' can now be opened
Lock   (0x1f) C/N= 25.50dB

Using w_scan

This is what I got in Haifa with my Sin Hon TDH601 (“HD809″). Note that I didn’t offer any hints on my location, but it managed anyhow.

$ w_scan
w_scan
w_scan version 20141122 (compiled for DVB API 5.10)
WARNING: could not guess your country. Falling back to 'DE'
guessing country 'DE', use -c <country> to override
using settings for GERMANY
DVB aerial
DVB-T Europe
scan type TERRESTRIAL, channellist 4
output format vdr-2.0
WARNING: could not guess your codepage. Falling back to 'UTF-8'
output charset 'UTF-8', use -C <charset> to override
Info: using DVB adapter auto detection.
	/dev/dvb/adapter0/frontend0 -> TERRESTRIAL "Silicon Labs Si2168": very good :-))

Using TERRESTRIAL frontend (adapter /dev/dvb/adapter0/frontend0)
-_-_-_-_ Getting frontend capabilities-_-_-_-_
Using DVB API 5.10
frontend 'Silicon Labs Si2168' supports
DVB-T2
INVERSION_AUTO
QAM_AUTO
TRANSMISSION_MODE_AUTO
GUARD_INTERVAL_AUTO
HIERARCHY_AUTO
FEC_AUTO
FREQ (42.00MHz ... 870.00MHz)
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
Scanning DVB-T...
Scanning 7MHz frequencies...
177500: (time: 00:01.719)
184500: (time: 00:03.747)
191500: (time: 00:05.803)
198500: (time: 00:07.811)
205500: (time: 00:09.819)
212500: (time: 00:11.827)
219500: (time: 00:13.831)
226500: (time: 00:15.835)
Scanning 8MHz frequencies...
474000: (time: 00:17.843)
482000: (time: 00:19.847)
490000: (time: 00:21.855)
498000: (time: 00:23.907)
506000: (time: 00:25.911)
514000: (time: 00:27.959)
522000: (time: 00:29.967)
530000: (time: 00:31.970)
538000: (time: 00:34.022)         signal ok:	QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (0:0:0)
        QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (0:0:0) : updating transport_stream_id: -> (0:0:2)
        QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (0:0:2) : updating network_id -> (0:4369:2)
        new transponder: (QPSK     f =      0 kHz I0B999C0D0T2G32Y0 (65314:4369:1)) 0x4000
        QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (0:4369:2) : updating original_network_id -> (65314:4369:2)
        updating transponder:
           (QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (65314:4369:2)) 0x0000
        to (QAM_16   f = 538000 kHz I999B8C23D0T8G4Y0 (65314:4369:2)) 0x405A
        new transponder: (QAM_16   f =      0 kHz I999B8C23D0T8G4Y0 (8959:4369:3)) 0x405A
546000: (time: 00:35.198)
554000: (time: 00:37.250)
562000: (time: 00:39.254)
570000: (time: 00:41.306)
578000: (time: 00:43.358)
586000: (time: 00:45.414)
594000: (time: 00:47.462)
602000: (time: 00:49.514)
610000: (time: 00:51.522)
618000: (time: 00:53.574)
626000: (time: 00:55.578)
634000: (time: 00:57.586)
642000: (time: 00:59.638)
650000: (time: 01:01.641)
658000: (time: 01:03.697)
666000: (time: 01:05.701)
674000: (time: 01:07.705)
682000: (time: 01:09.753)
690000: (time: 01:11.801)
698000: (time: 01:13.857)
706000: (time: 01:15.909)
714000: (time: 01:17.913)
722000: (time: 01:19.917)
730000: (time: 01:21.969)
738000: (time: 01:24.025)
746000: (time: 01:26.073)
754000: (time: 01:28.081)
762000: (time: 01:30.085)
770000: (time: 01:32.092)
778000: (time: 01:34.096)
786000: (time: 01:36.104)
794000: (time: 01:38.108)
802000: (time: 01:40.112)
810000: (time: 01:42.164)
818000: (time: 01:44.216)
826000: (time: 01:46.220)
834000: (time: 01:48.276)
842000: (time: 01:50.328)
850000: (time: 01:52.332)
858000: (time: 01:54.384)
Scanning DVB-T2...
Scanning 7MHz frequencies...
177500: (time: 01:56.388)
184500: (time: 01:58.396)
191500: (time: 02:00.400)
198500: (time: 02:02.403)
205500: (time: 02:04.407)
212500: (time: 02:06.455)
219500: (time: 02:08.511)
226500: (time: 02:10.519)
Scanning 8MHz frequencies...
474000: (time: 02:12.571)
482000: (time: 02:14.579)
490000: (time: 02:16.583)
498000: (time: 02:18.587)
506000: (time: 02:20.591)
514000: (time: 02:22.643)
522000: (time: 02:24.695)
530000: (time: 02:26.699)
538000: skipped (already known transponder)
546000: (time: 02:28.751)
554000: (time: 02:30.755)
562000: (time: 02:32.762)
570000: (time: 02:34.766)
578000: (time: 02:36.774)
586000: (time: 02:38.778)
594000: (time: 02:40.782)
602000: (time: 02:42.786)
610000: (time: 02:44.790)
618000: (time: 02:46.842)
626000: (time: 02:48.846)
634000: (time: 02:50.850)
642000: (time: 02:52.858)
650000: (time: 02:54.862)
658000: (time: 02:56.866)
666000: (time: 02:58.874)
674000: (time: 03:00.878)
682000: (time: 03:02.881)
690000: (time: 03:04.889)
698000: (time: 03:06.893)
706000: (time: 03:08.897)
714000: (time: 03:10.901)
722000: (time: 03:12.909)
730000: (time: 03:14.917)
738000: (time: 03:16.921)
746000: (time: 03:18.929)
754000: (time: 03:20.933)
762000: (time: 03:22.937)
770000: (time: 03:24.941)
778000: (time: 03:26.945)
786000: (time: 03:28.949)
794000: (time: 03:30.957)
802000: (time: 03:32.961)
810000: (time: 03:34.964)
818000: (time: 03:36.968)
826000: (time: 03:38.976)
834000: (time: 03:41.028)
842000: (time: 03:43.080)
850000: (time: 03:45.132)
858000: (time: 03:47.184)
tune to: QAM_16   f = 538000 kHz I999B8C23D0T8G4Y0 (65314:4369:2) (time: 03:49.188)
	service = Ch 1 (Idan +)
	service = Ch 2 (Idan +)
	service = Ch 10 (Idan +)
	service = Ch 33 (Idan +)
	service = Ch 99 (Idan +)
	service = Ch 23 (Idan +)
	service = Idan+test_2 (Idan+)
	service = Aleph (Idan +)
	service = Bet (Idan +)
	service = Gimmel (Idan +)
	service = Dalet (Idan +)
	service = Moreshet (Idan +)
	service = 88FM (Idan +)
	service = Musica (Idan +)
	service = Reka (Idan +)
	service = Galatz (Idan +)
	service = Galgalatz (Idan +)
	service = Radios (Idan +)
	service = Kol Barama (Idan +)
	service = Lev HaMdina (Idan +)
	service = CLASSICAL bu (Idan +)
retrying with center_frequency = 514000000
tune to: QAM_16   f = 514000 kHz I999B8C23D0T8G4Y0 (8959:4369:3) (time: 04:02.968)
----------no signal----------
tune to: QAM_AUTO f = 514000 kHz I999B8C999D0T999G999Y0 (8959:4369:3) (time: 04:08.995)  (no signal)
----------no signal----------
(time: 04:15.019) dumping lists (20 services)
..
Ch 1;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2561=27:2562@17:0;1025:0:1:65314:2:0
Ch 2;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2593=27:2594@17,2595:0;2608,2609,2610:0:2:65314:2:0
Ch 10;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2625=27:2626@17,2627:0;2640,2641,2642:0:3:65314:2:0
Ch 33;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2657=27:2658@17:0:0:4:65314:2:0
Ch 99;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2689=27:2690@17:0;2704:0:5:65314:2:0
Ch 23;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:3585=27:3586@17:0:0:6:65314:2:0
Aleph;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2817@17:0:0:21:65314:2:0
Bet;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2833@17:0:0:22:65314:2:0
Gimmel;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2849@17:0:0:23:65314:2:0
Dalet;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2865@17:0:0:24:65314:2:0
Moreshet;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2881@17:0:0:25:65314:2:0
88FM;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2897@17:0:0:26:65314:2:0
Musica;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2913@17:0:0:27:65314:2:0
Reka;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2929@17:0:0:28:65314:2:0
Galatz;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2945@17:0:0:29:65314:2:0
Galgalatz;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2961@17:0:0:30:65314:2:0
Radios;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:3057@17:0:0:36:65314:2:0
Kol Barama;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:3137@17:0:0:41:65314:2:0
Lev HaMdina;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:3153@17:0:0:42:65314:2:0
CLASSICAL bu;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:3201@17:0:0:45:65314:2:0
Done, scan time: 04:15.019

The dvb_channel.conf file

As promised above, this is the dvb_channel.conf that was obtained with dvbv5-scan:

[Ch 1]
	SERVICE_ID = 1
	VIDEO_PID = 2561
	AUDIO_PID = 2562
	PID_06 = 1025
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 2]
	SERVICE_ID = 2
	VIDEO_PID = 2593
	AUDIO_PID = 2594 2595
	PID_06 = 2610 2609 2608
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 10]
	SERVICE_ID = 3
	VIDEO_PID = 2625
	AUDIO_PID = 2626 2627
	PID_06 = 2642 2641 2640
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 33]
	SERVICE_ID = 4
	VIDEO_PID = 2657
	AUDIO_PID = 2658
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 99]
	SERVICE_ID = 5
	VIDEO_PID = 2689
	AUDIO_PID = 2690
	PID_06 = 2704
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 23]
	SERVICE_ID = 6
	VIDEO_PID = 3585
	AUDIO_PID = 3586
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Aleph]
	SERVICE_ID = 21
	AUDIO_PID = 2817
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Bet]
	SERVICE_ID = 22
	AUDIO_PID = 2833
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Gimmel]
	SERVICE_ID = 23
	AUDIO_PID = 2849
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Dalet]
	SERVICE_ID = 24
	AUDIO_PID = 2865
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Moreshet]
	SERVICE_ID = 25
	AUDIO_PID = 2881
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[88FM]
	SERVICE_ID = 26
	AUDIO_PID = 2897
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Musica]
	SERVICE_ID = 27
	AUDIO_PID = 2913
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Reka]
	SERVICE_ID = 28
	AUDIO_PID = 2929
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Galatz]
	SERVICE_ID = 29
	AUDIO_PID = 2945
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Galgalatz]
	SERVICE_ID = 30
	AUDIO_PID = 2961
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Radios]
	SERVICE_ID = 36
	AUDIO_PID = 3057
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Kol Barama]
	SERVICE_ID = 41
	AUDIO_PID = 3137
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Lev HaMdina]
	SERVICE_ID = 42
	AUDIO_PID = 3153
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[CLASSICAL bu]
	SERVICE_ID = 45
	AUDIO_PID = 3201
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

This was obtained on February 8th, 2017. It’s probably going to change over time.

Linux and DVB: Failing with a Sin Hon TDH 601 / HD809 USB dongle

General

These are my jots as I attempted to use an DVB USB dongle to receive digital TV in Haifa, Israel. Spoiler: I never managed to get my dongle working properly. Maybe because it was faulty to begin with, and maybe because I missed something. It seems more like the former.

It says “HD809″ and has Vendor/Product IDs 3344/24a0 (see below). 0x3344 = Leaguer Microelectronics (Shenzhen, China), 24a0 is unknown.

Here’s what it looks like:

Sin Hon TDH601 DVB-T2 dongle

Probably a Sin Hon TDH601. According to the manufacturer, it should run with Android 4.1 with OTG on the USB plug, which according to this page means any kernel after 3.0.31. And my phone should detect the dongle, which it doesn’t. As a matter of fact, looking into Android’s kernel v4.4 (which is pretty much a plain Linux kernel) there is nothing matching the “24a0″ string under drivers/. So no.

A look inside:

Sin Hon TDH601 DVB-T2 dongle under the hood

and

Sin Hon TDH601 DVB-T2 dongle under the hood(click to enlarge)

Can you see the little short-circuit on LME2510C two pins to the upper left? And the two of Si2168′s, at the right? I don’t know if they should be there, but I know I messed up completely trying to separate them.

Back to Linux and drivers: Found the device mentioned, leading to this patch, which outlines the devices: LME2510C USB interface (a.k.a. LM04 or QQBOX, not QBOX, with drivers for Windows), Si2168-B40 demodulator, Si2157-A30 tuner. The Windows driver for non-C LME2510 appears to be the same one.

Apparently, LME2510C is a USB front-end for a tuner and a demodulator, each controller by I2C. Calling the driver by the front end surely causes some confusion. It may be useful to know, that the same pair of tuner and demodulator is used in the PCTV tripleStick (292e), so except for the LME2510C USB front end, all that applies to the 292e probably goes for the Sin Hon dongle.

Antti Palosaari’s Linux repo obtained with

$ git clone git://git.linuxtv.org/anttip/media_tree.git/

where the lme2510c_tdh601branch contains the commit from June 2016, adding the drivers/media/usb/dvb-usb-v2/lme2510.c file (not to be confused with rc-lme2510.c, which contains key maps for a remote control it seems). It requires dvb-usb-lme2510c-0.fw as a firmware file.

Not to be confused with drivers/media/usb/dvb-usb-v2/lmedm04.c, which relates to the same USB interface, but with different devices behind it.

Found 0x3344/0x1122 supported in the 3.12 kernel of Zedboard (LME’s remote control?)

Incorporation in Linux Mint 18.1

Grabbed the Linux Kernel git:

$ git clone git://kernel.ubuntu.com/ubuntu/ubuntu-xenial.git

and checked out the Ubuntu-4.4.0-53.74 tag

Copied configuration file:

$ cp /boot/config-4.4.0-53-generic .config

And on the machine itself:

$ sudo apt-get install libssl-dev
$ make modules_prepare

libssl-dev is required for one of the kernel scripts (sign-file). And running this on my own computer failed with

  CC      kernel/bounds.s
gcc: unrecognized option '-no-pie'
cc1: error: unrecognized command line option "-fstack-protector-strong"
make[1]: *** [kernel/bounds.s] Error 1
make: *** [prepare0] Error 2

(so much for a vintage distribution and compiler)

Tried to compile the directory in question:

$ make M=drivers/media/usb/dvb-usb-v2

That went through nice, however there was a complaint about missing Module.symvers, and hence the module didn’t get into the kernel with insmod.

So after patching the kernel with commit f92f72c1138e33e3a2976724e8b4bc6775b53ee8 from Antti Palosaari’s repo (creating a text patch and applying it with git am on Ubuntu’s kernel) I compiled the kernel and modules completely on the target machine

$ make -j 6 bzImage modules

And that took some time, of course. It seems like this is the only way to obtain Module.symvers.

Eventually, I went down the entire way from the lme2510c_tdh601branch in the media-tree git repo to some common point with the kernel I used (4.4.0-53-generic) and cherry-picked whatever was in the middle. This required some manual adjustments. In particular, this enabled the UCB and BER statistics collection.

Finally, the module was put in place:

# cp drivers/media/usb/dvb-usb-v2/lme2510c.ko /lib/modules/4.4.0-53-generic/kernel/drivers/media/usb/dvb-usb-v2/
# depmod -a

and plugging in the dongle was enough:

[12200.242253] usb 1-2: new high-speed USB device number 6 using xhci_hcd
[12200.371223] usb 1-2: config 1 interface 0 altsetting 1 bulk endpoint 0x81 has invalid maxpacket 64
[12200.371235] usb 1-2: config 1 interface 0 altsetting 1 bulk endpoint 0x1 has invalid maxpacket 64
[12200.371241] usb 1-2: config 1 interface 0 altsetting 1 bulk endpoint 0x2 has invalid maxpacket 64
[12200.371248] usb 1-2: config 1 interface 0 altsetting 1 bulk endpoint 0x8A has invalid maxpacket 64
[12200.371681] usb 1-2: New USB device found, idVendor=3344, idProduct=24a0
[12200.371691] usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=3
[12200.371697] usb 1-2: SerialNumber: 䥈児
[12201.486687] usb 1-2: dvb_usb_v2: found a 'Sin Hon TDH601' in cold state
[12201.489636] usb 1-2: dvb_usb_v2: downloading firmware from file 'dvb-usb-lme2510c-0.fw'
[12201.516925] usbcore: registered new interface driver lme2510c
[12201.549778] usb 1-2: USB disconnect, device number 6
[12201.549992] usb 1-2: dvb_usb_v2: 'Sin Hon TDH601' successfully deinitialized and disconnected
[12201.826659] usb 1-2: new high-speed USB device number 7 using xhci_hcd
[12201.955630] usb 1-2: New USB device found, idVendor=3344, idProduct=24a0
[12201.955642] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[12201.955648] usb 1-2: Product: 䝇䝇
[12201.955656] usb 1-2: Manufacturer: Leaguerme
[12201.955661] usb 1-2: SerialNumber: LMEUSBSN0001
[12201.957020] usb 1-2: dvb_usb_v2: found a 'Sin Hon TDH601' in warm state
[12201.957302] usb 1-2: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer
[12201.957324] DVB: registering new adapter (Sin Hon TDH601)
[12201.972436] i2c i2c-9: Added multiplexed i2c bus 10
[12201.972444] si2168 9-0064: Silicon Labs Si2168 successfully attached
[12201.979987] si2157 10-0060: Silicon Labs Si2147/2148/2157/2158 successfully attached
[12201.980015] usb 1-2: DVB: registering adapter 0 frontend 0 (Silicon Labs Si2168)...
[12201.980442] usb 1-2: dvb_usb_v2: 'Sin Hon TDH601' successfully initialized and connected

with lsmod’s relevant part going

Module                  Size  Used by
si2157                 16384  1
si2168                 20480  1
i2c_mux                16384  1 si2168
lme2510c               16384  0
dvb_usb_v2             36864  1 lme2510c
dvb_core              122880  1 dvb_usb_v2
rc_core                28672  1 dvb_usb_v2

The relevant device files reside in /dev/dvb/adapter0. I made them R/W accessible to all manually to begin with.

And then, when attempting to scan, I got the following in dmesg:

[13200.818391] si2168 9-0064: found a 'Silicon Labs Si2168-B40'
[13200.818461] si2168 9-0064: Direct firmware load for dvb-demod-si2168-b40-01.fw failed with error -2
[13200.818493] si2168 9-0064: Direct firmware load for dvb-demod-si2168-02.fw failed with error -2
[13200.818499] si2168 9-0064: firmware file 'dvb-demod-si2168-02.fw' not found
[13200.823201] si2157 10-0060: found a 'Silicon Labs Si2157-A30'
[13200.873313] si2157 10-0060: firmware version: 3.0.5

So I grabbed the two files from the dvb-firmware Github repo.

The firmware for the driver itself (dvb-usb-lme2510c-0.fw) was downloaded from Palosaari’s site.

Firmware for the si2168 (dvb-demod-si2168-b40-01.fw) was downloaded from here (version 4.0.25). Doesn’t seem like there’s a major difference between the revisions (in the sense that none worked for me. I tried several).

dvb-demod-si2168-02.fw is the fallback firmware for all si2168 demodulators. There’s no point using it when a specific firmware file is available.

The si2157 tuner doesn’t require any firmware file.

All firmware files were copied to /lib/firmware on the target machine.

Missing firmware symptoms

When both dvb-demod-si2168-02.fw and dvb-demod-si2168-b40-01.fw are missing or have not been loaded properly:

[ 1089.192756] si2168 9-0064: Direct firmware load for dvb-demod-si2168-b40-01.fw failed with error -2
[ 1089.193730] si2168 9-0064: please install firmware file 'dvb-demod-si2168-b40-01.fw'
[ 1089.193753] si2168 9-0064: downloading firmware from file 'dvb-demod-si2168-02.fw'
[ 1089.509845] si2168 9-0064: firmware version: B 4.0.4

And this results with something like this:

$ dvbv5-scan /usr/share/dvb/dvb-t/il-All
Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet).
Scanning frequency #1 514000000
       (0x00) Signal= 0.00dBm
Scanning frequency #2 538000000
       (0x00) Signal= 0.00dBm

But with dvb-demod-si2168-02.fw loaded (and dvb-demod-si2168-b40-01.fw not present):

$ dvbv5-scan /usr/share/dvb/dvb-t/il-All
Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet).
Scanning frequency #1 514000000
       (0x00) Signal= -85.00dBm
Scanning frequency #2 538000000
Lock   (0x1f) Signal= -85.00dBm C/N= 20.25dB UCB= 0 postBER= 1.00
Service Ch 1, provider Idan +: digital television
Service Ch 2, provider Idan +: digital television
[... etc ...]

The important lesson is that channels are detected without dvb-demod-si2168-b40-01.fw, only no data can be obtained (the BER is horribly high). Explained why above.

Final status

I destroyed the hardware completely when trying to fix what seemed to be a short circuit between two pins of the LME2510C chip. Unfortunately, I messed things up (fine-pitch soldering is a skill, too bad I don’t possess it), and the device isn’t detected on the USB bus properly. Or more precisely, one gets

[12135.429658] usb 1-4: new full-speed USB device number 13 using xhci_hcd
[12135.541697] usb 1-4: device descriptor read/64, error -71
[12135.757589] usb 1-4: device descriptor read/64, error -71
[12135.973634] usb 1-4: new full-speed USB device number 14 using xhci_hcd
[12136.085569] usb 1-4: device descriptor read/64, error -71
[12136.301560] usb 1-4: device descriptor read/64, error -71
[12136.517668] usb 1-4: new full-speed USB device number 15 using xhci_hcd
[12136.517909] usb 1-4: Device not responding to setup address.
[12136.721700] usb 1-4: Device not responding to setup address.
[12136.925512] usb 1-4: device not accepting address 15, error -71
[12137.037492] usb 1-4: new full-speed USB device number 16 using xhci_hcd
[12137.037709] usb 1-4: Device not responding to setup address.
[12137.241728] usb 1-4: Device not responding to setup address.
[12137.445494] usb 1-4: device not accepting address 16, error -71
[12137.445653] usb usb1-port4: unable to enumerate USB device

Raw session

A proper plug-in syslog (device is OK, and drivers and firmware in place):

[ 1175.580411] usb 1-4: new high-speed USB device number 7 using xhci_hcd
[ 1175.708790] usb 1-4: config 1 interface 0 altsetting 1 bulk endpoint 0x81 has invalid maxpacket 64
[ 1175.708803] usb 1-4: config 1 interface 0 altsetting 1 bulk endpoint 0x1 has invalid maxpacket 64
[ 1175.708810] usb 1-4: config 1 interface 0 altsetting 1 bulk endpoint 0x2 has invalid maxpacket 64
[ 1175.708817] usb 1-4: config 1 interface 0 altsetting 1 bulk endpoint 0x8A has invalid maxpacket 64
[ 1175.709033] usb 1-4: New USB device found, idVendor=3344, idProduct=24a0
[ 1175.709041] usb 1-4: New USB device strings: Mfr=0, Product=0, SerialNumber=3
[ 1175.709048] usb 1-4: SerialNumber: 䥈児
[ 1175.711681] usb 1-4: dvb_usb_v2: found a 'Sin Hon TDH601' in cold state
[ 1175.711789] usb 1-4: dvb_usb_v2: downloading firmware from file 'dvb-usb-lme2510c-0.fw'
[ 1175.775782] usb 1-4: USB disconnect, device number 7
[ 1175.775955] usb 1-4: dvb_usb_v2: 'Sin Hon TDH601' successfully deinitialized and disconnected
[ 1176.052434] usb 1-4: new high-speed USB device number 8 using xhci_hcd
[ 1176.181496] usb 1-4: New USB device found, idVendor=3344, idProduct=24a0
[ 1176.181510] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1176.181519] usb 1-4: Product: 䝇䝇
[ 1176.181527] usb 1-4: Manufacturer: Leaguerme
[ 1176.181534] usb 1-4: SerialNumber: LMEUSBSN0001
[ 1176.183341] usb 1-4: dvb_usb_v2: found a 'Sin Hon TDH601' in warm state
[ 1176.183804] usb 1-4: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer
[ 1176.183833] DVB: registering new adapter (Sin Hon TDH601)
[ 1176.192171] i2c i2c-9: Added multiplexed i2c bus 10
[ 1176.192182] si2168 9-0064: Silicon Labs Si2168-B40 successfully identified
[ 1176.192188] si2168 9-0064: firmware version: B 4.0.2
[ 1176.197203] si2157 10-0060: Silicon Labs Si2147/2148/2157/2158 successfully attached
[ 1176.197228] usb 1-4: DVB: registering adapter 0 frontend 0 (Silicon Labs Si2168)...
[ 1176.197483] usb 1-4: dvb_usb_v2: 'Sin Hon TDH601' successfully initialized and connected

And when running e.g. dvbv5-zap:

[ 1320.568204] si2168 9-0064: downloading firmware from file 'dvb-demod-si2168-b40-01.fw'
[ 1321.527006] si2168 9-0064: firmware version: B 4.0.25
[ 1321.538051] si2157 10-0060: found a 'Silicon Labs Si2157-A30'
[ 1321.588369] si2157 10-0060: firmware version: 3.0.5

And lsusb:

# lsusb -v

Bus 001 Device 003: ID 3344:24a0
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x3344
  idProduct          0x24a0
  bcdDevice            0.00
  iManufacturer           0
  iProduct                0
  iSerial                 3 ???
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           76
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xc0
      Self Powered
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       1
      bNumEndpoints           7
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x86  EP 6 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x87  EP 7 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x03fc  1x 1020 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x0a  EP 10 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x8a  EP 10 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  bNumConfigurations      1
Device Status:     0x0000
  (Bus Powered)

The lsusb was made on another computer, but that shouldn’t matter.

Linux Mint 18.1 + i915: Updating the Intel Graphics stack

Running Linux Mint 18.1 (kernel 4.4.0-53) on a Gigabyte Brix BACE-3160 (with an i915 graphics controller) , I had all kind of minor graphics artifacts (in particular a sluggish mouse pointer and Kodi felt heavy). So obviously, I went for updating the graphics stack.

Intel supplies an tool for doing this automagically on a selected list of distributions. In particular, the Graphics Update Tool 2.0.2 is intended for Ubuntu 16.04. Which is fine, since Mint 18.1 is derived from this distribution exactly.

So I downloaded it, and installed it:

$ sudo dpkg -i intel-graphics-update-tool_2.0.2_amd64.deb

That didn’t work all that nice, because there were missing dependencies. Easily fixed with

$ sudo apt-get -f install

And then launch the tool itself:

$ sudo intel-graphics-update-tool

And this is where the tool refused, because the distribution doesn’t match. So I tricked it by replacing the file it checks (a thanks goes to strace). First, save the real one:

$ sudo mv /etc/lsb-release /etc/lsb-release-mint

and then edit /etc/lsb-release to mimic Ubuntu. That is, saying this:

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04 LTS"

And then run the tool again. Now everything went through fine. And for the record, it really helped with those graphics issues.

By the way, among the things it did was to add an apt-get repository. Namely, adding the file /etc/apt/sources.list.d/intellinuxgraphics.list with the following:

deb https://download.01.org/gfx/ubuntu/16.04/main xenial main #Intel Graphics drivers

For the record, this is /etc/lsb-release for Linux Mint 18.1:

DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=18.1
DISTRIB_CODENAME=serena
DISTRIB_DESCRIPTION="Linux Mint 18.1 Serena"

In case someone needs to fake Linux Mint…

Note that the effective initrd.img file (probably in /boot) must be updated (I’m not 100% about it, but it seems like the update tool did it): Odds are that the kernel modules related to graphics are loaded from the initrd.img, and not /lib/modules, as part of displaying the graphical splash screen (Plymouth) until Gnome is up and running. Unless you’ve disabled it, like myself.

PCIe: Xilinx’ pipe_clock module and its timing constraints

Introduction

In several versions of Xilinx’ wrapper for the integrated PCIe block, it’s the user application logic’s duty to instantiate the module which generates the “pipe clock”. It typically looks something like this:

pcie_myblock_pipe_clock #
      (
          .PCIE_ASYNC_EN                  ( "FALSE" ),                 // PCIe async enable
          .PCIE_TXBUF_EN                  ( "FALSE" ),                 // PCIe TX buffer enable for Gen1/Gen2 only
          .PCIE_LANE                      ( LINK_CAP_MAX_LINK_WIDTH ), // PCIe number of lanes
          // synthesis translate_off
          .PCIE_LINK_SPEED                ( 2 ),
          // synthesis translate_on
          .PCIE_REFCLK_FREQ               ( PCIE_REFCLK_FREQ ),        // PCIe reference clock frequency
          .PCIE_USERCLK1_FREQ             ( PCIE_USERCLK1_FREQ ),      // PCIe user clock 1 frequency
          .PCIE_USERCLK2_FREQ             ( PCIE_USERCLK2_FREQ ),      // PCIe user clock 2 frequency
          .PCIE_DEBUG_MODE                ( 0 )
      )
      pipe_clock_i
      (

          //---------- Input -------------------------------------
          .CLK_CLK                        ( sys_clk ),
          .CLK_TXOUTCLK                   ( pipe_txoutclk_in ),     // Reference clock from lane 0
          .CLK_RXOUTCLK_IN                ( pipe_rxoutclk_in ),
          .CLK_RST_N                      ( pipe_mmcm_rst_n ),      // Allow system reset for error_recovery
          .CLK_PCLK_SEL                   ( pipe_pclk_sel_in ),
          .CLK_PCLK_SEL_SLAVE             ( pipe_pclk_sel_slave),
          .CLK_GEN3                       ( pipe_gen3_in ),

          //---------- Output ------------------------------------
          .CLK_PCLK                       ( pipe_pclk_out),
          .CLK_PCLK_SLAVE                 ( pipe_pclk_out_slave),
          .CLK_RXUSRCLK                   ( pipe_rxusrclk_out),
          .CLK_RXOUTCLK_OUT               ( pipe_rxoutclk_out),
          .CLK_DCLK                       ( pipe_dclk_out),
          .CLK_OOBCLK                     ( pipe_oobclk_out),
          .CLK_USERCLK1                   ( pipe_userclk1_out),
          .CLK_USERCLK2                   ( pipe_userclk2_out),
          .CLK_MMCM_LOCK                  ( pipe_mmcm_lock_out)

      );

Consequently, some timing constraints that are related to the PCIe block’s internal functionality aren’t added automatically by the wrapper’s own constraints, but must be given explicitly by the user of the block, typically by following an example design.

This post discusses the implications of this situation. Obviously, none of this applies to PCIe block wrappers which handle this instantiation internally.

What is the pipe clock?

For our narrow purposes, the PIPE interface is the parallel data part of the SERDES attached to the Gigabit Transceivers (MGTs), which drive the physical PCIe lanes. For example, data to a Gen1 lane, running at 2.5 GT/s, requires 2.0 Gbit/s of payload data (as it’s expanded by a 10/8 ratio with 10b/8b encoding). If the SERDES is fed with 16 bits in parallel, a 125 MHz clock yields the correct data rate (125 MHz * 16 = 2 GHz).

By the same coin, a Gen2 interface requires a 250 MHz clock to support a payload data rate of 4.0 Gbit/s per lane (expanded into 5 GT/s with 10b/8b encoding).

The clock mux

If a PCIe block is configured for Gen2, it’s required to support both rates: 5 GT/s, and also be able to fall back to 2.5 GT/s if the link partner doesn’t support Gen2 or if the link doesn’t work properly at the higher rate.

In the most common setting (or always?), the pipe clock is muxed between two source clocks by this piece of code (in the pipe_clock module):

    //---------- PCLK Mux ----------------------------------
    BUFGCTRL pclk_i1
    (
        //---------- Input ---------------------------------
        .CE0                        (1'd1),
        .CE1                        (1'd1),
        .I0                         (clk_125mhz),
        .I1                         (clk_250mhz),
        .IGNORE0                    (1'd0),
        .IGNORE1                    (1'd0),
        .S0                         (~pclk_sel),
        .S1                         ( pclk_sel),
        //---------- Output --------------------------------
        .O                          (pclk_1)
    );
    end

So pclk_sel, which is a registered version of the CLK_PCLK_SEL input port is used to switch between a 125 MHz clock (pclk_sel == 0) and a 250 MHz clock (clk_sel == 1), both clocks generated from the same MMCM_ADV block in the pipe_clock module.

The BUFGMUX’ output, pclk_1 is assigned as the pipe clock output (CLK_PCLK). It’s also used in other ways, depending on the instantiation parameters of pipe_clock.

Constraints for Gen1 PCIe blocks

If a PCIe block is configured for Gen1 only, there’s no question about the pipe clock’s frequency: It’s 125 MHz. As a matter of fact, if the PCIE_LINK_SPEED instantiation parameter is set to 1, one gets (by virtue of Verilog’s generate commands)

    BUFG pclk_i1
    (
        //---------- Input ---------------------------------
        .I                          (clk_125mhz),
        //---------- Output --------------------------------
        .O                          (clk_125mhz_buf)
    );
    assign pclk_1 = clk_125mhz_buf;

But never mind this — it’s never used: Even when the block is configured as Gen1 only, PCIE_LINK_SPEED is set to 3 in the example design’s instantiation, and we all copy from it.

Instead, the clock mux is used and fed with pclk_sel=0. The constraints reflect this with the following lines appearing in the example design’s XDC file for Gen1 PCIe blocks (only!):

set_case_analysis 1 [get_pins {pcie_myblock_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/S0}]
set_case_analysis 0 [get_pins {pcie_myblock_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/S1}]
set_property DONT_TOUCH true [get_cells -of [get_nets -of [get_pins {pcie_myblock_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/S0}]]]

The first two commands tell the timing analysis tools to assume that the clock mux’ inputs are S0=1 and S1=0, and hence that the mux forwards the 125 MHz clock (connected to I0).

The DONT_TOUCH constraint works around a bug in early Vivado revisions, as explained in AR #62296: The S0 input is assigned ~pclk_sel, which requires a logic inverter. This inverter was optimized into the BUFCTRL primitive by the synthesizer, flipping the meaning of the first set_case_analysis constraints. Which caused the timing tools to analyze the design as if both S0 and S1 were set to zero, hence no clock output, and no constraining of the relevant paths.

The problem with this set of constraints is their cryptic nature: It’s not clear at all why they are there, just by reading the XDC file. If the user of the PCIe block decides, for example, to change from a 8x Gen1 configuration to 4x Gen2, everything will appear to work nicely, since all clocks except the pipe clock remain the same. It takes some initiative and effort to figure out that these constraints are incorrect for a Gen2 block.

To make things even worse, almost all relevant paths will meet the 250 MHz (4 ns) requirement even when constrained for 125 MHz on a sparsely filled FPGA, simply because there’s little logic along these paths. So odds are that everything will work fine during the initial tests (before the useful logic is added to the design), and later on the PCIe interface may become shaky throughout the design process, as some paths accidentally exceed the 4 ns limit.

Dropping the set_case_analysis constraints

As these constraints are relaxing by their nature, what happens if they are dropped? Once could expect that the tools would work a bit harder to ensure that all relevant paths meet timing with either 125 MHz or 250 MHz, or simply put, that the constraining would occur as if pclk_1 was always driven with a 250 MHz clock.

But this isn’t how timing calculations are made. The tools can’t just pick the faster clock from a clock mux and follow through, since the logic driven by the clock might interact with other clock domains. If so, a slower clock might require stricter timing due to different relations between the source and target clock’s frequencies.

So what actually happens is that the timing tools mark all logic driven by the pipe clock as having multiple clocks: The timing of each path going to and from any such logic element is calculated for each of the two clocks. Even the timing for paths going between logic elements that are both driven by the pipe clock are calculated four times, covering the four combinations of the 125 MHz and 250 MHz clocks, as source and destination clocks.

From a practical point of view, this is rather harmless, since both clocks come from the same MMCM_ADV, and are hence aligned. Making these excessive timing calculations always ends up with the equivalent for the 250 MHz clock only (some clock skew uncertainty possibly added for going between the two clocks). Since timing is met easily on these paths, this extra work adds very little to the implementation efforts (and how long it takes to finish).

On the other hand, this adds some dirt to the timing report. First, the multiple clocks are reported (excerpt from the Timing Report):

7. checking multiple_clock
--------------------------
 There are 2598 register/latch pins with multiple clocks. (HIGH)

Later on, the paths between logic driven by the pipe clock are counted as inter clock paths: Once from 125 MHz to 250 MHz, and vice versa. This adds up to a large number of bogus inter clock paths:

------------------------------------------------------------------------------------------------
| Inter Clock Table
| -----------------
------------------------------------------------------------------------------------------------

From Clock    To Clock          WNS(ns)      TNS(ns)  TNS Failing Endpoints  TNS Total Endpoints      WHS(ns)      THS(ns)  THS Failing Endpoints  THS Total Endpoints
----------    --------          -------      -------  ---------------------  -------------------      -------      -------  ---------------------  -------------------
clk_250mhz    clk_125mhz          0.114        0.000                      0                 5781        0.053        0.000                      0                 5781
clk_125mhz    clk_250mhz          0.114        0.000                      0                 5764        0.053        0.000                      0                 5764

Since a single endpoint might produce many paths (e.g. a block RAM), there’s no need for a correlation between the number of endpoints and the number of paths. However the similarity between the figures of the two directions seems to indicate that the vast majority of these paths are bogus.

So dropping the set_case_analysis constraints boils down to some noise in the timing report. I can think of two ways to eliminate it:

  • Issue set_case_analysis constraints setting S0=0, S1=1, so the tools assume a 250 MHz clock. This covers the Gen2 case as well as Gen1.
  • Use the constraints of the example design for a Gen2 block (shown below).

Even though both ways (in particular the second) seem OK to me, I prefer taking the dirt in the timing report and not add constraints without understanding the full implications. Being more restrictive never hurts (as long as the design meets timing).

Constraints for Gen2 PCIe blocks

If a PCIe block is configured for Gen2, it has to be able to work a Gen1 as well. So the set_case_analysis constraints are out of the question.

Instead, this is what one gets in the example design:

create_generated_clock -name clk_125mhz_x0y0 [get_pins pcie_myblock_support_i/pipe_clock_i/mmcm_i/CLKOUT0]
create_generated_clock -name clk_250mhz_x0y0 [get_pins pcie_myblock_support_i/pipe_clock_i/mmcm_i/CLKOUT1]
create_generated_clock -name clk_125mhz_mux_x0y0 \
                        -source [get_pins pcie_myblock_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/I0] \
                        -divide_by 1 \
                        [get_pins pcie_myblock_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/O]
#
create_generated_clock -name clk_250mhz_mux_x0y0 \
                        -source [get_pins pcie_myblock_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/I1] \
                        -divide_by 1 -add -master_clock [get_clocks -of [get_pins pcie_myblock_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/I1]] \
                        [get_pins pcie_myblock_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/O]
#
set_clock_groups -name pcieclkmux -physically_exclusive -group clk_125mhz_mux_x0y0 -group clk_250mhz_mux_x0y0

This may seem tangled, but says something quite simple: The 125 MHz and 250 MHz clocks are physically exclusive (see AR #58961 for an elaboration on this). In other words, these constraints declare that no path exists between logic driven by one clock and logic driven by the other. If such path is found, it’s bogus.

So this drops all the bogus paths mentioned above. Each path between logic driven by the pipe clock is now calculated twice (for 125 MHz and 250 MHz, but not across the clocks). This seems to yield the same practical results as without these constraints, but without complaints about multiple clocks, and of course no inter-clock paths.

Both clocks are still related to the pipe clock however. For example, checking a register driven by the pipe clock yields (Tcl session):

get_clocks -of_objects [get_pins -hier -filter {name=~*/pipe_clock_i/pclk_sel_reg1_reg[0]/C}]
clk_250mhz_mux_x0y0 clk_125mhz_mux_x0y0

Not surprisingly, this register is attached to two clocks. The multiple clock complaint disappeared thanks to the set_clock_groups constraint (even the lower “asynchronous” flag is enough for this purpose).

So can these constraints be used for a Gen1-only block, as a safer alternative for the set_case_analysis constraints? It seems so. Is it a good bargain for getting rid of those extra notes in the timing report? It’s a matter of personal choice. Or knowing for sure.

Bonus: Meaning of some instantiation parameters of pipe_clock

This is the meaning according to dissection of Kintex-7′s pipe_clock Verilog file. It’s probably the same for other targets.

PCIE_REFCLK_FREQ: The frequency of the reference clock

  • 1 => 125 MHz
  • 2 => 250 MHz
  • Otherwise: 100 MHz

CLKFBOUT_MULT_F is set to that the MCMM_ADV’s internal VCO always runs at 1 GHz. Hence the constant CLKOUT0_DIVIDE_F = 8 makes clk_125mhz run at 125 MHz (dividing by 8), and CLKOUT1_DIVIDE = 4 makes clk_250mhz run at 250 MHz (dividing by 8)

PCIE_USERCLK1_FREQ: The frequency of the module’s CLK_USERCLK1 output, which is among others the clock with the user interface (a.k.a. user_clk_out or axi_clk)

  • 1 => 31.25 MHz
  • 2 => 62.5 MHz
  • 3 => 125 MHz
  • 4 => 250 MHz
  • 5 => 500 MHz
  • Otherwise: 62.5 MHz

PCIE_USERCLK2_FREQ: The frequency of the module’s CLK_USERCLK2 output. Not used in most applications. Same frequency mapping as PCIE_USERCLK1_FREQ.

Turning off autosave on WordPress (since it hangs)

After upgrading to WordPress 4.7.2, and thought it would be smashing fun, I found my “Publish” button disabled due to a draft being saved forever. There have been many complaints about this all over the web. I didn’t manage to find a solution to this problem, just a workaround: Disable autosaving altogether.

This is a reasonable measure in my case, since I press the “Update” button frequently enough anyhow. The autosaving is more of an annoyance to me. I tried to think about a single time I used an autosaved revision. My answer was never.

Some have attempted to increase the autosave interval (a.k.a. AUTOSAVE_INTERVAL) to 24 hours or so, but reported that it didn’t help.

And I should mention that I didn’t upgrade the themes or anything else but WordPress itself. Maybe more upgrading (and trouble)?

I went for the solution presented on this page, and it actually works.

Essentially, the idea is to add the following piece of code at the end of the functions.php file of the active theme, just before the closing “?>” of the file.

function disable_autosave() {
    wp_deregister_script('autosave');
}
add_action('wp_print_scripts','disable_autosave');

(in my case, the file was wp-content/themes/cognoblue/functions.php, as I’m using the Cognoblue theme).

That’s it. I cleared my browser’s cache after this change, just to be safe. No more autosave, and no more problems with the Update/Publish button.

Note that this doesn’t disable revisions (which I actually like). And don’t ask me why and how this works. I have no idea.

Making a mirror of a WordPress blog on my own computer

This is a note to self on how to create a mirror copy of this blog on my own computer. My own peculiar methods are all over.

  • Create a virtual host on my apache httpd server (port 99)
  • Uncompress the site’s entire public_html directory into the virtual host site’s root directory (that’slazy, I got a lot of unnecessary files this way)
  • Create a git repo, and add the blog/ directory so I have a look on what happens (not really necessary, but I make git repos everywhere)
  • Create a new database, and fill it with an SQL backup of the site:
    $ mysql -D blogmirror < ~/Desktop/blogdb-Mon_17.01.23-05.23.sql
  • Change the database settings in wp_config.php. For a local database, which requires no password, it became (DB_HOST remained “localhost”):
    define('DB_NAME', 'blogmirror');
    
    /** MySQL database username */
    define('DB_USER', 'eli');
    
    /** MySQL database password */
    define('DB_PASSWORD', '');
  • Change WordPress’ view of the blog’s root (following this post), or it diverts from the allocated port 99. Add the following two lines to wp_config.php:
    define('WP_HOME','http://10.10.10.10:99/blog');
    define('WP_SITEURL','http://10.10.10.10:99/blog');

    Note that there’s no trailing slash. Adding one makes double slashes on the URLs generated by WordPress.

That’s it. At this point the blog worked. Log in with the same user and password as the real blog.

Automatic upgrade of the mirror

Create a new user, sitemirror, but don’t create the user’s home directory. Instead, edit /etc/passwd to set the home directory at the site’s root directory (not the public_html, but where public_html can be found).

Also, change the ownership of that directory to that user, or the modification through ftp won’t work:

# chown -R sitemirror sitemirror/

And start the ftp service (it doesn’t matter that the WordPress has an SFTP option. It goes for regular port 21 anyhow):

# service vsftpd start

Also, make the path accessible to the sitemirror user (in my case, it meant making the home directory accessible to all. Temporarily!)

Now, on the automatic upgrade page, go for localhost and the username/password of the ad-hoc sitemirror user.

And you get something like this:

Screenshot after upgrading

 

And now revert the damage made above: Shut down vsftpd (and verify port 21 is closed), fix the ownership of the sitemirror directory, and restore the ownership of the home directory.

Then remove the sitemirror user (but not its home directory, obviously).

This is for upgrading the local mirror blog. On the real blog, it was just clicking on the button for upgrading. No questions asked about FTP or anything like that.

But the irony is that after upgrading (to 4.7.2), I attempted to publish this post, but “Publish” button was inactive, and the editor stuck on “Saving Draft…”. To double the irony, I upgraded just because one has to, as a security measure. All was fine.

Oddly enough, I didn’t have a similar problem with the (upgraded) mirrored blog.

I wrote a separate post on how I worked around this issue.

How I love upgrading. Actually, I love downgrading more.

Manual wireless setting on Fedora 12

What’s this?

This is a note for myself, in case I need a quick replacement for my ADSL connection on the desktop computer (Fedora 12, and oldie). It may seem paradoxical that I’ll read this in order to access the internet (…), but this is probably where I would look first. With my cellphone, which is also the temporary access point, that is.

In short, there’s a lot of stuff here particular to my own computer.

I’m using the small TP-LINK dongle (TL-WN725N), which is usually doing nothing in particular.

Notes to self

  • This post is also on your local blog (copy-paste commands…)
  • wlan1 is the Access Point dongle (maybe use it instead…?)
  • Put the phone in the corner next to the door (that’s where I get a 4G connection) once the connection is established…
  • … but not before that, so you won’t run back and forth

Setting up the interface

# service ADSL off
# /etc/sysconfig/network-scripts/firewall-wlan0
# ifconfig wlan0 up
# wpa_supplicant -B -Dwext -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
ioctl[SIOCSIWAP]: Operation not permitted
# iwlist wlan0 scan
wlan0     Scan completed :
          Cell 01 - Address: 00:34:DA:3D:F8:F5
                    ESSID:"MYPHONE"
                    Protocol:IEEE 802.11bgn
                    Mode:Master
                    Frequency:2.462 GHz (Channel 11)
                    Encryption key:on
                    Bit Rates:108 Mb/s
                    Extra:rsn_ie =30140100000fac040100000fac040100000fac020c00
                    IE: IEEE 802.11i/WPA2 Version 1
                        Group Cipher : CCMP
                        Pairwise Ciphers (1) : CCMP
                        Authentication Suites (1) : PSK
                    IE: Unknown: DD5C0050F204104A0001101044000102103B00010310470010A7FED45DE0455F5DB64A55553EB96669102100012010230001201024000120104200012010540008000000000000000010110001201008000221481049000600372A000120
                    Quality:0  Signal level:0  Noise level:0

# iwconfig wlan0 essid MYPHONE
# dhclient wlan0 &

Note that wpa_supplicant complained, and it was still fine. Use the -d or -dd flags for some debugging info.

It seems like the iwconfig is redundant, as wpa_supplicant handles this, thanks to the “scan_ssid=1″ attribute in the config entry (?). The DHCP client isn’t redundant, because the routing table isn’t set correctly without it (making wlan0 the default gateway)

Shutting down

  • Kill wpa_supplicant (it was run as a daemon)
  • Kill DHCP client:
    # dhclient -r
  • Restart networking
    # service network restart
    # service firewall restart
    # service ADSL start

WPA supplicant config file

The WPA supplicant scans wlan0 and finds matching SSIDs. If such is found, it sends the password. Looks like it handles the association.

/etc/wpa_supplicant/wpa_supplicant.conf should read:

ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel

network={
  ssid="MYPHONE"
  scan_ssid=1
  key_mgmt=WPA-PSK
  psk="MYPASSWORD"
}

(it’s already this way)

Script for fixing a lot of git tags

I needed to update a lot of releases, each designated by a tag, with a single fix, which took the form of a commit. This commit was marked with the tag “this”.

#!/bin/bash
for i in $(git tag | grep 2.0) ; do
 git checkout $i
 git cherry-pick this
 git tag -d $i
 git tag $i
done

This bash script checks out all tags that match “2.0″, and advances it after cherry-picking. Recommended to try it on a cloned repo before going for the real thing, or things can get sad.

Raspberry Pi 3 notes

These are messy, random notes that I took while setting up my little Raspberry Pi 3. Odds are that by the time you read this, I’ve replaced it with a mini-PC. So if you ask a question, my answer will probably be “I don’t remember”.

Even though the Pi is cool, it didn’t supply what I really wanted from it, which is simultaneous output on SDTV and HDMI. It also turns out that it’s unable to handle a large portion of the video streams and apps out there on the web, seemingly because the lack of processing power vs. the resolution of these streams (running Kodi, which I suppose is the best optimized application for the Pi). So as a catch-all media center attached to a TV set, it’s rather useless.

Starting

  • Used the 2016-11-25-raspbian-jessie.zip image
  • Raspbian: To get remote access over ssh, do “service ssh start” and login as “pi” with password “raspberry”. Best to remove these before really working. To make ssh permanent, go
    # systemctl enable ssh
  • Cheap USB charger from Ebay didn’t hold the system up, and a reboot occurred every time the system attempted to boot up. The original LG G4 charger is strong enough, though.
  • Kodi installed cleanly with
    # apt-get update
    # apt-get install --install-suggests kodi
    # apt-get install --install-suggests vlc
  • … but it seems like vlc doesn’t use video acceleration, and I tried a lot to make it work. It didn’t. So it’s quite useless.
  • Enabling Composite output: Use a four-lead 3.5mm plug (a stereo plug doesn’t work). The Samsung screen refused to work, but Radiance detected the signal OK.
    I used old Canon Powershot’s video cable, but attached to the RED plug for video, and not the yellow.
    In /boot/config.txt, uncomment 

    sdtv_mode=2

    however composite video is disabled when an HDMI monitor is detected, and Q&A’s on the web seem to suggest that simultaneous outputs is not possible. Following this page, I tried setting (so that the HDMI output matches)

    hdmi_group=1
    hdmi_mode=21

    and got 576i (PAL) on the HDMI output but the signals on the composite output were dead (checked with a scope).

  • Added “eli” as a user:
    # adduser --gid 500 --uid 1010 eli
  • Add “eli as sudoer”. Add the file /etc/sudoers.d/010_eli-nopasswd saying
    eli ALL=(ALL) NOPASSWD: ALL
  • Manually edit /etc/groups, find all the places it says “pi” and add “eli” — so they have some groups. Compare “id” outputs.
  • Add ssh keys for password-less access (use ssh-copy-id)
  • Change the timezone
    $ sudo raspi-config

    pick “4 Internationalisation Options” and change the timezone to Jerusalem

  • Set “eli” as the default login: One possibility would have been to change the config script (usr/bin/raspi-config) as suggested on this page. Or change /etc/lightdm/lightdm.conf so it says
    autologin-user=eli

    as for console login, the key line in raspi-config is

    ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service

    so the change is to edit /etc/systemd/system/autologin@.service so it says

    ExecStart=-/sbin/agetty --autologin eli --noclear %I $TERM
  • Turn off scrrensaver / blanking: First check the current situation (from an ssh session, therefore specific about display)
    $ xset -display :0 q
    Keyboard Control:
      auto repeat:  on    key click percent:  0    LED mask:  00000000
      XKB indicators:
        00: Caps Lock:   off    01: Num Lock:    off    02: Scroll Lock: off
        03: Compose:     off    04: Kana:        off    05: Sleep:       off
        06: Suspend:     off    07: Mute:        off    08: Misc:        off
        09: Mail:        off    10: Charging:    off    11: Shift Lock:  off
        12: Group 2:     off    13: Mouse Keys:  off
      auto repeat delay:  500    repeat rate:  33
      auto repeating keys:  00ffffffdffffbbf
                            fadfffefffedffff
                            9fffffffffffffff
                            fff7ffffffffffff
      bell percent:  50    bell pitch:  400    bell duration:  100
    Pointer Control:
      acceleration:  20/10    threshold:  10
    Screen Saver:
      prefer blanking:  yes    allow exposures:  yes
      timeout:  600    cycle:  600
    Colors:
      default colormap:  0x20    BlackPixel:  0x0    WhitePixel:  0xffffff
    Font Path:
      /usr/share/fonts/X11/100dpi/:unscaled,/usr/share/fonts/X11/75dpi/:unscaled,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi,built-ins
    DPMS (Energy Star):
      Standby: 600    Suspend: 600    Off: 600
      DPMS is Enabled
      Monitor is On

    So turn it off, according to this thread. Edit /etc/kbd/config to say (in different places of the file)

    BLANK_TIME=0
    POWERDOWN_TIME=0

    and then append these lines to ~/.config/lxsession/LXDE-pi/autostart (this is a per-user thing):

    @xset s noblank
    @xset s off
    @xset -dpms

More jots

  • The script that warns against the unchanged password for “pi” user is at /etc/xdg/lxsession/LXDE-pi/sshpwd.sh, and is launched by /etc/xdg/autostart/pprompt.desktop
  • For some info on how to run a power fail safe system by mounting most of the filesystem as readonly, see this page.
  • Obtaining the .config file (from the kernel build guide):
    On Raspberry’s official kernel, check out git ID 4eb9a81002485a7abfa53a334dde5bc10328079f (as 4.4.34), and go 

    $ make ARCH=arm bcm2709_defconfig

Kodi setup

  • Change setting level to Advanced
  • System > Settings > Enable TV
  • System > Settings > System > Power savings, set Shutdown function to Minimise (actually, it didn’t help regarding the blackout of the screen on exit)
  • Enable and Configure PVR IPTV Simple Client
  • On exit, use Ctrl-Alt-F1 and then Ctrl-Alt-F7 to get back from the blank screen it leaves (/bin/chvt should do this as well?)

Video issues

I wanted to get a simultaneous SDTV / HDMI output. Everyone says it’s impossible, but I wanted to give it a try. I mean, it’s the drivers that say no-no, but one can find a combination of registers that gets it working. The alternative is an external HDMI splitter, and then an HDMI to CVBS converter. Spoiler: I gave up in the end. Not saying it’s impossible, only that it’s not worth the bother. So:

Broadcom implements the OpenMAX API, which seems to have a limited set of GPGPU capabilities. For example see firmware/opt/vc/src/hello_pi/hello_fft/ in Raspberry’s official git repo. The QPU is documented in VideoCoreIV-AG100-R.pdf, and there’s an open source assembler for it, vc4asm. and possibly this one is better, mentioned on this page. Also look at this blog.

This page details the VideoCore interface for Raspberry.

An utility for switching between HDMI/SDTV outputs (in hindsight, I would go for the official tvservice instead, but this is what I did):

$ git clone https://github.com/adammw/rpi-output-swapper.git

But that didn’t work:

eli@raspberrypi:~/rpi-output-swapper $ make
cc -Wall -DHAVE_LIBBCM_HOST -DUSE_EXTERNAL_LIBBCM_HOST -DUSE_VCHIQ_ARM -I/opt/vc/include/ -I/opt/vc/include/interface/vcos/pthreads -I./ -g -c video_swap.c -o video_swap.o -Wno-deprecated-declarations
cc -o video_swap.bin -Wl,--whole-archive video_swap.o -L/opt/vc/lib/ -lbcm_host -lvcos -lvchiq_arm -Wl,--no-whole-archive -rdynamic
rm video_swap.o
eli@raspberrypi:~/rpi-output-swapper $ sudo ./video_swap.bin --status
failed to connect to tvservice

which comes from this part in tvservice_init():

    if ( vc_vchi_tv_init( vchi_instance, &vchi_connections, 1) != 0) {
        fprintf(stderr, "failed to connect to tvservice\n");
        exit(-4);
    }

which is implemented in userland/interface/vmcs_host/vc_vchi_tvservice.c, header file vc_tvservice.h in same directory (Raspberry’s official git repo).

After a lot of back and forth, I compared with the official repo’s tvservice utitlity and discovered that it doesn’t check vc_vhci_tv_init()’s return value. So I ditched the check on video_swap as well, and it worked. But the results on the screen were so messy, that I didn’t want to pursue this direction.

In what follows, some things I found out while trying to solve the problem: The program opens /dev/vchiq on bcm_host_init(), and performs a lot of ioctl()’s on it. The rest of tvservice_init() until the error message causes no system calls at all!

/dev/vchiq had major/minor 248/0 on my system. According to /proc/devices, it belongs to the vchiq module (not a big surprise…). Drivers are at drivers/misc/vc04_services/interface/vchiq_arm/ Seemingly with vchiq_arm.c as the top level file, and are enabled with CONFIG_BCM2708_VCHIQ.

There’s a utility, vcgencmd , for setting a lot of different things, log levels among them, but I didn’t manage to figure out where the log messages go to.