<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Tech Tidbits</title>
    <link>https://octet-stream.net/b/tt/</link>
    <description></description>
    <managingEditor>tom.karpiniec@outlook.com (Thomas Karpiniec)</managingEditor>
    <pubDate>Wed, 13 May 2026 00:02:40 +0000</pubDate>
    <item>
      <title>Disabling the LED on a new Razer Cobra</title>
      <link>https://octet-stream.net/b/tt/disabling-the-led-on-razer-cobra.html</link>
      <description></description>
      <content:encoded><![CDATA[<p>
Recently my mouse began to die and I went searching for a replacement. I wanted something not too cheap but also not too expensive and gamery and eventually picked up a <a href="https://www.razer.com/gaming-mice/razer-cobra">Razer Cobra</a>. It's wired, nice and light, doesn't have an excess of buttons, and it's supposedly suitable for my style of mouse grip ("fingertip", according to companies who make mice). It's only been a few days but so far I'm quite happy with it. It's responsive and feels nice to use, though the button clicks are pretty loud.
</p>

<p>
I plugged this into a system running Debian testing (trixie) and had no intention of doing any sort of fancy mouse customisations, let alone letting <a href="https://www.bleepingcomputer.com/news/security/razer-bug-lets-you-become-a-windows-10-admin-by-plugging-in-a-mouse/">using Razer's own software for anything</a>. Unfortunately for me, it came out of the box with a very bright RGB-illuminated logo on the top that is continuously cycling through colours. I was thinking about just putting a sticker over it when I noticed that there is a very shmick <a href="https://openrazer.github.io/">OpenRazer project</a> to facilitate controlling these Razer peripherals on Linux, so I thought I would give that a go. I would tolerate installing a bit of one-off software but I wanted to avoid adding custom apt repos or installing anything wildly unmaintained.
</p>

<p>
Complete success: my LED is now off.
</p>

<p>
First install the required Debian packages:
</p>

<pre>
apt install openrazer-meta python3-pip
</pre>

<p>
Then reboot the machine to let the driver take effect.
</p>

<p>
Install <code>razer-cli</code>, a CLI configuration tool written in Python. It needs to use the system openrazer install so I passed <code>--break-system-packages</code>, but to contain any chaos to my own user I also passed <code>--user</code>. This has the ultimate result that the program works and is installed at <code>~/.local/bin/razer-cli</code>.
</p>

<pre>
pip3 install razer-cli --user --break-system-packages
</pre>

<p>
Hooray, it works:
</p>

<pre>
$ <b>./.local/bin/razer-cli -l</b>
Found 1 Razer device(s)
Razer Cobra:
   type: mouse
   DPI: (1800, 1800)
   max DPI: 8500
   DPI stages: (3, [(400, 400), (800, 800), (1600, 1600), (3200, 3200), (6400, 6400)])
   polling rate: 500
   generic zone:
   logo zone:
      brightness: 75.0
      colors: ['00FF00', '00FFFF', '0000FF']
      effect: spectrum
      speed: 1
      wave_dir: 1
      effects available: breath_dual, breath_random, breath_single, brightness, none, reactive, spectrum, static
   serial: PM2443H27003395
   firmware version: v1.0
   driver version: 3.9.0
   supported capabilities: name, type, firmware_version, serial, poll_rate, supported_poll_rates, dpi, dpi_stages, lighting, lighting_logo, lighting_logo_brightness, lighting_logo_spectrum, lighting_logo_static, lighting_logo_none, lighting_logo_reactive, lighting_logo_breath_single, lighting_logo_breath_dual, lighting_logo_breath_random
</pre>

<p>
Now let's set that brightness down to zero.
</p>

<pre>
$ <b>./.local/bin/razer-cli -b 0</b>
creating path and file
Adding new settings entry
</pre>

<p>
All done. Nice.
</p>

]]></content:encoded>
      <author>Thomas Karpiniec</author>
      <guid>urn:uuid:f2cfdd5e-da1f-4bc1-bb3f-344ca26266b9</guid>
      <pubDate>Tue, 14 Jan 2025 21:54:27 +1100</pubDate>
    </item>
    <item>
      <title>No route to host - Debian testing firewall</title>
      <link>https://octet-stream.net/b/tt/no-route-to-host-firewall.html</link>
      <description></description>
      <content:encoded><![CDATA[<p>
My old laptop recently failed catastrophically due to a hardware or driver issue and the filesystem was corrupted so badly I had to reinstall the OS. I installed the latest Debian testing (trixie) release and all was well until I tried to set up Syncthing. The laptop was being discovered by others but it couldn't see anyone itself. Attempts to share folders were failing silently.
</p>

<p>
Weirder yet, my desktop could ping the laptop but if I tried to connect to the Syncthing port with <kbd>nc -v $ip 22000</kbd> then it would report "no route to host". What? My routes are fine!
</p>

<p>
As many sysadmins would know, and I had forgotten, you can get this strange-looking error when the connection is being denied by a firewall. This is all well and good, but since when does Debian have a firewall installed by default?
</p>

<p>
<a href="https://forums.debian.net/viewtopic.php?t=161561">Apparently this is actually due to a "recommends" dependency on <code>firewalld</code></a> when you choose the "KDE" option in the installer. I don't know but I suspect this is a packaging bug more than an intentional decision. Anyways, uninstalling <code>firewalld</code> got me back in business.
</p>

]]></content:encoded>
      <author>Thomas Karpiniec</author>
      <guid>urn:uuid:9d19f00e-8b8c-45e5-9877-f00605ed03e4</guid>
      <pubDate>Wed, 26 Feb 2025 20:45:09 +1100</pubDate>
    </item>
    <item>
      <title>Digirig reporting incorrect channel count on Windows</title>
      <link>https://octet-stream.net/b/tt/2025-07-11-digirig-windows-dolby.html</link>
      <description></description>
      <content:encoded><![CDATA[<p>
One of the peculiarities of developing <a href="https://octet-stream.net/p/m17rt">M17RT</a> is working with the Rust cross-platform audio library <a href="https://github.com/RustAudio/cpal">cpal</a>. I'm not out to criticise cpal today&mdash;it's a wonderful library&mdash;but it <em>is</em> pretty low-level. As a developer I am required to take into account that certain input and output devices may support particular sample formats (e.g. 16 or 32-bit signed integers) and particular sample rates (e.g. 44.1&nbsp;kHz or 48&nbsp;kHz) and I need adapt my audio data to fit what's available.
</p>

<p>
One of the most popular USB audio interfaces for amateur radio is a gizmo called the <a href="https://digirig.net/">Digirig</a>. I own two of them. When I plug it in to my Win11 desktop, cpal offers me four choices for consuming the audio input: u8, i16, i32 or f32 sample formats all at 48&nbsp;kHz and with one channel. This is correct&mdash;it's a mono device.
</p>

<p>
You can imagine my surprise when I plugged exactly the same device into my Win11 laptop and cpal offered me i32 or f32 at 48&nbsp;kHz with <em>four</em> channels. Suspiciously, this is exactly the same combinations offered by the laptop's built-in microphone. How did it go so wrong? Was it a bug in cpal? (Spoiler: It was not.)
</p>

<pre>
Onboard sound card:
SupportedStreamConfigRange { channels: 4, min_sample_rate: SampleRate(48000), max_sample_rate: SampleRate(48000), buffer_size: Range { min: 0, max: 4294967295 }, sample_format: I32 }
SupportedStreamConfigRange { channels: 4, min_sample_rate: SampleRate(48000), max_sample_rate: SampleRate(48000), buffer_size: Range { min: 0, max: 4294967295 }, sample_format: F32 }

Digirig:
SupportedStreamConfigRange { channels: 4, min_sample_rate: SampleRate(48000), max_sample_rate: SampleRate(48000), buffer_size: Range { min: 0, max: 4294967295 }, sample_format: I32 }
SupportedStreamConfigRange { channels: 4, min_sample_rate: SampleRate(48000), max_sample_rate: SampleRate(48000), buffer_size: Range { min: 0, max: 4294967295 }, sample_format: F32 }
</pre>

<p>
It turns out my Lenovo laptop came with some fancy Dolby drivers which by default would insert themselves to do some sort of signal processing on the input and output of an attached USB audio device. As a result cpal was talking to this virtual audio component which had different expectations of format, instead of directly providing samples for the digirig behind it like I wanted.
</p>

<p>
Luckily the solution was quite simple. I just had to go through sound settings for both the USB input and output devices and disable audio enhancements.
</p>

<a href="https://octet-stream.net/assets/tidbits/cpal-issue.png"><img src="https://octet-stream.net/assets/tidbits/cpal-issue.png"></a>

<p>
Now cpal enumerates the configurations for the Digirig how I expected. The lesson is clear&mdash;if you're using a Digirig on Windows you will definitely want to make sure this is disabled. Otherwise a driver like this might interfere with your digital radio signals. This is my fault of course. Digirig's <a href="https://digirig.net/getting-started-with-digirig-mobile/">getting started guide</a> warns that you need to turn off "custom features" like "spatial audio". I hadn't checked; when I first got the Digirig I was using it with a Linux system and had no such issues.
</p>

<pre>
SupportedStreamConfigRange { channels: 1, min_sample_rate: SampleRate(48000), max_sample_rate: SampleRate(48000), buffer_size: Range { min: 0, max: 4294967295 }, sample_format: U8 }
SupportedStreamConfigRange { channels: 1, min_sample_rate: SampleRate(48000), max_sample_rate: SampleRate(48000), buffer_size: Range { min: 0, max: 4294967295 }, sample_format: I16 }
SupportedStreamConfigRange { channels: 1, min_sample_rate: SampleRate(48000), max_sample_rate: SampleRate(48000), buffer_size: Range { min: 0, max: 4294967295 }, sample_format: I32 }
SupportedStreamConfigRange { channels: 1, min_sample_rate: SampleRate(48000), max_sample_rate: SampleRate(48000), buffer_size: Range { min: 0, max: 4294967295 }, sample_format: F32 }
</pre>

]]></content:encoded>
      <author>Thomas Karpiniec</author>
      <guid>urn:uuid:8009fad8-e137-4e5c-8991-2bbdfb4f273b</guid>
      <pubDate>Fri, 11 Jul 2025 14:57:09 +1000</pubDate>
    </item>
    <item>
      <title>Getting YOLO mode in GitHub Copilot with VS Code</title>
      <link>https://octet-stream.net/b/tt/2025-11-12-vscode-github-copilot-yolo-mode.html</link>
      <description></description>
      <content:encoded><![CDATA[<p>
Recently I've been semi-vibing a data processing pipeline. Don't worry, the output is easy to check and I'm not making anyone else read or otherwise deal with this code. Anyhoo, VS Code has some bugs which mean that the "auto-approve" functionality doesn't work terribly well (<a href="https://github.com/microsoft/vscode/issues/273415">vscode#273415</a>, <a href="https://github.com/microsoft/vscode/issues/266651">vscode#266651</a>, <a href="https://github.com/microsoft/vscode/issues/274133">vscode#274133</a>, etc.). I am developing in a Codespace container and for the purposes of this project I feel pretty good about letting the AI do whatever it wants without badgering me all the time. Even if it was actively malicious, at worst it could trash my private GitHub repo. That would be unfortunate but not a tragedy.
</p>

<p>
As far as I can tell reading around online there used to be an explicit "YOLO mode" in the preferences but this seems to have disappeared. There's an auto-approve setting where you can choose which commands (or regexes matching commands) are allowed. Unfortunately, even though <code>/.*/</code> is documented as "allow every command" this simply doesn't work and one ends up having to click "Approve" a lot.
</p>

<p>
The good news is that the YOLO setting remains although it's a little hard to find. (A Microsoft employee mentions it in the second issue above.) The trick is that you need to open the <em>remote</em> settings JSON for your codespace&mdash;it doesn't work if you set it locally&mdash;and enable <code>chat.tools.global.autoApprove</code>.
</p>

<p>
So if you Command-Shift-P, choose <code>Preferences: Open Remote Settings (JSON)</code>.
</p>

<a href="https://octet-stream.net/assets/remote-settings.png"><img src="https://octet-stream.net/assets/remote-settings.png"></a>

<p>
Then inside the global <code>{ ... }</code> JSON object, add:
</p>

<pre>
    "chat.tools.global.autoApprove": true,
</pre>

<p>
Now, the first time GitHub Copilot tries to run a command in a given session you'll get a dialog box asking you to confirm YOLO mode. You say yes, and then it will blissfully go ahead and run all the commands it wants to. Magnificent.
</p>

]]></content:encoded>
      <author>Thomas Karpiniec</author>
      <guid>urn:uuid:8036fe13-7cfa-4f5b-98c4-9aeb5b91ecac</guid>
      <pubDate>Wed, 12 Nov 2025 10:59:05 +0000</pubDate>
    </item>
    <item>
      <title>High CPU reading epubs and PDFs in Linux</title>
      <link>https://octet-stream.net/b/tt/2026-02-10-high-cpu-epub-pdf-linux.html</link>
      <description></description>
      <content:encoded><![CDATA[<p>
Recently I had a peculiar problem with some ebooks. Both Calibre and Okular were obscenely slow when I tried to open these documents or switch between pages. Converting the epub to PDF didn't seem to make any difference. The programs would freeze up for tens of seconds at a time while one CPU core ran hot. I poked around in the epub's contents and couldn't see anything out of place. It wasn't like it was hundreds of MB of scanned pages or anything like that.
</p>

<p>
I found the solution by accident: install a proper font for Chinese characters. Although these texts were English they had Hanzi sprinkled liberally throughout. In some parts of the UI they were rendered extremely poorly and in other parts they were missing entirely. I'm not exactly sure why this hits the CPU so hard. I guess it was doing some sort of search to figure out what to display instead? So I ran:
</p>

<pre>
sudo zypper in google-noto-sans-cjk-fonts
</pre>

<p>
...and now I not only have all the characters, but everything is nice and fast. Aren't computers grand?
</p>

]]></content:encoded>
      <author>Thomas Karpiniec</author>
      <guid>urn:uuid:0d0ce0e3-9bb0-4d3a-8a68-46a35cda36ad</guid>
      <pubDate>Tue, 10 Feb 2026 19:28:21 +1100</pubDate>
    </item>
  </channel>
</rss>