Category Archives: software

Silabs Silicon Labs Configurator (SLC) command line

Wow, this is clearly not used much! but, it does seem to work so far? I’ve only taken a few steps, so this is note taking for me and the rest of the internet!


It talks about pip install -r requirements.txt, but even if you run it in a venv, somewhere it … escapes? and relies on system libraries, or something. You’ll get failures about unable to find jinja2 anyway. (I already had python3-jinja2 installed system wide, but it failed anyway. I had to remake the virtual env with

$ python3 -m venv --system-site-packages .env33
$ . .env33/bin/activate
(.env33) $ pip install -r requirements.txt

Generate a project

Ok, this is described (poorly, IMO) in their UG520: Software Project Generation and Configuration with SLC-CLI, (also linked from the bottom of the readme of the Gecko SDK) which at least is trying to document this process, so props for getting there I guess.

slc generate ~/SimplicityStudio/SDKs/gecko_sdk/app/bluetooth/example/soc_thermometer/soc_thermometer_freertos.slcp -d ~/src/slc-test1-soc-thermo -np --with brd4184a

Ok, that wasn’t so bad. You can use parts instead of brd ids, but that went ok. You’ll need to use “slc configuration …” to set your sdk path separately. I got a failure about “untrusted sdk” first, which was not described in UG520, but it at least gave me the command line to “trust” the sdk. I don’t know what the goals here are, I presume it’s important for secure boot stuff one day?

You can now simply “make” in the output directory. Not bad. Lots of files, lots of files but hey, command line ready to go…

Adding bluetooth configuration

Ok, but what about the UI for GATT config and things? Components I’m not covering (yet), I _think_ you just edit your .slcp in the output directory?) but I needed to know how to generate the bluetooth stuff again.

Bad news, you’re editing xml. Good news, it’s not terribly sucky, as long as you have a decent grasp of how bluetooth works. There’s online “help” for the syntax inside simplicity studio, if you click the “Manual” button

Click “View manual” to get the syntax for the XML

You can even, while you’re playing, do it in simplicity studio, and then rip it out again. Save in the UI, then right click the “gatt_configuration.btconf” and choose edit in text editor and view it as the plain old XML it is underneath. (What’s a namespace? What’s a QName? aintnobodygottime.gif)

Ok, so you edited your project_path/config/btconf/gatt_configuration.btconf and want to regenerate all the things that need regenerating, filling that sweet “autogen” folder right? slc has a temptingly named “btConfig” that sounds like it might do the right thing. So you run it and give it arguments until it’s happy right?


$ slc btConfig generate -contentFolder $(realpath config/btconf) -generationOutput $(realpath autogen)

But how did we get there? Really?

$ slc btConfig generate -contentFolder config/btconfg -generationOutput autogen
Error: No 'gatt' node found in xml!
Error running command. Exit code: 1

Hrm. what? Maybe it wants the full path to the file, even though it says folder?

$ slc btConfig generate -contentFolder config/btconf/gatt_configuration.btconf -generationOutput autogen
Traceback (most recent call last):
  File "", line 167, in <module>
    od = xml_to_dict(args.inputs)
  File "", line 124, in xml_to_dict
    od[x] = GattXmlParser().to_string(x)
  File "/home/karlp/SimplicityStudio/SDKs/gecko_sdk/protocol/bluetooth/bin/gatt/", line 33, in to_string
    tree = ET.parse(xml)
  File "/home/karlp/tools/Silabs_slc_cli/bin/slc-cli/developer/adapter_packs/python/lib/python3.6/xml/etree/", line 1196, in parse
    tree.parse(source, parser)
  File "/home/karlp/tools/Silabs_slc_cli/bin/slc-cli/developer/adapter_packs/python/lib/python3.6/xml/etree/", line 586, in parse
    source = open(source, "rb")
FileNotFoundError: [Errno 2] No such file or directory: 'config/btconf/gatt_configuration.btconf'
Error running command. Exit code: 1

Well, progress, What? that smells like relative path brain damage….

$ slc btConfig generate -contentFolder $(realpath config/btconf/gatt_configuration.btconf) -generationOutput $(realpath autogen)

That… looks ok then? If you were clever, and had already committed the default state to revision control, you could check what it had done. And you’d see that you just lost the SiLabs OTA and health thermometer characteristics that were in the demo originally. If you look in the gatt_configuration.btconf, you also see that they’re not mentioned there! they’re just extra files dropped in the config/btconf directory. Ahhhh, so we don’t want to use the full path to the file, but we need to use our relative path workarounds we learnt later!

And that builds at least. Command line flashing/debugging/etc is for another day at least…. (We’re going to use SSv5 a bit more, we need to _work_ but at least we need to know how some of this might be possible

Simplicity Studio 5 on Fedora 34

UPDATE: You can do the steps below, and it will…. mostly work, but you’ll still run into broken things like, unable to enter text on the project config wizards or the bluetoot gatt configuration. The only _viable_ solution I’ve found really, is just to log out, and log in again choosing “Gnome on Xorg” and just not making wayland part of your daily headaches.

You still need the export GDK_BACKEND=x11 trick, and you still need the ./studio -Djxbrowser.chromium.dir=/home/$USER/.jxbrowser trick.

You also need to make sure you have git-lfs installed, or you will get fun errors like

/home/karlp/Downloads/SimplicityStudio_v5/developer/toolchains/gnu_arm/10.2_2020q4/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld:/home/karlp/SimplicityStudio/SDKs/gecko_sdk//protocol/bluetooth/lib/EFR32BG22/GCC/binapploader.o:1: syntax error

$ cat /home/karlp/SimplicityStudio/SDKs/gecko_sdk//protocol/bluetooth/lib/EFR32BG22/GCC/binapploader.o
oid sha256:59b50942a2f0085fe2c87d0d038b13b8af279c742f0d3013b1d1ad6929070a3f
size 66088

Oops, that doesn’t look like a bootloader binary! This is actually mentioned on as issue 76584, but you wouldn’t find that til later. The tips are to reinstall, but you can also

cd ~/SimplicityStudio/SDKs/gecko_sdk && git lfs fetch && git lfs pull && echo "whew, that took aaaages"

You can _probably_ do tricks with git lfs to just pull the single files you need, and avoid pulling the 800meg or something at 1meg/sec that it took, but this got me a building and functional simplicity studio! wheee…..

Restoring a Kicad 6.99 PCB to Kicad 6.x

Yah, I was using the 5.99 nightlies via a “kicad-nightly” package on fedora, and after Kicad 6.0 came out, this moved (correctly) to the 6.99 branch, which brought in a whole slew of new changes to the project files, which are… not backward compatible. (Which I also understand… but…)

So, what to do? First, edit the “version” in the top of the file to something like 20211014.

Then try and open the file, see how far along you were and how much got munched….

Try and remove strokes

The following VIM regex will strip all the line settings out. :%s/(stroke.*type solid))// If you had customized lines, sorry, you can’t have that in 6.0 anyway. Try re-opening the file again…

Try also :%s/(stroke.*type default))//

Try and remove thermal angles

more vim regexping…. :%s/(thermal_bridge_angle \d*)//g

That was enough for my file. Hopefully this helps someone…

Xiaomi Miijia LYWSD03MMC with pure bluetoothctl

Because software is software, it all gets thrown out every now and again for….. reasons. BlueZ, on linux, has moved away from hciconfig and hcitool and gattttool and so on, and it’s all “bluetoothctl” and “btmgmt” See for some more on that.

Anyway, I got some of these really cheap Xiaomi BTLE temperature+humidity meters. Turns out there’s a custom firmware you can flash to them and all sorts, but really, I was just interested in some basic usage, and also, as I’m getting my toes wet in bluetooth development, working out how to just plain use them as intended! (well, mostly, I’ve no intention of using any Xiaomi cloud apps)

This application claims to use the standard interface, and it’s “documentation” of this interface is and the little bit of code at

def connect():
	#print("Interface: " + str(args.interface))
	p = btle.Peripheral(adress,iface=args.interface)	
	p.writeCharacteristic(0x0038,val,True) #enable notifications of Temperature, Humidity and Battery voltage
	return p

Well, that wasn’t very helpful. Using tools like NrfConnect, I’m expecting things like a service UUID and a characteristic UUID and things. Also, I don’t have gatttool to even try it like this :)

So, how to do it in “modern” bluetoothctl? Here’s the cheatsheet. First, find our meters…

$ bluetoothctl
# menu scan
# clear
# transport le
# back
# scan on
SetDiscoveryFilter success
Discovery started
[CHG] Controller <your hci mac> Discovering: yes
[NEW] Device <a meter mac> LYWSD03MMC
[NEW] Device <other devices> <other ids>
# scan off

Now, we need to connect to it. According to it actually does broadcast the details about once every 10 minutes, which is neat, but you need a key for it, and aintnobodygottimeforthat.gif.

# connect <mac address>
lots and lots of spam like
[NEW] Descriptor (Handle 0x9f94)
	Characteristic User Description
[NEW] Descriptor (Handle 0xa434)
	Client Characteristic Configuration
[NEW] Characteristic (Handle 0xa904)
	Vendor specific
[NEW] Descriptor (Handle 0xb1d4)
	Characteristic User Description
....more lines like this.
[CHG] Device MAC_ADDRESS UUIDs: 00000100-0065-6c62-2e74-6f696d2e696d
[CHG] Device MAC_ADDRESS UUIDs: 00001800-0000-1000-8000-00805f9b34fb
[CHG] Device MAC_ADDRESS UUIDs: 00001801-0000-1000-8000-00805f9b34fb
[CHG] Device MAC_ADDRESS UUIDs: 0000180a-0000-1000-8000-00805f9b34fb
[CHG] Device MAC_ADDRESS UUIDs: 0000180f-0000-1000-8000-00805f9b34fb
[CHG] Device MAC_ADDRESS UUIDs: 0000fe95-0000-1000-8000-00805f9b34fb
[CHG] Device MAC_ADDRESS UUIDs: 00010203-0405-0607-0809-0a0b0c0d1912
[CHG] Device MAC_ADDRESS UUIDs: ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6
[CHG] Device MAC_ADDRESS ServicesResolved: yes

The characteristic you need is ebe0ccc1-7a0a-4b0c-8a1a-6ff2997da3a6, under the similar service UUID. So now, we just “subscribe” to notifications from it.

# menu gatt
[LYWSD03MMC]# select-attribute ebe0ccc1-7a0a-4b0c-8a1a-6ff2997da3a6
[LYWSD03MMC:/service0021/char0035]# notify on
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035 Notifying: yes
Notify started
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035 Value:
  36 09 2a f6 0b                                   6.*..           
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRRESS/service0021/char0035 Value:
  35 09 2a f6 0b                                   5.*..           
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035 Value:
  33 09 2a f6 0b                                   3.*..           
[LYWSD03MMC:/service0021/char0035]# notify off

And…. now we can go back to and decode these readings.

>>> x = "2a 09 2a 4e 0c"
>>> struct.unpack("<HbH",binascii.unhexlify((x).replace(" ","")))
(2346, 42, 3150)

With Python, that gives us a temperature of 23.46°C, humidity of 42%, and a battery level of 3.150V.


Originally, I was blind to the subtle differences in the characteristic UUIDs, and thought I had to hand iterate them. The below text at least shows how you can do that, but it’s unnecessary.

Ok, now the nasty bit. We want to get notifications from one of the characteristics on service UUID ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6. But you can’t just “select” this, because, at least as far as I can tell, there’s no way of saying _which_ descriptor you want.

So, first you need to use scroll that big dump of descriptors (or view it again with list-attributes in the gatt menu) to work out the “locally assigned service handle” In my case it’s 0021, but I’ve got zero faith that’s a stable number. You figure it from a line like this…

[NEW] Characteristic (Handle 0xd944)
	Vendor specific

Now, which characteristic is which? Well, thankfully, Xiaomi uses the lovely Characteristic User Description in their descriptors, so you just go through them one by one, “read”ing them, until you get to the right one…

[LYWSD03MMC:]# select-attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035/desc0037 
[LYWSD03MMC:/service0021/char0035/desc0037]# read
Attempting to read /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035/desc0037
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035/desc0037 Value:
  54 65 6d 70 65 72 61 74 75 72 65 20 61 6e 64 20  Temperature and 
  48 75 6d 69 64 69 74 79 00                       Humidity.       
  54 65 6d 70 65 72 61 74 75 72 65 20 61 6e 64 20  Temperature and 
  48 75 6d 69 64 69 74 79 00                       Humidity.       

The sucky bit, is you need to manually select _each_ of the “descNNNN” underneath _each_ of the “charNNNN” under this service. (On my devices, it’s the second characteristic with dual descriptors…)

now, select the characteristic itself. (you can’t get notifications on the descriptor…)

[LYWSD03MMC:/service0021/char0035/desc0037]# select-attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035
[LYWSD03MMC:/service0021/char0035]# notify on
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035 Notifying: yes
Notify started
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035 Value:
  2b 09 2a 4e 0c                                   +.*N.           
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035 Value:
  2a 09 2a 4e 0c                                   *.*N.           
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035 Value:
  2b 09 2a 4e 0c                                   +.*N.           
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035 Value:
  2b 09 2a 4e 0c                                   +.*N.           
[CHG] Attribute /org/bluez/hci0/dev_MAC_ADDRESS/service0021/char0035 Value:
  29 09 2a 4e 0c                                   ).*N.           
[LYWSD03MMC:/service0021/char0035]# notify off

Autofailing autotools are autohell, as always

“Needed” a new version of something, so build from source. Configure not available, because… autohell, so run “” instead.

karlp@nanopiduo2:~/src/libgpiod$ ./ 
autoreconf: Entering directory `.'
autoreconf: not using Gettext
autoreconf: running: aclocal --force -I m4
aclocal: warning: couldn't open directory 'm4': No such file or directory
autoreconf: tracing
autoreconf: creating directory autostuff
autoreconf: not using Libtool
autoreconf: running: /usr/bin/autoconf --force error: possibly undefined macro: AC_CHECK_HEADERS
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation. error: possibly undefined macro: AC_LIBTOOL_CXX error: Unexpanded AX_ macro found. Please install GNU autoconf-archive. error: possibly undefined macro: AC_LANG_PUSH error: possibly undefined macro: AC_LANG_POP error: Unexpanded AX_ macro found. Please install GNU autoconf-archive.
autoreconf: /usr/bin/autoconf failed with exit status: 1

Whatever, this is “traditional” that you can’t actually use autohell without adding more autohell from somewhere else, but ok, bend the knee, install autoconf-archive and continue….

karlp@nanopiduo2:~/src/libgpiod$ ./ 
autoreconf: Entering directory `.'
autoreconf: not using Gettext
autoreconf: running: aclocal --force -I m4
aclocal: warning: couldn't open directory 'm4': No such file or directory
autoreconf: tracing
autoreconf: not using Libtool
autoreconf: running: /usr/bin/autoconf --force error: possibly undefined macro: AC_CHECK_HEADERS
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation. error: possibly undefined macro: AC_LIBTOOL_CXX error: possibly undefined macro: AC_LANG_PUSH error: possibly undefined macro: AC_LANG_POP
autoreconf: /usr/bin/autoconf failed with exit status: 1

wat? really? that’s it? Thanks for nothing. Google and the accumulated wisdom of years of hate suggest that, as this is a “new” machine, I might not have installed pkg-config. (Given that the whole thing with autohell is finding things, you might think it could give you a better error?) ok, Install that, try again

karlp@nanopiduo2:~/src/libgpiod$ ./ 
autoreconf: Entering directory `.'
autoreconf: not using Gettext
autoreconf: running: aclocal --force -I m4
aclocal: warning: couldn't open directory 'm4': No such file or directory
autoreconf: tracing
autoreconf: not using Libtool
autoreconf: running: /usr/bin/autoconf --force error: possibly undefined macro: AC_LIBTOOL_CXX
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.
autoreconf: /usr/bin/autoconf failed with exit status: 1

Progress, but… still not there. Still absolutely atrociously useless error messages. Now, I’ve read the README, it says to install autoconf-archive, and that’s about it. I have python3-dev and libstdc++-9-dev I’m not sure what else now…

Oh right. libtool, another gross piece of historic nonsense, that mostly just gets in the way, and leaves pretend files around the place.

Now autogen will ~finish, and run configure, happily checking whether I’m running on a 30 year old unpatched sparc solaris, so it applies the right workarounds, but don’t worry…

configure: error: "libgpiod needs linux headers version >= v5.10.0"

I mean, I’m super glad we included all that “portable” autohell bullshit when we’re explicitly tied to linux anyway. And not just any linux. At the time of writing, 5.10.0 was three days old.

At this point, there are now _other_ problems that autotools, but this is just another example of why you should NEVER be using autotools in 2020.

Jenkins agent systemd unit file

So, you try to setup an agent, and instead of getting a nice package or anything, you get told, “run this long java command line app” …. wat. Here’s a (very) basic system unit file to run your agent. You can copy the command lines from what jenkins provides itself.

$ cat /etc/systemd/system/jenkins-agent.service 
Description=My radical Jenkins agent

ExecStart=/usr/bin/java -jar /var/opt/jenkins-agent/agent.jar -jnlpUrl -secret @/var/opt/jenkins-agent/my.jenkins.secret-file -workDir /var/opt/jenkins-agent


(And remember, JDK8 for your agent, until is fixed)

Then, just systemctl enable jenkins-agent and systemctl start jenkins-agent.

Actually using FEL to boot openwrt on friendlyarm nanopi duo2

Following on from where we left off, now let’s actually use FEL for the whole process, not just to get uboot loaded. In the last piece, once uboot was loaded, we used uboot+tftp to boot our openwrt ramdisk, but FEL can do it all in one hit, over usb, according to and that’s way more useful on things that might not have an ethernet port onboard.

We basically just take our steps from the last one, and add them as options to the sunxi-fel tool.

First, we trim down our “my.env” file, as now it just needs to boot.

$ cat my-fel.cmd
setenv bootargs console=ttyS0,115200 earlyprintk
bootm $kernel_addr_r - $fdt_addr_r

Now, we convert that to the “scr” file that uboot will run magically.

$ tools/mkimage -C none -A arm -T script -d my-fel.cmd my-fel.scr

Now, use sunxi-fel with all the wonderful paths into the build guts of openwrt.

$ sunxi-fel uboot u-boot-sunxi-with-spl.bin write-with-progress 0x42000000 /home/karlp/src/openwrt-git/bin/targets/sunxi/cortexa7/openwrt-sunxi-cortexa7-sun8i-h3-nanopi-neo-initramfs-kernel.bin write 0x43000000 ~/src/openwrt-git/build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/linux-sunxi_cortexa7/linux-4.14.82/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dtb write 0x43100000 my-fel.scr
100% [================================================] 4013 kB, 770.4 kB/s

Because openwrt’s buildroot builds us a nice kernel+ramdisk image out of the box, (well, if you select “ramdisk” in the image settings) we don’t need to write the uImage and rootfs separately as indicated on the page.

For reference, the openwrt diffconfig to build this is just

$ ./scripts/

Booting openwrt on nanopi duo2 (or a nanopi neo) via FEL

Edit: See the next post to use just FEL via USB, (no cheating and using tftp afterwards like we do here)

(Very rough unformatted, just so I don’t lose it)

FriendlyARM NanoPi Duo2 is ~similar enough to a FriendlyARM NanoPi Neo to get started. Later, we’ll work on… later stuff.

I don’t want to go hacking around with sd cards and crap while I’m developing stuff, and FEL mode is great.

So… get a uboot built (2018.11 is what I tested) using “make nanopi_neo_defconfig” (You will almost definitely want to enable “Networking Support->Random ethaddr if unset”

Now, patch sunxi-fel:

Now, make an environment file with some helpers…. (you can do this by hand if you like)

bootcmd=echo "Hello $myvar."
bootargs=console=ttyS0,115200 earlyprintk
resetserver=setenv serverip
loadkernel=tftp $kernel_addr_r build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/linux-sunxi_cortexa7//sun8i-h3-nanopi-neo-kernel.bin
loaddtb=tftp $fdt_addr_r build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/u-boot-nanopi_neo/u-boot-2018.05/arch/arm/dts/sun8i-h3-nanopi-neo.dtb
loaddisk=tftp $ramdisk_addr_r
# Running dhcp will reset serverip....
winning=run resetserver && run loadkernel && run loaddtb && bootm $kernel_addr_r - $fdt_addr_r

(the magic variables are reffered to at
The magic trick of bootm $kernel_addr_r – $fdt_addr_r I got from extracting the openwrt sdcard image file, and reading the “boot.scr” file in the first partition.

Now, go and build openwrt master

Now, setup a dhcp/tftp server as appropriate for your network.

Now, use (patched) sunxi-fel (fixing udev perms if necessary):

sunxi-fel uboot u-boot-sunxi-with-spl.bin write 0x43100000 my.env

Now, on serial console, use uboot to dhcp an address and run stuff…

(ctrl-c to abort the dumb attempts at autofinding an image)
run resetserver
run winning

Now, enjoy the fruits of a whole lot of people’s labour…..

=> bootm $kernel_addr_r - $fdt_addr_r
## Booting kernel from Legacy Image at 42000000 ...
Image Name: ARM OpenWrt Linux-4.14.82
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 4013368 Bytes = 3.8 MiB
Load Address: 40008000
Entry Point: 40008000
Verifying Checksum ... OK
## Flattened Device Tree blob at 43000000
Booting using the fdt blob at 0x43000000
EHCI failed to shut down host controller.
Loading Kernel Image ... OK
Loading Device Tree to 49ff9000, end 49fff4b7 ... OK

Starting kernel ...

[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.14.82 (karlp@beros) (gcc version 7.3.0 (OpenWrt GCC 7.3.0 r8575-a734450d6f)) #0 SMP PREEMPT Mon Nov 26 20:27:17 2018
[ 0.000000] CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=30c5387d
[ 0.000000] CPU: div instructions available: patching division code
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[ 0.000000] OF: fdt: Machine model: FriendlyARM NanoPi NEO

boring bootlog snipped, you know what they look like

From here, we need to move to a real separate device tree for the duo2, prepare to get the AP6212 module up and running, and handle how overlays/custom versions should be handled….

tracker-miner-fs stuck at 100% alternative solution

There’s plenty of posts about problems with tracker-miner-fs being a CPU hog, even if it’s theoretically “idle”. “tracker status” will say that indexing is complete, and all miners are idle, but that’s clearly a lie, and you process stuck running from bootup.

Most “solutions” on the internet revolve around just turning off tracker completely, or at least the filesystem miner. I don’t want that, I actually like having search work. What I wanted was it to, you know, work :)

So, while experimenting with resetting it, I noticed that it was always getting stuck trying to recurse a particular directory tree. It’s 6GB, but that was unlikely to be problem. However, one directory there contained a lot of files. Lots like, 600,000 files or so, in one directory. This is enough to make ls hang, so, maybe it was enough to make tracker-miner-fs hang too? (Side note, if you want to count files in a directory like this, find . | wc -l will work, where ls doesn’t.)

I didn’t actually need those files anymore, so I just deleted the suspect directories entirely, and then restarted the trackers with tracker daemon --stop; tracker daemon --kill; tracker daemon --start (The kill was to kill the errant tracker-miner-fs process, the others all stopped gracefully)

And presto, tracker status starts reporting sane and plausible results, the tracker-miner-fs runs at 100% for a short period, reporting status correctly, then the tracker extractor takes over. And we have search again!

GVFS mount points, or, how to completely ignore usability while building a usability feature.

Gnome happily mounts my phone’s MTP shares for me. I can even browse for them in “files” and drag and drop and everything. It’s pretty cool. And, magically, behind the scenes, it even exists in the filesystem so I can use rsync and cp and things.

But the mount point…. Oh boy. What on earth were they thinking. /run/user/1000/gvfs/mtp\:host\=%5Busb%3A002%2C010%5D/
Are you fucking kidding me? That’s an url encoded way of saying [usb:002,010] Why did it need to be url encoded? No idea. What about the content? Oh, that’s the USB bus, and device address. Spectacular. That means it depends on not only what physical port it’s plugged into, but what order it was plugged in. (And that unplugging and replugging will make a new path) Let’s not use things like iManufacturer, iProduct, iSerial, vid, pid, anything actually device specific no, not here.

I’m sure this was done to try and ensure that the mount point would be unique. Great. Mission accomplished. However, it could be made unique, and usable at the same time. And then this thing, that exists out of a usability feature, would actually be more usable.