<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/rss-style.xsl" type="text/xsl"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	     xmlns:dc="http://purl.org/dc/elements/1.1/"
	   xmlns:atom="http://www.w3.org/2005/Atom"
	     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>linux &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/tag/linux/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Wed, 11 Feb 2026 09:38:26 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shkspr.mobi/blog/wp-content/uploads/2023/07/cropped-avatar-32x32.jpeg</url>
	<title>linux &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[Gadget Review: Epomaker TH87 ISO Mechanical Keyboard ★★★★⯪]]></title>
		<link>https://shkspr.mobi/blog/2026/02/gadget-review-epomaker-th87-iso-mechanical-keyboard/</link>
					<comments>https://shkspr.mobi/blog/2026/02/gadget-review-epomaker-th87-iso-mechanical-keyboard/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 11 Feb 2026 12:34:46 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[review]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=67546</guid>

					<description><![CDATA[If I&#039;m being brutally honest, I never really got the appeal of mechanical keyboards. There was always someone in the office who made a godawful racket hammering on their keyboard and then waxed lyrical about the merits of various switches. I&#039;d mostly just dismissed them as cranks. I&#039;m in love with my old Microsoft 4000 ergonomic keyboard. What use could I have a mechanical keyboard festooned with …]]></description>
										<content:encoded><![CDATA[<p>If I'm being brutally honest, I never really <em>got</em> the appeal of mechanical keyboards. There was always someone in the office who made a godawful racket hammering on their keyboard and then waxed lyrical about the merits of various switches. I'd mostly just dismissed them as cranks. I'm in love with my old <a href="https://shkspr.mobi/blog/2021/10/buying-obsolete-keyboards-microsoft-4000/">Microsoft 4000 ergonomic keyboard</a>. What use could I have a mechanical keyboard festooned with lights?</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/02/keyboard.webp" alt="A brightly multicoloured mess of a keyboard with a USB cable and keytool on it." width="2040" height="891" class="aligncenter size-full wp-image-67568">

<p>The good folks at <a href="https://epomaker.com/">Epomaker</a> want me to see the error of my ways and have sent me a couple of devices to review. Today I'm trying out the <a href="https://epomaker.com/products/epomaker-th87">TH87</a> and it is surprisingly lovely!</p>

<h2 id="blinken-lights"><a href="https://shkspr.mobi/blog/2026/02/gadget-review-epomaker-th87-iso-mechanical-keyboard/#blinken-lights">Blinken lights!</a></h2>

<p>Here's a quick video showing some of the effects.</p>

<p></p><div style="width: 620px;" class="wp-video"><video class="wp-video-shortcode" id="video-67546-2" width="620" height="349" preload="metadata" controls="controls"><source type="video/mp4" src="https://shkspr.mobi/blog/wp-content/uploads/2026/02/th87-new.mp4?_=2"><a href="https://shkspr.mobi/blog/wp-content/uploads/2026/02/th87-new.mp4">https://shkspr.mobi/blog/wp-content/uploads/2026/02/th87-new.mp4</a></video></div><p></p>

<p>Is this <em>necessary</em>? No! But it is jolly good fun. Probably a bit distracting - especially if you're in a dark space or a crowded office - but rather pleasing nevertheless. Switching between the effects means remembering the correct key combo - there's no way to do it programatically, you just have to cycle through them all.</p>

<h2 id="linux-compatibility"><a href="https://shkspr.mobi/blog/2026/02/gadget-review-epomaker-th87-iso-mechanical-keyboard/#linux-compatibility">Linux Compatibility</a></h2>

<p>The TH87 comes with a USB-C to A cable. Personally, I'd've preferred straight C-C, but this does the job. Flick the switch at the back to USB mode, plug it in, and Linux instantly detected it. No drivers to configure.</p>

<p>Rather cheekily, <code>lsusb</code> shows it as <code>05ac:0250 Apple, Inc. Aluminium Keyboard (ISO)</code> - there's another switch for changing between Mac and PC mode. That doesn't change how the keyboard presents itself; just the keycodes it sends.</p>

<p>Oddly, there was this warning in <code>dmesg</code>:</p>

<p><code>apple 0003:05AC:0250.0010: Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling</code></p>

<p>However, the function keys worked and I was able to control screen brightness etc using <kbd>Fn</kbd> and the <kbd>F1-12</kbd> keys.</p>

<p>There's also a Bluetooth option. Again, Linux use was a breeze - although you'll have to remember what the pairing combo is and which device it is paired to.</p>

<p>There's also a 2.4GHz option. Hidden under one of the feet is a little USB-A receiver. Again, pairing is simple - just plug it in and flick the switch.</p>

<p>As expected, it also plays well with Android. The Bluetooth connection worked as did USB-OTG. Of course, quite <em>why</em> you'd want a giant heavy keyboard paired to your tiny phone is an exercise left to the reader.</p>

<h2 id="clunk-click-every-trip"><a href="https://shkspr.mobi/blog/2026/02/gadget-review-epomaker-th87-iso-mechanical-keyboard/#clunk-click-every-trip">Clunk Click Every Trip</a></h2>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2026/02/EPOMAKER_TH87_ISO_UK_9.webp" alt="A keyboard with a UK layout and lots of colourful lights." width="1131" height="444" class="aligncenter size-full wp-image-67566">

<p>So let's talk about noise. This keyboard is noisier than some of my other typing surfaces, but not aggressively so. Apparently it is "pre-lubricated" and has some noise suppression. The travel on the switches is excellent, they aren't stiff, and the whole contraption is sturdy.</p>

<p>It was easy to remove the caps with the enclosed tool. I didn't bother trying to extract a switch because I'm afraid of buggering it up.</p>

<h2 id="other-things"><a href="https://shkspr.mobi/blog/2026/02/gadget-review-epomaker-th87-iso-mechanical-keyboard/#other-things">Other Things</a></h2>

<p>Battery life is excellent - as you'd expect from a 10,000 mAh unit. It recommends charging by attaching to a computer and warns a regular charger might damage it. But, frankly, it seemed to cope just fine.</p>

<p>There's no software for customising the colours or functionality. Apparently lots of mechanical keyboards run an Open Source firmware - but this appears to be proprietary.  There is some question about whether Epomaker comply with the GPL when it comes to the <a href="https://docs.qmk.fm/license_violations">QMK source</a>. They appear to have <a href="https://github.com/Epomaker?tab=repositories">some source code available</a> but it is hard to tell whether it exists for this specific model. I've contacted them for clarification.</p>

<p>There's a <em>lot</em> of technobabble on the website. Apparently it uses "5-Layer Sound Optimizing Design with PORON Sandwich Foam, IXPE Switch Pad, Sound Enhancement Pad, EPDM Switch Socket Pad, and Silicone Bottom". I've no ideas what it means, but it appears important to some people.</p>

<p>There's no number-pad, which is a bit of a shame. However the keyboard has a proper UK layout and is reasonably compact. Although at 1Kg it is almost as heavy as my laptop!</p>

<h2 id="cost"><a href="https://shkspr.mobi/blog/2026/02/gadget-review-epomaker-th87-iso-mechanical-keyboard/#cost">Cost</a></h2>

<p>I have no internal benchmark for something like this. It's around <a href="https://s.click.aliexpress.com/e/_c2RJxZJd">£60 from AliExpress</a> or <a href="https://amzn.to/4qaSRMf">£80 on Amazon UK</a> depending on whether you have pleased The Algorithm. That seems pretty reasonable for a hefty keyboard with lots of customisability.</p>

<p>If you want ALL THE LIGHTS and value the ability to hot-swap various keys and switches, I think this is a nifty bit of kit.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=67546&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2026/02/gadget-review-epomaker-th87-iso-mechanical-keyboard/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		<enclosure url="https://shkspr.mobi/blog/wp-content/uploads/2026/02/th87-new.mp4" length="38193797" type="video/mp4" />

			</item>
		<item>
		<title><![CDATA[Installing and Updating Filezilla from a Zip File on Pop_OS / Ubuntu]]></title>
		<link>https://shkspr.mobi/blog/2026/01/installing-and-updating-filezilla-from-a-zip-file-on-pop_os-ubuntu/</link>
					<comments>https://shkspr.mobi/blog/2026/01/installing-and-updating-filezilla-from-a-zip-file-on-pop_os-ubuntu/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 24 Jan 2026 12:34:21 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[pop_os]]></category>
		<category><![CDATA[ubuntu]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=65041</guid>

					<description><![CDATA[Notes to myself because I keep forgetting.  tl;dr Unzip it into the /opt/ directory.  I want to install Filezilla - so I can SFTP files around. Sadly, the Flatpak version is unmaintained and the version in apt is out of date. Luckily, you can download the zipped version.  Their Wiki helpfully says:  If you have special needs, don&#039;t have sufficient rights to install programs or don&#039;t like…]]></description>
										<content:encoded><![CDATA[<p>Notes to myself because I keep forgetting.</p>

<p><abbr title="To Long; Didn't Read">tl;dr</abbr> Unzip it into the <code>/opt/</code> directory.</p>

<p>I want to install Filezilla - so I can SFTP files around. Sadly, the <a href="https://github.com/flathub/org.filezillaproject.Filezilla/issues/103">Flatpak version is unmaintained</a> and the version in apt is out of date. Luckily, you can <a href="https://filezilla-project.org/download.php">download the zipped version</a>.</p>

<p>Their Wiki <a href="https://wiki.filezilla-project.org/Client_Installation#Zip_version">helpfully says</a>:</p>

<blockquote><p>If you have special needs, don't have sufficient rights to install programs or don't like installers, the zip version is there for you. A zip-file is a file that contains files inside of it. They are packed into one file and you need to unpack (unzip) them to use them.</p></blockquote>

<p>But it doesn't say where!</p>

<p>The answer is <a href="https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s13.html">the <code>/opt/</code> directory</a>.</p>

<p>Run this command:</p>

<p><code>sudo tar -xJf FileZilla_*_x86_64-linux-gnu.tar.xz -C /opt</code></p>

<p>The first time <a href="https://cyanogenmods.org/install-filezilla-in-ubuntu/">you may need to adjust the directory permissions</a>:</p>

<p><code>cd /opt/</code><br>
<code>sudo chown -R root:root FileZilla*</code></p>

<p>After installing, FileZilla will periodically check for updates. It will download them to the <code>~/Downloads/</code> directory. Run the above command to install the new version.</p>

<p>If you want to be able to launch Filezilla from your dashboard, or to pin it to your dock, you'll need to create:</p>

<p><code>/usr/share/applications/Filezilla.desktop</code></p>

<p>Place this text in it:</p>

<pre><code class="language-_">[Desktop Entry]
Name=Filezilla
Comment=FTP
Exec=/opt/FileZilla3/bin/filezilla
Icon=/opt/FileZilla3/share/icons/hicolor/scalable/apps/filezilla.svg
Type=Application
StartupWMClass=filezilla
Categories=Game;
</code></pre>

<p>What a faff!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=65041&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2026/01/installing-and-updating-filezilla-from-a-zip-file-on-pop_os-ubuntu/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Extracting Video from Motion Photos on Linux]]></title>
		<link>https://shkspr.mobi/blog/2025/12/extracting-video-from-motion-photos-on-linux/</link>
					<comments>https://shkspr.mobi/blog/2025/12/extracting-video-from-motion-photos-on-linux/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 28 Dec 2025 12:34:22 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[exif]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[photos]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=66565</guid>

					<description><![CDATA[Modern Android cameras can take &#34;Motion Photos&#34;. They capture a few seconds of video from before and after you hit the shutter button. You can then either select the bit of the photo where no-one is blinking, or you can send the whole thing as a little movie.  Some apps (like WhatsApp) will play the motion photo when the image is selected, others will just show a static image.  So how do you…]]></description>
										<content:encoded><![CDATA[<p>Modern Android cameras can take "Motion Photos". They capture a few seconds of video from before and after you hit the shutter button. You can then either select the bit of the photo where no-one is blinking, or you can send the whole thing as a little movie.</p>

<p>Some apps (like WhatsApp) will play the motion photo when the image is selected, others will just show a static image.</p>

<p>So how do you extract the movie from the image using Linux?</p>

<p>Step one, let's take a look at the EXIF metadata in the image. Here's what running <code>exiftool photo.MP.jpg</code> gets:</p>

<pre><code class="language-_">Motion Photo                    : 1
Motion Photo Version            : 1
Motion Photo Presentation Timestamp Us: 866808
Directory Item Mime             : image/jpeg, image/jpeg, video/mp4
Directory Item Semantic         : Primary, GainMap, MotionPhoto
Directory Item Length           : 46353, 2106347
Directory Item Padding          : 0
MPF Version                     : 0100
Number Of Images                : 2
MP Image Flags                  : (none)
MP Image Format                 : JPEG
MP Image Type                   : Undefined
MP Image Length                 : 46353
MP Image Start                  : 2570425
</code></pre>

<p>That can be cross-referenced with the <a href="https://developer.android.com/media/platform/motion-photo-format">Motion Photo metadata specification</a>.</p>

<p>We can confirm this is a Motion Photo, Version 1. The video portion at 866,808 microseconds (about 0.8 seconds) is where the main photo is taken from.</p>

<p>The file starts with the image, then a GainMap (for HDR), and then the video.</p>

<p>Somewhat obtusely (in my opinion) the Directory Item Length only shows "secondary media items" - in this case, the GainMap and Video.</p>

<p>The filesize is 4,723,125 bytes, which equals the sum of the three values; 46,353 + 2,106,347 + 2,570,425.</p>

<p>So, to get the MP4 video, we need to extract the <em>last</em> 2,106,347 bytes. This can be double-checked by taking the filesize and subtracting the MP Image Start and the MP Image Lengths (4,723,125 - 46,353 - 2,570,425 = 2,106,347).</p>

<p>The extraction can be done with <code>dd</code> but it's probably just as easy to use <code>tail</code> to read the last N bytes of a file:</p>

<p><code>tail -c 2106347 photo.MP.jpg &gt; video.mp4</code></p>

<p>You can verify that the video is valid by running <code>ffmpeg -i video.mp4</code> - the output will be lower resolution than the photo and will only be a few seconds long. It will play in VLC or any other standard player.</p>

<h2 id="try-it-yourself"><a href="https://shkspr.mobi/blog/2025/12/extracting-video-from-motion-photos-on-linux/#try-it-yourself">Try It Yourself</a></h2>

<p>Here's one of my motion photos - it should present in your browser as a still image, but run the above code to extract the video.</p>

<p><a href="https://shkspr.mobi/blog/wp-content/uploads/2025/12/PXL_20251220_224052239.MP_.bk.jpg"><img src="https://shkspr.mobi/blog/wp-content/uploads/2025/12/PXL_20251220_224052239.MP_.jpg" alt="Photo of a wind turbine." width="3072" height="4080" class="aligncenter size-full wp-image-66570"></a></p>

<p>Click the photo to download the full version rather than the optimised one.</p>

<h2 id="sources"><a href="https://shkspr.mobi/blog/2025/12/extracting-video-from-motion-photos-on-linux/#sources">Sources</a></h2>

<p>For other adventures in Motion Photo exploration, take a look at:</p>

<ul>
<li><a href="https://developer.android.com/media/platform/motion-photo-format">https://developer.android.com/media/platform/motion-photo-format</a></li>
<li><a href="https://motion-live.js.org/">https://motion-live.js.org/</a></li>
<li><a href="https://medium.com/android-news/working-with-motion-photos-da0aa49b50c">https://medium.com/android-news/working-with-motion-photos-da0aa49b50c</a></li>
</ul>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=66565&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/12/extracting-video-from-motion-photos-on-linux/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Gadget Review: Benfei USB-C Video Capture ★★★★★]]></title>
		<link>https://shkspr.mobi/blog/2025/11/gadget-review-benfei-usb-c-video-capture/</link>
					<comments>https://shkspr.mobi/blog/2025/11/gadget-review-benfei-usb-c-video-capture/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 15 Nov 2025 12:34:43 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[usb-c]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=64444</guid>

					<description><![CDATA[Want to capture video from your phone or console? You could just point a camera at the screen, but a more sensible way to do it is to capture the video directly via USB-C.  The good folks at Benfei have sent me another gadget to review! This is a USB-C Video/Audio capture dongle. Plug one end into a device and the other into your computer - it will show up as a USB video capture device.    Notice …]]></description>
										<content:encoded><![CDATA[<p>Want to capture video from your phone or console? You <em>could</em> just point a camera at the screen, but a more sensible way to do it is to capture the video directly via USB-C.</p>

<p>The good folks at Benfei have sent me another gadget to review! This is a <a href="https://amzn.to/47L0br2">USB-C Video/Audio capture</a> dongle. Plug one end into a device and the other into your computer - it will show up as a USB video capture device.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/11/Benfei-USB-C-Video.webp" alt="A long USB-C cable with a box in the middle." width="1024" height="722" class="aligncenter size-full wp-image-64497">

<p>Notice the extra USB socket there?</p>

<h2 id="usb-power"><a href="https://shkspr.mobi/blog/2025/11/gadget-review-benfei-usb-c-video-capture/#usb-power">USB Power</a></h2>

<p>One great thing about this device is that it has USB Power Delivery pass through. This means you can charge your device while grabbing video from it. That's more than a "nice to have" - the Nintendo Switch will refuse to output video over USB-C unless it is connected to a power supply.</p>

<p>The capture device claims to be able to pass through 100W - I don't have any devices which need that much power, but my <a href="https://shkspr.mobi/blog/2023/10/gadget-review-plugable-usb-c-voltage-amperage-meter-240w/">USB-C Power Meter</a> showed devices happily slurping down between 5W and 20W depending on the device I was using.</p>

<p>So how does it do?</p>

<h2 id="video-and-audio"><a href="https://shkspr.mobi/blog/2025/11/gadget-review-benfei-usb-c-video-capture/#video-and-audio">Video and Audio</a></h2>

<p>It is limited to 1080p @ 60Hz, which is good enough for most things.</p>

<p>Here's a short clip from the Nintendo Switch:</p>

<p></p><div style="width: 620px;" class="wp-video"><video class="wp-video-shortcode" id="video-64444-5" width="620" height="349" preload="metadata" controls="controls"><source type="video/mp4" src="https://shkspr.mobi/blog/wp-content/uploads/2025/11/Benfei-Switch.mp4?_=5"><a href="https://shkspr.mobi/blog/wp-content/uploads/2025/11/Benfei-Switch.mp4">https://shkspr.mobi/blog/wp-content/uploads/2025/11/Benfei-Switch.mp4</a></video></div><p></p>

<p>And here's a capture from my Android phone:</p>

<p></p><div style="width: 620px;" class="wp-video"><video class="wp-video-shortcode" id="video-64444-6" width="620" height="349" preload="metadata" controls="controls"><source type="video/mp4" src="https://shkspr.mobi/blog/wp-content/uploads/2025/11/Benfei-Android-Video.mp4?_=6"><a href="https://shkspr.mobi/blog/wp-content/uploads/2025/11/Benfei-Android-Video.mp4">https://shkspr.mobi/blog/wp-content/uploads/2025/11/Benfei-Android-Video.mp4</a></video></div><p></p>

<h2 id="linux"><a href="https://shkspr.mobi/blog/2025/11/gadget-review-benfei-usb-c-video-capture/#linux">Linux</a></h2>

<p>For the nerds amongst us, this shows up in <code>lsusb</code> as <code>345f:2130 MACROSILICON USB3 Video</code> which should be <a href="https://linux-hardware.org/?id=usb:345f-2130">well supported</a>.</p>

<p>OBS Studio was able to capture the video and audio input perfectly:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/11/OBS.webp" alt="The OBS software showing video from a console." width="1440" height="1002" class="aligncenter size-full wp-image-64496">

<p>It is the epitome of Plug &amp; Play. Shove one end into your device and plug the other end into your computer's USB-C port. That's it. Done. No software to install, no drivers to download, no switches to flip. There's also a handy adapter if you want to use a USB-A socket - although it will need to support USB 3 speeds.</p>

<h2 id="limitations"><a href="https://shkspr.mobi/blog/2025/11/gadget-review-benfei-usb-c-video-capture/#limitations">Limitations</a></h2>

<p>As with most HDMI devices, it will refuse to stream video protected by HDCP DRM. That means you <em>probably</em> can't stream your Netflix / Disney / Whatever subscription to your laptop.</p>

<p>It is limited to stereo sound. I couldn't convince the Nintendo Switch to output surround sound.</p>

<p>Obviously, it only works with devices which have USB-C <em>video</em> output. Modern Android and most hand-held consoles will work. Your PS5 won't.</p>

<p>So what about those devices without USB-C?</p>

<h2 id="bonus-hdmi-dongle"><a href="https://shkspr.mobi/blog/2025/11/gadget-review-benfei-usb-c-video-capture/#bonus-hdmi-dongle">Bonus HDMI Dongle!</a></h2>

<p>So you're a wannabe Twitch streamer, or you just want to capture something from your HDMI output? The good folks at Benfei also sent me their <a href="https://amzn.to/47uq1AG">HDMI Capture Dongle</a> to review.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/11/HDMI-capture.webp" alt="A short USB-C cable with an HDMI port." width="1024" height="768" class="aligncenter size-full wp-image-64500">

<p>There's absolutely nothing else to say about this one. It has the same internals - <code>345f:2130 MACROSILICON USB3 Video</code> - and works exactly the same.</p>

<p>Shove an HDMI cable in there and you're good to go,</p>

<h2 id="price"><a href="https://shkspr.mobi/blog/2025/11/gadget-review-benfei-usb-c-video-capture/#price">Price</a></h2>

<p>The USB-C to USB-C cable <a href="https://amzn.to/47L0br2">a surprisingly reasonable £15</a>.  If you need to capture video for presentations or streaming, it will do the job splendidly. The cable is long enough to drape from a machine to a source - and the Power Delivery is useful.</p>

<p>The HDMI capture is <a href="https://amzn.to/47uq1AG">only £12</a>. They both work identically well and are supported on Linux.</p>

<p>Highly recommended!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=64444&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/11/gadget-review-benfei-usb-c-video-capture/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		<enclosure url="https://shkspr.mobi/blog/wp-content/uploads/2025/11/Benfei-Switch.mp4" length="2811227" type="video/mp4" />
<enclosure url="https://shkspr.mobi/blog/wp-content/uploads/2025/11/Benfei-Android-Video.mp4" length="4090290" type="video/mp4" />

			</item>
		<item>
		<title><![CDATA[How to *actually* test your readme]]></title>
		<link>https://shkspr.mobi/blog/2025/10/how-to-actually-test-your-readme/</link>
					<comments>https://shkspr.mobi/blog/2025/10/how-to-actually-test-your-readme/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 07 Oct 2025 11:34:08 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[developers]]></category>
		<category><![CDATA[Free Software]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=62224</guid>

					<description><![CDATA[If you&#039;ve spent any time using Linux, you&#039;ll be used to installing software like this:  The README says to download from this link. Huh, I&#039;m not sure how to unarchive .tar.xz files - guess I&#039;ll search for that. Right, it says run setup.sh hmm, that doesn&#039;t work. Oh, I need to set the permissions. What was the chmod command again? OK, that&#039;s working. Wait, it needs sudo. Let me run that again.…]]></description>
										<content:encoded><![CDATA[<p>If you've spent any time using Linux, you'll be used to installing software like this:</p>

<blockquote><p>The README says to download from this link. Huh, I'm not sure how to unarchive .tar.xz files - guess I'll search for that. Right, it says run <code>setup.sh</code> hmm, that doesn't work. Oh, I need to set the permissions. What was the <code>chmod</code> command again? OK, that's working. Wait, it needs <code>sudo</code>. Let me run that again. Hang on, am I in the right directory? Here it goes. What, it crapped out. I don't have some random library - how the hell am I meant to install that? My distro has v21 but this requires &lt;=19. Ah, I also need to upgrade something which isn't supplied by repo. Nearly there, just need to compile this obscure project from SourceForge which was inexplicably installed on the original dev's machine and then I'll be good to go. Nope. Better raise an issue on GitHub. Oh, look, it is tomorrow.</p></blockquote>

<p>As a developer, you probably don't want to answer dozens of tickets complaining that users are frustrated with your work. You thought you made the README really clear and - hey! - it works on your machine.</p>

<p>There are various solutions to this problem - developers can release AppImages, or Snaps, or FlatPaks, or Docker or whatever. But that's a bit of stretch for a solo dev who is slinging out a little tool that they coded in their spare time. And, even those don't always work as seamlessly as you'd hope.</p>

<p>There's an easier solution:</p>

<ol>
<li>Follow the steps in your README</li>
<li>See if they work.</li>
<li>…</li>
<li>That's it.</li>
</ol>

<p>OK, that's a bit reductive! There are a million variables which go into a test - so I'm going to introduce you to a secret <em>zeroth</em> step.</p>

<ol start="0">
<li>Spin up a fresh Virtual Machine with a recent-ish distro.</li>
</ol>

<p>If you are a developer, your machine probably has a billion weird configurations and obscure libraries installed on it - things which <em>definitely</em> aren't on your users' machines. Having a box-fresh VM means than you are starting with a blank-slate. If, when following your README, you discover that the app doesn't install because of a missing dependency, you can adjust your README to include <code>apt install whatever</code>.</p>

<h2 id="ok-but-how"><a href="https://shkspr.mobi/blog/2025/10/how-to-actually-test-your-readme/#ok-but-how">OK, but how?</a></h2>

<p>Personally, I like <a href="https://flathub.org/apps/org.gnome.Boxes">Boxes</a> as it gives you a simple choice of VMs - but there are plenty of other Virtual Machine managers out there.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/07/OS-Selection.webp" alt="List of Linux OSes." width="801" height="728" class="aligncenter size-full wp-image-62227">

<p>Pick a standard OS that you like. I think the latest Ubuntu Server is pretty lightweight and is a good baseline for what people are likely to have. But feel free to pick something with a GUI or whatever suits your audience.</p>

<p>Once your VM is installed and set up for basic use, take a snapshot.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/07/revert.webp" alt="Pop up showing a snapshot of a virtual machine." width="692" height="628" class="aligncenter size-full wp-image-62228">

<p>Every time you want to test or re-test a README, revert back to the <em>original</em> state of your box. That way you won't have odd half-installed packages laying about.</p>

<p>Your next step is to think about how much hand-holding do you want to do?</p>

<p>For example, the default Debian doesn't ship with git. Does your README need to tell people to <code>sudo apt install git</code> and then walk them through configuring it so that they can <code>git clone</code> your repo?</p>

<p>Possibly! Who is your audience? If you've created a tool which is likely to be used by newbies who are just getting started with their first Raspberry Pi then, yeah, you probably will need to include that. Why? Because it will save you from receiving a lot of repeated questions and frustrated emails.</p>

<p>OK, but most developers will have <code>gcc</code> installed, right? Maybe! But it doesn't do any harm to include it in a long list of <code>apt get …</code> anyway, does it? Similarly, does everyone know how to upgrade to the very latest npm?</p>

<p>If your software is designed for people who are experienced computer touchers, don't fall into the trap of thinking that they know everything you do.  I find it best to assume people are intelligent but not experienced; it doesn't hurt to give <em>slightly</em> too much detail.</p>

<p>The best way to do this is to record <em>everything</em> you do after logging into the blank VM.</p>

<ol start="0">
<li>Restore the snapshot.</li>
<li>Log in.</li>
<li>Run all the commands you need to get your software working.</li>
<li>Once done, run <code>history -w history.txt</code>

<ul>
<li>That will print out <em>every</em> command you ran.</li>
</ul></li>
<li>Copy that text into your README.</li>
</ol>

<p>Hey presto! You now have README instructions which have been tested to work. Even on the most bare-bones machine, you can say that your README will allow the user to get started with your software with the minimum amount of head-scratching.</p>

<p>Now, this isn't foolproof. Maybe the user has an ancient operating system running on obsolete hardware which is constantly bombarded by cosmic rays. But at least this way your issues won't be clogged up by people saying their install failed because <code>lib-foobar</code> wasn't available or that <code>./configure</code> had fatal errors.</p>

<p>A great example is <a href="https://github.com/xiph/opus/blob/main/README">the Opus Codec README</a>.  I went into a fresh Ubuntu machine, followed the readme, ran the above history command, and got this:</p>

<pre><code class="language-_">sudo apt-get install git autoconf automake libtool gcc make
git clone https://gitlab.xiph.org/xiph/opus.git
cd opus
./autogen.sh
./configure
make
sudo make install
</code></pre>

<p>Everything worked! There was no missing step or having to dive into another README to figure out how to bind flarg 6.9 with schnorp-unstable.</p>

<p>So that's my plea to you, dear developer friend. Make sure your README contains both the necessary <em>and</em> sufficient information required to install your software. For your sake, as much as mine!</p>

<h2 id="wait-you-didnt-follow-your-own-advice"><a href="https://shkspr.mobi/blog/2025/10/how-to-actually-test-your-readme/#wait-you-didnt-follow-your-own-advice">Wait! You didn't follow your own advice!</a></h2>

<p>You're quite right. Feel free to send a pull request to correct this post - as I shall be doing with any unhelpful READMEs I find along the way.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=62224&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/10/how-to-actually-test-your-readme/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[A little oddity in the way curl deals with old dates]]></title>
		<link>https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/</link>
					<comments>https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 01 Sep 2025 11:34:48 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[time]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=63068</guid>

					<description><![CDATA[For boring technical reasons, computers think the world began on 1st of January 1970. To keep track of the future, they count the number of seconds since that momentous date.  So zero seconds represents midnight on that day.  So how do computers deal with dates before The Beatles&#039; Abbey Road was top of the UK album charts?  Negative numbers! Most modern computers can deal with dates far in the…]]></description>
										<content:encoded><![CDATA[<p>For boring technical reasons, computers think the world began on 1st of January 1970<sup id="fnref:who"><a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fn:who" class="footnote-ref" title="Although, who is to say it didn't? Were you there? Do you have proof? Maybe the Young Earth Creationists aren't ambitious enough?!" role="doc-noteref">0</a></sup>. To keep track of the future, they count the number of seconds since that momentous date.  So zero seconds represents midnight on that day<sup id="fnref:midnight"><a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fn:midnight" class="footnote-ref" title="Except! Psych! It doesn't! The UK was experimenting with year-round BST so there's actually an hour's difference. Time is hard™." role="doc-noteref">1</a></sup>.</p>

<p>So how do computers deal with dates <em>before</em> The Beatles' Abbey Road was top of the UK album<sup id="fnref:album"><a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fn:album" class="footnote-ref" title="Do not search for the number 1 single on that date. You'll give yourself a sad." role="doc-noteref">2</a></sup> charts?</p>

<p>Negative numbers! Most modern computers can deal with dates far in the past and, hopefully, far into the future. Again, for <a href="https://righteousit.com/2024/09/04/more-on-ext4-timestamps-and-timestomping/">boring technical reasons</a>, lots of computers can only save files with a date no earlier than 13th December 1901<sup id="fnref:book"><a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fn:book" class="footnote-ref" title="The music charts were less well-developed in 1901. But you could have read &quot;The Purple Cloud&quot; which is a brilliant early sci-fi novel." role="doc-noteref">3</a></sup>.</p>

<p>When you download a file from the Internet, the sending server can tell you when that file was last modified. That's useful if you only want to download the file if it has changed since you last got it.</p>

<p>It presents the date using <a href="https://www.rfc-editor.org/rfc/rfc1123">RFC 1123</a> format for reasons which are lost to the ages.</p>

<p><code>&lt; Last-Modified: Wed, 09 Oct 1940 16:45:49 +0100</code></p>

<p>Great!</p>

<p>If you use the venerable <code>wget</code> utility, it will happily save the file on your disk and tell you that is when it was created.</p>

<p>But what if you use <code>curl -OR</code> to download the file? The <code>-R</code> option says:</p>

<blockquote><p><a href="https://curl.se/docs/manpage.html#-R">Make curl attempt to figure out the timestamp of the remote file that is getting downloaded, and if that is available make the local file get that same timestamp. </a></p></blockquote>

<p>THIS IS A LIE!<sup id="fnref:lie"><a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fn:lie" class="footnote-ref" title="Everything you know is false! How deep does this conspiracy go!?!?" role="doc-noteref">4</a></sup></p>

<p>If curl sees a date with a negative time, it pretends that the past doesn't exist and that what you <em>really</em> wanted was to save the file with today's date and time.</p>

<p>Why does it do this?</p>

<p>I <em>think</em> it is because <a href="https://github.com/curl/curl/blob/f08ecdc586203026d1a81bd401486261f28848d3/src/tool_filetime.c#L89-L91">this code only checks for times ≥ 0</a>. Which, I guess, is pretty reasonable. There weren't <em>many</em> computers around before the 1970s<sup id="fnref:zero"><a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fn:zero" class="footnote-ref" title="Although, there were some. Not just the secret ones used to control the weather - but actual proper computers you could use to do maths!" role="doc-noteref">5</a></sup> so the chances of finding a file which predates disco are slim.</p>

<p>Should we storm the barricades and demand this temporal anomaly be rectified?<sup id="fnref:photon"><a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fn:photon" class="footnote-ref" title="Preferably by firing photon torpedoes. Or maybe ejecting the warp core. I'm not an engineer." role="doc-noteref">6</a></sup> Nah. I've <a href="https://github.com/curl/curl/discussions/18424">raised it as a discussion item on curl's GitHub</a>.</p>

<p>If you have strong opinions about this - please join in the discussion<sup id="fnref:help"><a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fn:help" class="footnote-ref" title="Or seek help from a mental health professional." role="doc-noteref">7</a></sup>.</p>

<div id="footnotes" role="doc-endnotes">
<hr>
<ol start="0">

<li id="fn:who">
<p>Although, who is to say it didn't? Were you there? Do you have proof? Maybe the Young Earth Creationists aren't ambitious enough?!&nbsp;<a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fnref:who" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:midnight">
<p>Except! Psych! It doesn't! <a href="https://www.shellscript.sh/examples/1970/">The UK was experimenting with year-round BST</a> so there's actually an hour's difference. Time is hard™.&nbsp;<a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fnref:midnight" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:album">
<p>Do not search for the number 1 <em>single</em> on that date. You'll give yourself a sad.&nbsp;<a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fnref:album" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:book">
<p>The music charts were less well-developed in 1901. But you could have read "<a href="https://en.wikipedia.org/wiki/The_Purple_Cloud">The Purple Cloud</a>" which is a brilliant early sci-fi novel.&nbsp;<a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fnref:book" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:lie">
<p>Everything you know is false! How deep does this conspiracy go!?!?&nbsp;<a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fnref:lie" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:zero">
<p>Although, there were <em>some</em>. Not just the secret ones used to control the weather - but actual proper computers you could use to do maths!&nbsp;<a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fnref:zero" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:photon">
<p>Preferably by firing photon torpedoes. Or maybe ejecting the warp core. I'm not an engineer.&nbsp;<a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fnref:photon" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:help">
<p>Or seek help from a mental health professional.&nbsp;<a href="https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/#fnref:help" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

</ol>
</div>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=63068&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/09/a-little-oddity-in-the-way-curl-deals-with-old-dates/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Reading NFC Passport Chips in Linux]]></title>
		<link>https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/</link>
					<comments>https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 24 Jun 2025 11:34:49 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[CyberSecurity]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nfc]]></category>
		<category><![CDATA[rfid]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=61546</guid>

					<description><![CDATA[For boring and totally not nefarious reasons, I want to read all the data contained in my passport&#039;s NFC chip using Linux. After a long and annoying search, I settled on roeften&#039;s pypassport.  I can now read all the passport information, including biometrics.  Table of ContentsBackgroundRecreating the MRZPython code to generate an MRZCan you read a cancelled passport?Cryptography and other…]]></description>
										<content:encoded><![CDATA[<p>For boring and totally not nefarious reasons, I want to read all the data contained in my passport's NFC chip using Linux. After a long and annoying search, I settled on <a href="https://github.com/roeften/pypassport">roeften's pypassport</a>.</p>

<p>I can now read all the passport information, including biometrics.</p>

<p></p><nav role="doc-toc"><menu><li><h2 id="table-of-contents"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#table-of-contents">Table of Contents</a></h2><menu><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#background">Background</a><menu><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#recreating-the-mrz">Recreating the MRZ</a><menu><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#python-code-to-generate-an-mrz">Python code to generate an MRZ</a></li></menu></li></menu></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#can-you-read-a-cancelled-passport">Can you read a cancelled passport?</a></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#cryptography-and-other-security">Cryptography and other security</a></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#can-you-brute-force-a-passport">Can you brute-force a passport?</a><menu><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#is-it-worth-brute-forcing-a-password">Is it worth brute-forcing a password?</a></li></menu></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#installing">Installing</a></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#getting-structured-data">Getting structured data</a><menu><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#saving-the-image">Saving the image</a></li></menu></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#what-didnt-work">What didn't work</a><menu><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#mrtdreader">mrtdreader</a></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#jean-francois-houzards-and-olivier-rogers-pypassport">Jean-Francois Houzard's and Olivier Roger's pyPassport</a></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#beaujeans-pypassport">beaujean's pyPassport</a></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#d-logic">d-Logic</a></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#android-reader">Android reader</a></li></menu></li><li><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#is-it-worth-it">Is it worth it?</a></li></menu></li></menu></nav><p></p>

<h2 id="background"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#background">Background</a></h2>

<p>The NFC chip in a passport is protected by a password. The password is printed on the inside of the physical passport. As well as needing to be physically close to the passport for NFC to work<sup id="fnref:long"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fn:long" class="footnote-ref" title="There are some commercially available long range readers - up to 15cm! I've no doubt some clever engineer has made a some high-powered radio device which can read things from a mile away using a…" role="doc-noteref">0</a></sup>, you also need to be able to see the password. The password is printed in the "Machine Readable Zone" (MRZ) - which is why some border guards will swipe your passport through a reader before scanning the chip; they need the password and don't want to type it in.</p>

<p>I had a small problem though.  I'm using my old passport<sup id="fnref:old"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fn:old" class="footnote-ref" title="I'm not dumb enough to do this stuff on a live passport!" role="doc-noteref">1</a></sup> which <a href="https://www.gov.uk/government/publications/cancellation-of-passports/cancelling-british-passports-accessible#cancelling-epassport-version-2">has been cancelled</a>.  Cancelling isn't just about revoking the document. It is also physically altered:</p>

<blockquote><p>Cut off the bottom left hand corner of the personal details page, making sure you cut the MRZ on the corner opposite the photo.</p></blockquote>

<p>So a chunk of the MRZ is missing! Oh no! Whatever can we do!?</p>

<h3 id="recreating-the-mrz"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#recreating-the-mrz">Recreating the MRZ</a></h3>

<p>The password is made up of three pieces of data:</p>

<ol>
<li>Passport Number (Letters and Numbers)</li>
<li>Date of Birth (YYMMDD)</li>
<li>Expiry Date (YYMMDD)</li>
</ol>

<p>Each piece <em>also</em> has a checksum. This calculation is defined in Appendix A to <a href="https://www.icao.int/publications/Documents/9303_p3_cons_en.pdf">Part 3 of Document 9303</a>.</p>

<p>Oh, and there's a checksum for the entire string. It's this final checksum which is cut off when the passport cover is snipped.</p>

<p>The final password is: <code>Number Number-checksum DOB DOB-checksum Expiry Expiry-checkum checksum-of-previous-digits</code></p>

<h4 id="python-code-to-generate-an-mrz"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#python-code-to-generate-an-mrz">Python code to generate an MRZ</a></h4>

<p>If you know the passport number, date of birth, and expiry date, you can generate your own Machine Readable Zone - this acts as the password for the NFC chip.</p>

<pre><code class="language-python">def calculateChecksum( value ):
    weighting = [7,3,1]
    characterWeight = {
        '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7,  
        '8': 8, '9': 9, '&lt;': 0, 'A':10, 'B':11, 'C':12, 'D':13, 'E':14, 
        'F':15, 'G':16, 'H':17, 'I':18, 'J':19, 'K':20, 'L':21, 'M':22, 
        'N':23, 'O':24, 'P':25, 'Q':26, 'R':27, 'S':28, 'T':29, 'U':30, 
        'V':31, 'W':32, 'X':33, 'Y':34, 'Z':35
    }
    counter = 0
    result = 0
    for x in value:
        result += characterWeight[str(x)] * weighting[counter%3]
        counter += 1
    return str(result%10)

def calculateMRZ( passportNumber, DOB, expiry ):
    """
    DOB and expiry are formatted as YYMMDD
    """
    passportCheck = calculateChecksum( passportNumber )
    DOBCheck      = calculateChecksum( DOB )
    expiryCheck   = calculateChecksum( expiry )
    mrzNumber  = passportNumber + passportCheck + DOB + DOBCheck + expiry + expiryCheck
    mrzCheck = calculateChecksum( mrzNumber ).zfill(2)
    mrz =  passportNumber + passportCheck + "XXX" + DOB + DOBCheck + "X" + expiry + expiryCheck + "&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;" + mrzCheck
    return mrz

print( calculateMRZ("123456789", "841213", "220229") )
</code></pre>

<h2 id="can-you-read-a-cancelled-passport"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#can-you-read-a-cancelled-passport">Can you read a cancelled passport?</a></h2>

<p>I would have thought that cutting the cover of the passport would destroy the antenna inside it. But, going back to <a href="https://www.gov.uk/government/publications/cancellation-of-passports/cancelling-british-passports-accessible#cancelling-epassport-version-2">the UK guidance</a>:</p>

<blockquote><p>You must not cut the back cover on the ePassport</p></blockquote>

<p>Ah! That's where the NFC chip is. I presume this is so that cancelled passports can still be verified for authenticity.</p>

<h2 id="cryptography-and-other-security"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#cryptography-and-other-security">Cryptography and other security</a></h2>

<p>The security is, thankfully, all fairly standard Public Key Cryptography - <a href="https://www.icao.int/publications/Documents/9303_p11_cons_en.pdf">9303 part 11</a> explains it in <em>excruciating</em> levels of detail.</p>

<p>One thing I found curious - because the chip has no timer, it cannot know how often it is being read. You could bombard it with thousands of password attempts and not get locked out.  Indeed, the specification says:</p>

<blockquote><p>the success probability of the attacker is given by the time the attacker has access to the IC, the duration of a single attempt to guess the password, and the entropy of the passport.</p></blockquote>

<h2 id="can-you-brute-force-a-passport"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#can-you-brute-force-a-passport">Can you brute-force a passport?</a></h2>

<p>Wellllll… maybeeeee…?</p>

<p>Passports are generally valid for only 10 years. So that's 36,525 possible expiry dates.</p>

<p>Passport holders are generally under 100 years old. So that's 3,652,500 possible dates of birth.</p>

<p>That's already 133,407,562,500 attempts - and we haven't even got on to the 1E24 possible passport numbers!</p>

<p>In my experiments, sending an incorrect but valid MRZ results in the chip returning "Security status not satisfied (0x6982)" in a very short space of time. Usually less than a second.</p>

<p>But sending that incorrect attempt seemed to introduce a delay in the next response - by a few seconds. Sending the correct MRZ seemed to reset this and let the chip be read instantly.</p>

<p>So, if you knew the target's passport number and birthday, brute forcing the expiry date would take a couple of days. Not instant, but not impossible.</p>

<p>Most <a href="https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.pdf">commercial NFC chips support 100,000 writes</a> with no limit for the number of reads. Some also have a 24 bit read counter which increments after every read attempt. After 16 million reads, the counter doesn't increment. It <em>could</em> be possible for a chip to self-destruct after a specific number of reads - but I've no evidence that passport chips do that.</p>

<h3 id="is-it-worth-brute-forcing-a-password"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#is-it-worth-brute-forcing-a-password">Is it <em>worth</em> brute-forcing a password?</a></h3>

<p>If you were to brute-force the MRZ, you would discover the passport-holder's date of birth.  You would also get:</p>

<ul>
<li>A digital copy of their photo,</li>
<li>Their full name,</li>
<li>Their sex<sup id="fnref:sex"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fn:sex" class="footnote-ref" title="Sex is complicated. But ICAO allow for &quot;F for female, M for male, or X for unspecified&quot;." role="doc-noteref">2</a></sup>,</li>
<li>The country which issued their passport, and</li>
<li>Their nationality.</li>
</ul>

<p>All of that is something which you can see from looking at the passport. So there's little value in attempting to read it electronically.</p>

<h2 id="installing"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#installing">Installing</a></h2>

<p>As mentioned, I'm using <a href="https://github.com/roeften/pypassport">https://github.com/roeften/pypassport</a></p>

<p>The only library I needed to install was <a href="https://pypi.org/project/pyasn1/">pyasn1</a> using <code>pip3 install pyasn1</code> - your setup may vary.</p>

<p>Download PyPassport. In the same directory, you can create a test Python file to see if the passport can be read. Here's what it needs to contain:</p>

<pre><code class="language-python">from pypassport import epassport, reader

#   Replace this MRZ with the one from your passport
MRZ = "1234567897XXX8412139X2202299&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;04"

def trace(name, msg):
    if name == "EPassport":
        print(name + ": " + msg)

r = reader.ReaderManager().waitForCard()

ep = epassport.EPassport(r, MRZ)
ep.register(trace)
ep.readPassport()
</code></pre>

<p>Plug in your NFC reader, place your passport on it, run the above code.  If it works, it will spit out a lot of debug information, including all the data it can find on the passport.</p>

<h2 id="getting-structured-data"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#getting-structured-data">Getting structured data</a></h2>

<p>The structure of the passport data is a little convoluted.  <a href="https://www.icao.int/publications/Documents/9303_p10_cons_en.pdf">The specification</a> puts data into different "Data Groups" - each with its own ID.</p>

<p>By running:</p>

<pre><code class="language-python">ep.keys()
</code></pre>

<p>You can see which Data Groups are available. In my case, <code>['60', '61', '75', '77']</code></p>

<ul>
<li><code>60</code> is the common area which contains some metadata. Nothing interesting there.</li>
<li><code>61</code> is DG1 - the full MRZ. This contains the holder's name, sex, nationality, etc.</li>
<li><code>77</code> is the Document Security Object - this was empty for me.</li>
<li><code>75</code> is DG2 to DG4 Biometric Templates - this contains the image and other metadata.</li>
</ul>

<p>Dumping the biometrics - <code>print( ep["75"] )</code> - gives these interesting pieces of metadata:</p>

<pre><code class="language-_">'83': '20190311201345',
'meta': {   'Expression': 'Unspecified',
            'EyeColour' : 'Unspecified',
            'FaceImageBlockLength': 19286,
            'FaceImageType': 'Basic',
            'FeatureMask': '000000',
            'FeaturePoint': {0: {'FeaturePointCode': 'C1',
                                'FeatureType': '01',
                                'HorizontalPosition': 249,
                                'Reserved': '0000',
                                'VerticalPosition': 216},
                            1: {'FeaturePointCode': 'C2',
                                'FeatureType': '01',
                                'HorizontalPosition': 141,
                                'Reserved': '0000',
                                'VerticalPosition': 214}},
            'Features': {},
            'Gender': 'Unspecified',
            'HairColour': 'Unspecified',
            'ImageColourSpace': 'RGB24',
            'ImageDataType': 'JPEG',
            'ImageDeviceType': 0,
            'ImageHeight': 481,
            'ImageQuality': 'Unspecified',
            'ImageSourceType': 'Static Scan',
            'ImageWidth': 385,
            'LengthOfRecord': 19300,
            'NumberOfFacialImages': 1,
            'NumberOfFeaturePoint': 2,
            'PoseAngle': '0600B5',
            'PoseAngleUncertainty': '000000',
            'VersionNumber': b'010'
        }
</code></pre>

<p>If I understand <a href="https://www.icao.int/security/mrtd/siteassets/pages/technical-reports/tr%20-%20rf%20and%20protocol%20testing%20part%204%20v2.10.pdf">the testing document</a> - the "Feature Points" are the middle of the eyes.  Interesting to see that gender (not sex!) and hair colour are also able to be recorded. The "PoseAngle" represents the <a href="https://www.icao.int/Security/FAL/TRIP/Documents/TR%20-%20Portrait%20Quality%20v1.0.pdf">pitch, yaw, and roll</a> of the face.</p>

<h3 id="saving-the-image"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#saving-the-image">Saving the image</a></h3>

<p>Passport images are saved either with JPEG or with <a href="https://www.icao.int/Security/FAL/TRIP/Documents/TR%20-%20Portrait%20Quality%20v1.0.pdf">JPEG2000 encoding</a>. Given the extremely limited memory available photos are small and highly compressed. Mine was a mere 19KB.</p>

<p>To save the image, grab the bytes and plonk them onto disk:</p>

<pre><code class="language-python">photo = ep["75"]["A1"]["5F2E"]
with open( "photo.jpg", "wb" ) as f:
   f.write( photo )
</code></pre>

<p>As expected, the "FeaturePoints" co-ordinates corresponded roughly to the centre of my eyes. Nifty!</p>

<h2 id="what-didnt-work"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#what-didnt-work">What didn't work</a></h2>

<p>I tried a few different tools. Listed here so you don't make the same mistakes as me!</p>

<h3 id="mrtdreader"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#mrtdreader">mrtdreader</a></h3>

<p>The venerable <a href="https://github.com/rubund/mrtdreader">mrtdreader</a>. My NFC device beeped, then mrtdreader said "No NFC device found."</p>

<p>I think this is because <a href="https://github.com/nfc-tools/libnfc/issues/719">NFC Tools haven't been updated in ages</a>.</p>

<h3 id="jean-francois-houzards-and-olivier-rogers-pypassport"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#jean-francois-houzards-and-olivier-rogers-pypassport">Jean-Francois Houzard's and Olivier Roger's pyPassport</a></h3>

<p>I looked at <a href="https://code.google.com/archive/p/pypassport/">pyPassport</a> but it is only available for Python 2.</p>

<h3 id="beaujeans-pypassport"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#beaujeans-pypassport">beaujean's pyPassport</a></h3>

<p>This <a href="https://github.com/beaujeant/pypassport">pypassport</a> only checks if a passport is resistant to specific security vulnerabilities.</p>

<h3 id="d-logic"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#d-logic">d-Logic</a></h3>

<p><a href="https://www.d-logic.com/nfc-rfid-reader-sdk/software/epassport-reading/">Digital Logic's ePassport software</a> only works with their hardware readers.</p>

<h3 id="android-reader"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#android-reader">Android reader</a></h3>

<p><a href="https://github.com/tananaev/passport-reader">tananaev's passport-reader</a> - works perfectly on Android. So I knew my passport chip was readable - but the app won't run on Linux.</p>

<h2 id="is-it-worth-it"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#is-it-worth-it">Is it worth it?</a></h2>

<p>Yeah, I reckon so! Realistically, you aren't going to be able to crack the MRZ to read someone's passport. But if you need to gather personal information<sup id="fnref:gdpr"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fn:gdpr" class="footnote-ref" title="Under the auspices of GDPR, of course!" role="doc-noteref">3</a></sup>, it's perfectly possible to do so quickly from a passport.</p>

<p>The MRZ is a <em>Machine Readable</em> Zone - so it is fairly simple to OCR the text and then pass that to your NFC reader.</p>

<p>And even if the MRZ is gone, you can reconstruct it from the data printed on the passport.</p>

<p>Of course, this won't be able to detect fraudulent passports. It doesn't check against a database to see if it has been revoked<sup id="fnref:interpol"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fn:interpol" class="footnote-ref" title="Nor does it check if the holder is on some Interpol list." role="doc-noteref">4</a></sup>. I don't think it will detect any cryptographic anomalies.</p>

<p>But if you just want to see what's on your travel documents, it works perfectly.</p>

<div id="footnotes" role="doc-endnotes">
<hr>
<ol start="0">

<li id="fn:long">
<p>There are some <a href="https://www.shopnfc.com/en/nfc-readers-writers/300-nfc-xl-reader-long-range-hf-reader.html">commercially available long range readers</a> - up to 15cm! I've no doubt some clever engineer has made a some high-powered radio device which can read things from a mile away using a <a href="https://www.makeuseof.com/tag/how-to-make-a-wifi-antenna-out-of-a-pringles-can-nb/">Pringle's tube</a>. Of note, the <a href="https://www.icao.int/publications/Documents/9303_p11_cons_en.pdf">ICAO guidance</a> says:</p>

<blockquote><p>the unencrypted communication between a contactless IC and a reader can be eavesdropped within a distance of several metres.</p></blockquote>

<p><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fnref:long" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:old">
<p>I'm not dumb enough to do this stuff on a <em>live</em> passport!&nbsp;<a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fnref:old" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:sex">
<p>Sex is complicated<sup id="fnref:giggle"><a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fn:giggle" class="footnote-ref" title="Stop giggling at the back!" role="doc-noteref">5</a></sup>. But ICAO allow for "<a href="https://www.icao.int/publications/Documents/9303_p4_cons_en.pdf">F for female, M for male, or X for unspecified</a>".&nbsp;<a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fnref:sex" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:gdpr">
<p>Under the auspices of GDPR, of course!&nbsp;<a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fnref:gdpr" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:interpol">
<p>Nor does it check if the holder is on some Interpol list.&nbsp;<a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fnref:interpol" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:giggle">
<p>Stop giggling at the back!&nbsp;<a href="https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/#fnref:giggle" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

</ol>
</div>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=61546&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/06/reading-nfc-passport-chips-in-linux/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Convert Shotwell Photo Metadata to Digikam Metadata]]></title>
		<link>https://shkspr.mobi/blog/2025/06/convert-shotwell-photo-metadata-to-digikam-metadata/</link>
					<comments>https://shkspr.mobi/blog/2025/06/convert-shotwell-photo-metadata-to-digikam-metadata/#respond</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 20 Jun 2025 11:34:37 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=61338</guid>

					<description><![CDATA[Mostly notes to myself.  Shotwell stores most of its information in a database. Which I lost. Because I&#039;m an idiot.  But a bunch of metadata is also stored in the image&#039;s EXIF metadata!  Most importantly is the &#34;Original File Name&#34; which should become the &#34;Description&#34; in DigiKam. Unfortunately, there&#039;s no way to copy those values automatically on import.  So here&#039;s a one-liner which will read…]]></description>
										<content:encoded><![CDATA[<p>Mostly notes to myself.</p>

<p>Shotwell stores most of its information in a database. Which I lost. Because I'm an idiot.</p>

<p>But a bunch of metadata is <em>also</em> stored in the image's EXIF metadata!</p>

<p>Most importantly is the "Original File Name" which should become the "Description" in DigiKam. Unfortunately, there's no way to copy those values automatically on import.</p>

<p>So here's a one-liner which will read the "Original File Name" and store it in the "Title" EXIF - ready for DigiKam to parse!</p>

<pre><code class="language-bash">exiftool "-XMP-dc:Title&lt;XMP-getty:OriginalFileName" whatever.jpg
</code></pre>

<p>If you want to make sure any existing Title isn't overwritten, use:</p>

<pre><code class="language-bash">exiftool "-XMP-dc:Title&lt;${XMP-getty:OriginalFileName}" -if "not defined $XMP-dc:Title" whatever.jpg
</code></pre>

<p>Finally, to do it recursively, across all files:</p>

<pre><code class="language-bash">exiftool -r "-XMP-dc:Title&lt;${XMP-getty:OriginalFileName}" -if "not defined $XMP-dc:Title" /path/to/images
</code></pre>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=61338&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/06/convert-shotwell-photo-metadata-to-digikam-metadata/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Opening Compact File Set (CFS)  files in Linux]]></title>
		<link>https://shkspr.mobi/blog/2024/10/opening-compact-file-set-cfs-files-in-linux/</link>
					<comments>https://shkspr.mobi/blog/2024/10/opening-compact-file-set-cfs-files-in-linux/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 24 Oct 2024 11:34:13 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[DICOM]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=52251</guid>

					<description><![CDATA[I was sent some medical images in a password-protected CFS file. Here&#039;s how to open them in Linux.  You can&#039;t.  OK, that&#039;s a bit of an exaggeration.  It&#039;s complex, but here&#039;s how to do it.  The Linux software for the Compact File Set hasn&#039;t been updated in years and only works with ancient versions of Linux.  Here&#039;s how to temporarily install an old version, install the software, and then…]]></description>
										<content:encoded><![CDATA[<p>I was sent some medical images in a password-protected CFS file. Here's how to open them in Linux.</p>

<p>You can't.</p>

<p>OK, that's a bit of an exaggeration.  It's complex, but here's how to do it.</p>

<p>The <a href="https://pismotec.com/cfs/">Linux software for the Compact File Set</a> hasn't been updated in years and only works with <em>ancient</em> versions of Linux.  Here's how to temporarily install an old version, install the software, and then liberate your files.</p>

<ol start="0">
<li>Install VirtualBox or your favourite Virtual Machine.</li>
<li>Install <a href="https://www.releases.ubuntu.com/bionic/">Ubuntu 18.04.6 LTS (Bionic Beaver)</a></li>
<li>Once you're in Ubuntu, run <code>sudo apt install make gcc</code></li>
<li>Download the <a href="https://pismotec.com/download/">Pismo File System Redirector build 23X</a> for Linux.</li>
<li>Run <code>chmod +x fsr-23X-lin.run</code></li>
<li>Extract it with <code>runstub_folder=. ./fsr-23X-lin.run</code></li>
<li>Go into the folder it created <code>cd fsr-23X-lin/</code></li>
<li>Install with <code>sudo ./fsrcmd install</code></li>
<li>Go back to the location where you downloaded the files <code>cd ..</code></li>
<li>Downloand the <a href="https://pismotec.com/download/pfm-23X-lin.run">Pismo File Mount build 23X</a></li>
<li>Run <code>chmod +x pfm-23X-lin.run</code></li>
<li>Run <code>sudo ./pfm-23X-lin.run install</code></li>
<li>Mount the file with <code>pfm mount YourFile.cfs</code></li>
<li>Type the file's password (not your login password)</li>
<li>Open your file explorer, you should see the folder mounted with the files ready to copy off.</li>
</ol>

<p>If that doesn't work, there is an alternative.</p>

<ol>
<li>Download an install <a href="https://pismotec.com/download/pfm-23X-lin.run">Pismo File Mount build 23X</a> as above.</li>
<li>That installs a helper app called <code>ptcfs</code></li>
<li>Run <code>ptcfs extract YourFile.cfs</code> and all the contents should be unpacked.</li>
</ol>

<p>Thanks to the NHS for supplying my medical files free of charge. But why did they have to use this weird and non-standard file format? Luckily the medical images are in DICOM format, so I can 3D print my brains.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=52251&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/10/opening-compact-file-set-cfs-files-in-linux/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Game Review - World of Goo 2 for Linux ★★★★⯪]]></title>
		<link>https://shkspr.mobi/blog/2024/08/game-review-world-of-goo-2-for-linux/</link>
					<comments>https://shkspr.mobi/blog/2024/08/game-review-world-of-goo-2-for-linux/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 07 Aug 2024 11:34:48 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Game Review]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=51254</guid>

					<description><![CDATA[Remember World of Goo? The hit game that you loved on the Nintendo Wii?  It was all the rage in 2009:  .social-embed{all:unset;display:block;}.social-embed * {all:unset;display:revert;}.social-embed::after{all:unset;}.social-embed::before{all:unset;}blockquote:not(*){all:unset;}.social-embed a{cursor:pointer;}blockquote.social-embed{box-sizing:border-box;border:.5px…]]></description>
										<content:encoded><![CDATA[<p>Remember World of Goo? The hit game that you loved on the Nintendo Wii?  It was all the rage in 2009:</p>

<style>.social-embed{all:unset;display:block;}.social-embed * {all:unset;display:revert;}.social-embed::after{all:unset;}.social-embed::before{all:unset;}blockquote:not(*){all:unset;}.social-embed a{cursor:pointer;}blockquote.social-embed{box-sizing:border-box;border:.5px solid;width:550px;max-width:100%;font-family:sans-serif;margin:auto;margin-bottom:.5em;padding:1em;border-radius:1em;background-color:#FFF;color:#000;display:block;}.social-embed-header{display:flex;justify-content:space-between;}.social-embed-user{display:flex;position:relative;align-items:center;text-decoration:none;color:inherit;}.social-embed-avatar{width:3em;height:3em;margin-right:.5em;}.social-embed-avatar-circle{border-radius:50%;}.social-embed-avatar-square{border-radius:5%;}.social-embed-user-names-name{display:flex;align-items:center;font-weight:bold;margin:0;}.social-embed-text{margin-top:.5em;}.social-embed-footer{display:flex;align-items:center;justify-content:space-between;}.social-embed-logo{width:3em;}.social-embed-hr{border:.1px solid;margin:.5em 0 .5em 0;}.social-embed-meta{text-decoration:none !important;color:unset !important;}.social-embed-reply{display:block;}.social-embed-text a, .social-embed-footer time{color:blue;text-decoration:underline;}.social-embed-media, .social-embed-video{border-radius:1em;max-width:100%;}.social-embed-reply{font-size:.75em;display:block;}.social-embed-meter{width:100%;background:#0005;}</style>

<blockquote class="social-embed" id="social-embed-1290883165" lang="en"><header class="social-embed-header"><a href="https://twitter.com/edent" class="social-embed-user"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt=""><div class="social-embed-user-names"><p class="social-embed-user-names-name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCmFyaWEtbGFiZWw9IlR3aXR0ZXIiIHJvbGU9ImltZyIKdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoCmQ9Im0wIDBINTEyVjUxMkgwIgpmaWxsPSIjZmZmIi8+PHBhdGggZmlsbD0iIzFkOWJmMCIgZD0ibTQ1OCAxNDBxLTIzIDEwLTQ1IDEyIDI1LTE1IDM0LTQzLTI0IDE0LTUwIDE5YTc5IDc5IDAgMDAtMTM1IDcycS0xMDEtNy0xNjMtODNhODAgODAgMCAwMDI0IDEwNnEtMTcgMC0zNi0xMHMtMyA2MiA2NCA3OXEtMTkgNS0zNiAxczE1IDUzIDc0IDU1cS01MCA0MC0xMTcgMzNhMjI0IDIyNCAwIDAwMzQ2LTIwMHEyMy0xNiA0MC00MSIvPjwvc3ZnPg=="></header><section class="social-embed-text">Ah. I appear to have spent the majority of the night playing World Of Goo. What an addictive little game.</section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/1290883165" aria-label="1 likes" class="social-embed-meta">❤️ 1</a><a href="https://twitter.com/edent/status/1290883165" aria-label="0 replies" class="social-embed-meta">💬 0</a><a href="https://twitter.com/edent/status/1290883165" aria-label="0 retweets" class="social-embed-meta">♻️ 0</a><a href="https://twitter.com/edent/status/1290883165"><time datetime="2009-03-07T00:16:18.000Z">00:16 - Sat 07 March 2009</time></a></footer></blockquote>

<p>Fifteen years later... and I spent all night playing the sequel!</p>

<p>Yup! World of Goo is back, baby!  And it is just as good as you remember it.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/08/WoG2-puzzle-fs8.png" alt="Screenshot from World of Goo 2. A puzzle with Goo balls." width="800" height="500" class="aligncenter size-full wp-image-51263">

<p>In truth, there's nothing much which has changed. There are a few new Goo types, but the puzzles are all ostensibly the same - build a structure using limited resources. Use lots of triangles.</p>

<p>The art is gorgeous, the story is snarky, the puzzles are all solvable with various degrees of frustration. If you haven't played the original, you probably should - it's only an extra $10 in a bundle.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/08/WoG2-sign-fs8.png" alt="Screenshot from World of Goo 2. A sign says &quot;This must be one of those responsible new sustainability initiatives.&quot;" width="800" height="500" class="aligncenter size-full wp-image-51262">

<p>There are various challenges for every level - which does give it some replayability.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/08/WoG2-challenges-fs8.png" alt="Screenshot from World of Goo 2. Screen showing how many balls needed to complete a challenge." width="800" height="500" class="aligncenter size-full wp-image-51264">

<p>The soundtrack is delightful, the Goo are a silly mix of Lemmings and Minions, and the graphics are gorgeous.  Chapter 4 is... different. I liked it - but I didn't think the voice acting was particularly good.</p>

<p>Perhaps it is a little short, and perhaps it isn't much more than an expansion pack of the original. But, you know what? I was just happy to be transported back to 2009.</p>

<p>There's no microtransaction or lootboxes. No online gameplay - so no tweens screaming obscenities at you. Just pure gaming fun.</p>

<p>It isn't the longest game in the world. It took me about 13 hours - which included about an hour getting stuck on one (optional) level before caving and looking for a walkthrough..</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/08/WoG2-100-13-hr-fs8.png" alt="Screenshot from World of Goo 2. Screen showing 100% complete in 13 hours." width="800" height="500" class="aligncenter size-full wp-image-51265">

<h2 id="linux-instructions"><a href="https://shkspr.mobi/blog/2024/08/game-review-world-of-goo-2-for-linux/#linux-instructions">Linux Instructions</a></h2>

<p>World of Goo 2 is provided as a DRM-free AppImage file. Getting it working on Pop_OS was quite tricky:</p>

<ol>
<li>Double click the file to launch it.</li>
<li>Play the game.</li>
</ol>

<p>Oh.</p>

<p>If you're running something more esoteric, you'll probably need to sacrifice a chicken on the command line.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=51254&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/08/game-review-world-of-goo-2-for-linux/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Review: Framework 16 Laptop ★★★★⯪]]></title>
		<link>https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/</link>
					<comments>https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 08 Jun 2024 11:34:11 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[laptop]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[pop_os]]></category>
		<category><![CDATA[review]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=50749</guid>

					<description><![CDATA[Several years ago, I purchased a Clevo N151CU laptop with the idea that I&#039;d gradually upgrade the RAM, storage, and other bits. After my keyboard failed, I found it difficult to find replacement parts. The whole point of the Framework laptop is that it is specifically designed to be modular. It come in kit form, is easy to disassemble, and is (reasonably) well supported by an ecosystem of…]]></description>
										<content:encoded><![CDATA[<p>Several years ago, I purchased a <a href="https://shkspr.mobi/blog/2020/05/review-clevo-n151cu-lafite-iv-system76-darter-pro-entroware-proteus/">Clevo N151CU laptop</a> with the idea that I'd gradually upgrade the RAM, storage, and other bits. After my keyboard failed, <a href="https://shkspr.mobi/blog/2023/05/replacing-the-keyboard-on-the-clevo-n151cu-lafite-iv-system76-darter-pro-entroware-proteus/">I found it difficult to find replacement parts</a>. The whole point of the Framework laptop is that it is <em>specifically</em> designed to be modular. It come in kit form, is easy to disassemble, and is (reasonably) well supported by an ecosystem of manufacturers and makers.</p>

<p>I splashed out on the larger Framework 16. Again, I only bought one stick of RAM (32GB) so I can buy more when the price falls. Similarly, I only got a modest 500GB SSD, and I didn't bother with a super-premium CPU or extra graphics card. Total cost with all the gubbin was close to £1,700.</p>

<p>So here's a quick review: it's really good.</p>

<p>OK, here's a slightly longer review:</p>

<h2 id="set-up"><a href="https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/#set-up">Set Up</a></h2>

<p><a href="https://guides.frame.work/Guide/Framework+Laptop+16+DIY+Edition+Quick+Start+Guide/270">The setup guide</a> is beautifully designed. It has text <em>and</em> video to show you exactly how things work. All the screws are numbered, and are tackled in order. They all use the same (supplied) torx screwdriver. Oh, and the main body screws are attached, so they won't go flying.</p>

<p><img src="/blog/wp-content/uploads/2024/06/interior.jpg" alt="Numbered screws." class="aligncenter"></p>

<p>Removing the case, fitting the bits, and putting it back together was a breeze.</p>

<p><img src="/blog/wp-content/uploads/2024/06/guts.jpg" alt="Guts of a computer." class="aligncenter"></p>

<p>The BIOS / UEFI is an ugly pig of an interface. No worse than any other laptop, but really detracts from the quality of the product.</p>

<p>There was <a href="https://knowledgebase.frame.work/en_us/framework-laptop-16-bios-and-driver-releases-BkeqkVovp">a BIOS update</a> which was easy enough to apply - unzip it onto a USB drive, shove it in, wait.</p>

<p><img src="/blog/wp-content/uploads/2024/06/UEFI-update.jpg" alt="BIOS update screen" class="aligncenter"></p>

<p>Installing Pop_OS Linux was simple - although you do need to disable "Secure Boot" in the UEFI.</p>

<p>Everything worked without needing to futz about. WiFi, sound, keyboard back light, Bluetooth, camera. Once I <a href="https://www.hashbangcode.com/article/using-fingerprint-scanner-pop-os-2204">installed fprint</a> I was able to use the fingerprint reader to log in!</p>

<p>I got 4 USB-C expansion ports and, reluctantly, two USB-A for legacy devices. I didn't bother with HDMI or Ethernet - I have <a href="https://shkspr.mobi/blog/2024/01/review-another-usb-c-hub-from-mokin-14-in-1/">USB-C hubs</a>. To the future! The expansion ports slide in easily and can be locked in place. They are annoyingly small though.</p>

<h2 id="usage-and-tweaking"><a href="https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/#usage-and-tweaking">Usage and tweaking</a></h2>

<p>The screen supports 165Hz. That's bonkers. Yes, it does look gorgeous, but it probably eats battery life. So I set it back down to 60Hz.</p>

<p>The screen is beautifully tall - with a 16:10 aspect ratio. The resolution is 2560x1600 which, again, is probably <em>too</em> good! Everything looks crisp and gorgeous - but <em>tiny</em>. I used Wayland's fractional scaling and set it to 150%, I also boosted some of the fonts.</p>

<p>Sound is strong - for a laptop. Bass was just enough to feel it in my legs, voices were clear, there was no obvious clipping or distortion.  But, it is only a laptop. It isn't going to drown out the neighbours or deafen you.</p>

<p>The trackpad is geneously large and very responsive. It worked with multi-finger gestures and has a pleasing click to it.</p>

<h2 id="keyboard"><a href="https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/#keyboard">Keyboard</a></h2>

<p>The en-GB keyboard and numpad are great - but they're a different layout to my old one which makes my tired old brain a little confused. I don't get why insert / del share a key.</p>

<p><img src="/blog/wp-content/uploads/2024/06/keyboard.jpg" alt="Photo of the keyboard. The numpad is unlit but the main keyboard is illuminated." class="aligncenter"></p>

<p>Other oddities:</p>

<ul>
<li>There's no right context menu key:</li>
<li>The backlight is only a single colour (white) and only has 4 levels of brightness including off.</li>
<li>The <a href="https://community.frame.work/t/solved-how-to-disable-numpad-backlight/45568">numpad backlight is not controlled by the keyboard</a></li>
<li>There's a <a href="https://keyboard.frame.work/">keyboard information site</a> but no easy way to remap keys.</li>
</ul>

<p>On the plus side:</p>

<ul>
<li>The dedicated calculator key is nice.</li>
<li>The function keys have controls for media playback, volume, brightness etc.</li>
<li>Impressively, both Function Lock and NumLock remember their state between reboots. Sadly there's no indicator light on them.</li>
</ul>

<h2 id="battery-life"><a href="https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/#battery-life">Battery Life</a></h2>

<p>Fine. Looks like 5-8 hours of moderate use. To be honest, I spend most of my time near a USB-C power source. The UEFI has an option to set a maximum charge for the battery, so I set it to 75%. That's a good balance between usable battery life and preserving its longevity.</p>

<p>Suspend seemed to work and wasn't too heavy on the battery overnight.  It runs cool - I haven't heard the fans spin up yet. That said, I'm not running loads of 3D games or recompiling my kernel.</p>

<h2 id="niggles"><a href="https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/#niggles">Niggles</a></h2>

<p>There's a significant gap between the touchpad and the chassis when it is clicked.</p>

<p><img src="/blog/wp-content/uploads/2024/06/trackpad-gap.jpg" alt="Gap between trackpad and chassis." class="aligncenter"></p>

<p>After reassembling, there is a slight but noticeable lip between the trackpad unit and the spacer units.</p>

<p><img src="/blog/wp-content/uploads/2024/06/Rising-lip.jpg" alt="Gap between the shell." class="aligncenter"></p>

<p>The BIOS update seemed to take longer than the OS installation! Seriously annoying having to watch it transcribe each bit via the pony express. It doesn't stop when finished, so you'll need to keep an eye on it otherwise it goes through it again.</p>

<p>The hardware switches for the camera and microphone <em>feel</em> fragile. Because they're slightly stiff, I'm always worried I'll damage the screen when I use them.</p>

<p><img src="/blog/wp-content/uploads/2024/06/Camera-Switches.jpg" alt="Switches near the camera." class="aligncenter"></p>

<p>The microphone is ridiculously sensitive.  I had to set it to the lowest level otherwise it would pick up sounds from other rooms and made me sound a bit boomy.</p>

<p>Here's an audio test of it.</p>

<p></p><figure class="audio">
	<figcaption>🔊</figcaption>
	
	<audio controls="" loading="lazy" src="/blog/wp-content/uploads/2024/06/mictest.mp3">
		<p>💾 <a href="/blog/wp-content/uploads/2024/06/mictest.mp3">Download this audio file</a>.</p>
	</audio>
</figure><p></p>

<p>The setup guide didn't mention the tape which needs removing from the thermal pads - I only found out about it by reading the comments.</p>

<p>The expansion ports <em>seem</em> like a good idea, but they are ridiculously small. There's just about enough space to fit an HDMI socket and a smidgen of circuitry.
<img src="/blog/wp-content/uploads/2024/06/Expansion-Ports.jpg" alt="Expansion Ports" class="aligncenter"></p>

<p>Personally, I'd have liked them to be even longer to allow some more complicated expansion ideas.  I think I'm going to struggle to <a href="https://shkspr.mobi/blog/2024/03/thoughts-on-building-an-nfc-reader-for-the-framework-laptop/">design an NFC reader for them</a>.</p>

<h2 id="wifi"><a href="https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/#wifi">WiFi</a></h2>

<p>The 5GHz WiFi seems slow. I can hit 250Mbps on the Framework. Another laptop in the same position hit over 300Mbps.  I've also noticed it drop out once or twice. I don't know if that's the hardware, software, or firmware.</p>

<p>Obviously, that's plenty fast for most day-to-day operations, but it is a bit weird that it is noticeably slower than other machines.</p>

<h2 id="webcam"><a href="https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/#webcam">WebCam</a></h2>

<p>1080p @ 30fps. Excellent quality. The hardware switch disables it. I usually prefer a physical cover - but the switch does the trick. Here's a quick recording.</p>

<p></p><div style="width: 620px;" class="wp-video"><video class="wp-video-shortcode" id="video-50749-8" width="620" height="349" preload="metadata" controls="controls"><source type="video/mp4" src="https://shkspr.mobi/blog/wp-content/uploads/2024/06/frameworkwebcam.mp4?_=8"><a href="https://shkspr.mobi/blog/wp-content/uploads/2024/06/frameworkwebcam.mp4">https://shkspr.mobi/blog/wp-content/uploads/2024/06/frameworkwebcam.mp4</a></video></div><p></p>

<p>More than good enough for endless video calling. The tallness of the screen is an advantage here - it puts it much closer to your eye-line.</p>

<h2 id="final-thoughts"><a href="https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/#final-thoughts">Final thoughts</a></h2>

<p>I've only been using this for a few days, but it is a dream. Screen is big and bright. Keyboard is responsive. Sound is decent. The community are friendly.</p>

<p>The total cost of the laptop and accessories was £1,700. That's a fair whack of cash! But I wanted to support a new way of building and designing laptops.  In the few days that I've been using it the performance has been excellent and build quality is solid.</p>

<p>Is it a lightweight and svelte powerhouse like the M3 MacBook Air? No - but it isn't designed to be. I'm hoping this machine will last me into the 2030s with significant upgrades along the way.</p>

<p>If you have any questions - please drop a comment in the box.  And if you have any laptop stickers, send them my way - it is looking a little bare!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=50749&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/06/review-framework-16-laptop/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Review: ACS ACR1251T-E2 USB Token NFC Reader II ★★★★☆]]></title>
		<link>https://shkspr.mobi/blog/2024/04/review-acs-acr1251t-e2-usb-token-nfc-reader-ii/</link>
					<comments>https://shkspr.mobi/blog/2024/04/review-acs-acr1251t-e2-usb-token-nfc-reader-ii/#respond</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 12 Apr 2024 11:34:45 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nfc]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[USB]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=50158</guid>

					<description><![CDATA[Recap - I want to build an NFC reader expansion card for the FrameWork laptop. So I&#039;ve bought a couple of components.  This is the ACR1251T-E2 - it&#039;s a USB pen-drive sized NFC reader with a side-out USB-A plug.  Costs about £40.    There&#039;s a recessed green LED which flashes to let you know that it is working. It doesn&#039;t beep or vibrate when it detects an NFC token. It is a little bit tricky …]]></description>
										<content:encoded><![CDATA[<p>Recap - <a href="https://shkspr.mobi/blog/2024/03/thoughts-on-building-an-nfc-reader-for-the-framework-laptop/">I want to build an NFC reader expansion card for the FrameWork laptop</a>. So I've bought a couple of components.</p>

<p>This is the <a href="https://www.acs.com.hk/en/products/486/acr1251t-usb-tokens-nfc-reader-ii/">ACR1251T-E2</a> - it's a USB pen-drive sized NFC reader with a side-out USB-A plug.  Costs about £40.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/04/ACS-ACR1251T-E2-USB-Token-NFC-Reader-II.webp" alt="USB thumb drive plugged into a computer." width="1024" height="576" class="aligncenter size-full wp-image-50165">

<p>There's a recessed green LED which flashes to let you know that it is working. It doesn't beep or vibrate when it detects an NFC token. It is a little bit tricky finding the antenna as the internal circuitry slides down the plastic housing - <a href="https://fccid.io/V5MACR1251T/Internal-Photos/Int-Photos-3848090">as can be seen in these internal photos</a></p>

<p>There's a lanyard hole at the end, and a plastic clip so you can attach it to things.</p>

<p>Linux support is flawless. Running <code>lsusb</code> shows <code>072f:224f Advanced Card Systems, Ltd ACR1251 CL Reader PICC</code></p>

<p>And running <code>pcsc_scan</code> gives the same information: <code>0: ACS ACR1251 CL Reader [ACR1251 CL Reader PICC] 00 00</code></p>

<p>Sadly, <a href="https://github.com/nfc-tools/libnfc/issues/719">it wasn't detected by libnfc 1.8.0 ☹</a></p>

<p>Using the <a href="https://github.com/BryanJacobs/fido2-hid-bridge">FIDO2 HID Bridge</a> I was able to use <a href="https://shkspr.mobi/blog/2024/02/giving-the-finger-to-mfa-a-review-of-the-z1-encrypter-ring-from-cybernetic/">my NFC Ring</a> to log in to various websites.</p>

<p>It's a solid enough unit. The plastic housing is sturdy and not easily damaged. You can't get in to the shell without a spludger.</p>

<p>The only downsides are that it uses USB-A - we're in the C era now! - and that the sliding mechanism obscures the antenna position. But, if you want to carry a discreet USB stick with you for NFC purposes, there's nothing better.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=50158&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/04/review-acs-acr1251t-e2-usb-token-nfc-reader-ii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Review: ACM1252U-Z2 NFC Reader Board ★★★★★]]></title>
		<link>https://shkspr.mobi/blog/2024/04/review-acm1252u-z2-nfc-reader-board/</link>
					<comments>https://shkspr.mobi/blog/2024/04/review-acm1252u-z2-nfc-reader-board/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 11 Apr 2024 11:34:11 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nfc]]></category>
		<category><![CDATA[review]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=50160</guid>

					<description><![CDATA[Recap - I want to build an NFC reader expansion card for the FrameWork laptop. So I&#039;ve bought a couple of components.  This is the ACM1252U-Z2 and Oh! It is a dinky little component!    The only sign that it is working is a flashing green LED. There&#039;s no buzzer on the board. It really is a tiny thing. Side on it is almost invisible.    Does it work with Linux? Oh yes! It has a Micro-USB port, so…]]></description>
										<content:encoded><![CDATA[<p>Recap - <a href="https://shkspr.mobi/blog/2024/03/thoughts-on-building-an-nfc-reader-for-the-framework-laptop/">I want to build an NFC reader expansion card for the FrameWork laptop</a>. So I've bought a couple of components.</p>

<p>This is the <a href="https://www.acs.com.hk/en/products/412/acm1252u-z2-small-nfc-reader-module/">ACM1252U-Z2</a> and Oh! It is a dinky little component!</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/04/ACM1252U-Z2-Board.webp" alt="View of a circuit board with a lit green LED." width="768" height="576" class="aligncenter size-full wp-image-50162">

<p>The only sign that it is working is a flashing green LED. There's no buzzer on the board. It really is a tiny thing. Side on it is almost invisible.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/04/ACM1252U-Z2-Side.webp" alt="Side on view of a circuit board. Nothing much is protruding." width="767" height="670" class="aligncenter size-full wp-image-50161">

<p>Does it work with Linux? Oh yes! It has a Micro-USB port, so I got a USB-C OTG cable. I plugged it into my laptop and ran <code>lsusb</code> - which shows it as <code>072f:223e Advanced Card Systems, Ltd ACR1252 Reader</code></p>

<p>Running <code>pcsc_scan</code> gives pretty much the same information <code>0: ACS ACR1252 CL Reader [ACR1252 Reader PICC] 00 00</code></p>

<p>It wasn't detected by libnfc 1.8.0 ☹</p>

<p>Using the <a href="https://github.com/BryanJacobs/fido2-hid-bridge">FIDO2 HID Bridge</a> I was able to use <a href="https://shkspr.mobi/blog/2024/02/giving-the-finger-to-mfa-a-review-of-the-z1-encrypter-ring-from-cybernetic/">my NFC Ring</a> to log in to various websites.</p>

<p>The antenna seems pretty sensitive. It read my ring from about a centimetre away though a cardboard sleeve.  I <em>think</em> the debug port is the "J3 nRF USB" - but I can't find many details about wiring it up.</p>

<p>So, will it fit in the Framework laptop? Perhaps. If I could solder on a USB-C jack, it would still stick out 2.5cm - so a 3D printed protector would still be needed.</p>

<p>Alternatively, <a href="https://prattle.org.uk/@steve/112185044748746269">as suggested by Stephen Early</a> it <em>might</em> be possible to hook it in to the spare USB 2.0 ports. And, if the size is right, stowing it beside the touchpad.</p>

<p>But, first, I need to wait for my laptop to ship 😂</p>

<p>The board costs about £35</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=50160&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/04/review-acm1252u-z2-nfc-reader-board/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Fixing broken suspend on Pop_OS]]></title>
		<link>https://shkspr.mobi/blog/2024/04/fixing-broken-suspend-on-pop_os/</link>
					<comments>https://shkspr.mobi/blog/2024/04/fixing-broken-suspend-on-pop_os/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 06 Apr 2024 11:34:00 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[pop_os]]></category>
		<category><![CDATA[ubuntu]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=50105</guid>

					<description><![CDATA[My Linux laptop used to suspend perfectly. I&#039;d close the lid and it would go to sleep. Open it up, it would spring to life - presenting me with a password screen.  But, some time in the last few months, it has stopped doing that.  If I close the lid, it keeps running. This is unhelpful.  If I manually run the suspend command - systemctl suspend - the laptop blanks the screen then immediately…]]></description>
										<content:encoded><![CDATA[<p>My Linux laptop used to suspend perfectly. I'd close the lid and it would go to sleep. Open it up, it would spring to life - presenting me with a password screen.  But, some time in the last few months, it has stopped doing that.</p>

<p>If I close the lid, it keeps running. This is unhelpful.</p>

<p>If I manually run the suspend command - <code>systemctl suspend</code> - the laptop blanks the screen then immediately turns it back on at the lock screen. It doesn't suspend.</p>

<p>I know that suspend physically works - becasue running any of these other command <em>does</em> properly suspend the machine. But powering it back up goes straight to the desktop - no lock screen!</p>

<ul>
<li><code>sudo /lib/systemd/systemd-sleep suspend</code></li>
<li><code>sudo echo "mem" &gt; /sys/power/state</code></li>
<li><code>sudo acpitool -s</code></li>
</ul>

<h2 id="the-fix"><a href="https://shkspr.mobi/blog/2024/04/fixing-broken-suspend-on-pop_os/#the-fix">The Fix</a></h2>

<p>I found what was <a href="https://github.com/systemd/systemd/issues/21991#issuecomment-1005020257">causing suspend to fail</a> by running:</p>

<ul>
<li><code>sudo systemd-analyze verify systemd-suspend.service</code></li>
</ul>

<p>That spat out any errors in the suspend service.  Highlighted in red was:</p>

<p><code>systemd-suspend.service: Failed to create systemd-suspend.service/start: Unit nvidia-resume.service is masked.</code></p>

<p>That was odd, because I don't have an Nvidia graphics card.</p>

<p>Looking in the relevant directory:</p>

<p><code>cd /etc/systemd/system/systemd-suspend.service.requires</code></p>

<p>I found:</p>

<pre><code class="language-_">nvidia-resume.service -&gt; /lib/systemd/system/nvidia-resume.service
nvidia-suspend.service -&gt; /lib/systemd/system/nvidia-suspend.service
</code></pre>

<p>I deleted the <code>nvidia-resume.service</code> and <code>nvidia-suspend.service</code> files.</p>

<p>For good measure, I also checked what Nvidia stuff I had installed:</p>

<ul>
<li><code>apt list --installed | grep -i nvidia</code></li>
</ul>

<p>I used <code>sudo apt purge</code> to remove the remnants of any Nvidia stuff. Probably installed by mistake.</p>

<p>After that, suspend worked fine.</p>

<h2 id="what-fixes-didnt-work"><a href="https://shkspr.mobi/blog/2024/04/fixing-broken-suspend-on-pop_os/#what-fixes-didnt-work">What "Fixes" Didn't Work</a></h2>

<p>I went down a bit of a rabbit hole, following lots of suggestions from various people on the Internet.  None of these helped me - but they may be useful pointers to you.</p>

<p>I tried <a href="https://www.vegard.net/how-to-suspend-pop-os/">disabling everything in <code>/proc/acpi/wakeup</code></a>. I couldn't get <code>PXSX</code> to be disabled. But even with everything else off, the suspend didn't work.</p>

<p><a href="https://github.com/pop-os/pop/issues/2356#issuecomment-1987290124">Killing Bluetooth with <code>rfkill block bluetooth</code></a> didn't work. Nor did disabling WiFi.</p>

<p>I have <a href="https://www.reddit.com/r/pop_os/comments/ukyl7s/suspend_is_not_working_in_2204_lts/">an updated Kernel</a> 6.8.0. I'm not sure of the ramifications of swapping to an older one.</p>

<p>Running <a href="https://github.com/pop-os/pop/issues/1368"><code>sudo kernelstub -a mem_sleep_default=deep</code></a> and then rebooting didn't make a difference.</p>

<p>Switching from Wayland to X11 didn't fix it. Nor did unplugging the laptop from power. No external peripherals or screens were connected.</p>

<p>The whole system - including Flatpaks and Snaps - was updated.</p>

<p>This <a href="https://www.reddit.com/r/pop_os/comments/vr7uco/network_manager_wake_requested/jxxm0e4/">shell script</a> works. But there's no way to tie it in to having the power button pressed or the lid closed.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=50105&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/04/fixing-broken-suspend-on-pop_os/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Viewing my CT Scan in 3D using Linux]]></title>
		<link>https://shkspr.mobi/blog/2024/03/viewing-my-ct-scan-in-3d-using-linux/</link>
					<comments>https://shkspr.mobi/blog/2024/03/viewing-my-ct-scan-in-3d-using-linux/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 29 Mar 2024 12:34:22 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[health]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[medicine]]></category>
		<category><![CDATA[teeth]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=50005</guid>

					<description><![CDATA[Several years ago, I had a CT scan of my jaw. The dentist wasn&#039;t sure if she was allowed to give me a copy of the scan, which led me to ask &#34;who owns the copyright to my medical images?&#34;  I still don&#039;t have an answer to the copyright question - but I do now have a copy of a CT scan!  Last week - following some dental trauma - I had another scan of my head. The dentist took great delight in…]]></description>
										<content:encoded><![CDATA[<p>Several years ago, I had a CT scan of my jaw. The dentist wasn't sure if she was allowed to give me a copy of the scan, which led me to ask "<a href="https://shkspr.mobi/blog/2018/11/who-owns-the-copyright-to-my-medical-images/">who owns the copyright to my medical images?</a>"  I still don't have an answer to the copyright question - but I <em>do</em> now have a copy of a CT scan!</p>

<p>Last week - <a href="https://shkspr.mobi/blog/2024/03/the-tooth-the-whole-tooth-and-nothing-but-the-tooth/">following some dental trauma</a> - I had another scan of my head. The dentist took great delight in showing me my bones in 3D. So I asked for a copy.</p>

<p>This was something he'd never done before! So, together, we navigated the software, found the export button, and generated a copy. Even zipped up it was half a gigabyte - a bit too much for email and, not unreasonably, he didn't want me plugging in strange USB devices to his medical equipment. So he sent it over WeTransfer. Possibly not the most secure method for my medical data, but I didn't really have time to set up a personal SFTP site or teach him about installing WSL so he could SCP the content. Ah well, needs must.</p>

<p>Unzipped, the folder was about 700MB. Of that, 400MB was taken up by the included Windows app "Ez3D-i". Unsurprisingly, it didn't run on Linux.</p>

<p>The other 300MB was taken up by 450 .DCM files. These are medical images in the DICOM format. This is <a href="https://data.standards.nhs.uk/published-standards/digital-imaging-and-communications-in-medicine-dicom">a relatively open standard</a> which uses JPG plus lots of metadata.  There are dozens of Linux programs which can read this - although many haven't been updated in years.</p>

<p>The easiest GUI for viewing the images is <a href="https://mangoviewer.com/mango.html">Mango</a>. It presents a view of the CT Scan that you can move around.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/03/Mango-Teeth.jpg" alt="Screenshot of a user interface with three panels, each showing a different view of my teeth." width="782" height="581" class="aligncenter size-full wp-image-50007">

<p>It isn't the most intuitive app in the world, but it is good enough for browsing the scan.</p>

<p>If you want a 3D model of your scan, I recommend <a href="https://www.aliza-dicom-viewer.com/">Aliza</a>. Again, not the simplest interface:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/03/Aliza.jpg" alt="Screenshot of a user interface showing a 2D view and a 3D view of my scan." width="1024" height="650" class="aligncenter size-full wp-image-50008">

<p>But once you get the hang of it, you can manipulate the 3D scan and view it from all angles.  It's possible to peel away the soft tissue and do all sorts of other fancy trickery. Even on my laptop without a fancy graphics card, it was fast.  Here's a quick animation showing the (false colour) version.</p>

<p><video width="668" height="496" mute="" loop="" autoplay="" src="https://shkspr.mobi/blog/wp-content/uploads/2024/03/teeth.mp4"></video></p>

<p>If you have had a CT scan, please do ask for a copy of the DICOM files. It is great fun to explore around your own body.</p>

<p>Now I just need to find a way to import this into my Meta Quest so I can enjoy these teeth in VR!</p>

<p>As per <a href="https://twitter.com/LeBearGirdle/status/898280833299230722">the meme</a>:
<a href="https://twitter.com/LeBearGirdle/status/898280833299230722"><img src="https://shkspr.mobi/blog/wp-content/uploads/2024/03/teeth-fs8.png" alt="[Dentist waiting room] Me: [chanting] teeth, teeth-. Other patients: teeth, TEETH. Secretary: [pounding her clipboard] TEETH, TEETH, TEETH!" width="609" height="417" class="aligncenter size-full wp-image-50006"></a></p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=50005&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/03/viewing-my-ct-scan-in-3d-using-linux/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Review: An NFC reader/writer with USB-C - ACR1252U-MF ★★★★⯪]]></title>
		<link>https://shkspr.mobi/blog/2024/02/review-an-nfc-reader-writer-with-usb-c-acr1252u-mf/</link>
					<comments>https://shkspr.mobi/blog/2024/02/review-an-nfc-reader-writer-with-usb-c-acr1252u-mf/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 24 Feb 2024 12:34:04 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[MFA]]></category>
		<category><![CDATA[nfc]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[rfid]]></category>
		<category><![CDATA[usb-c]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49611</guid>

					<description><![CDATA[I needed to read and write NFC cards on Linux. I only buy USB-C peripherals now, so I found the brilliantly named &#34;ACR1252U-MF&#34; which appears to be the only USB-C reader on the market. Total cost was about £35 on eBay.  It&#039;s a cheap and light plastic box with a short USB cord. When you plug it in, there&#039;s a flashing light which can&#039;t be disabled. When it is powered up, or it detects and NFC chip, …]]></description>
										<content:encoded><![CDATA[<p>I needed to read and write NFC cards on Linux. I only buy USB-<strong>C</strong> peripherals now, so I found the brilliantly named "<a href="https://www.acs.com.hk/en/products/342/acr1252u-usb-nfc-reader-iii-nfc-forum-certified-reader/">ACR1252U-MF</a>" which appears to be the only USB-C reader on the market. Total cost was about £35 on eBay.</p>

<p>It's a cheap and light plastic box with a short USB cord. When you plug it in, there's a flashing light which can't be disabled. When it is powered up, or it detects and NFC chip, it makes this weird and scratchy beep:</p>

<p></p><figure class="audio">
	<figcaption>🔊</figcaption>
	
	<audio controls="" loading="lazy" src="https://shkspr.mobi/blog/wp-content/uploads/2024/02/ACR1252u-MF-Beep.mp3">
		<p>💾 <a href="https://shkspr.mobi/blog/wp-content/uploads/2024/02/ACR1252u-MF-Beep.mp3">Download this audio file</a>.</p>
	</audio>
</figure><p></p>

<p>On Linux, it shows up as: <code>072f:223b Advanced Card Systems, Ltd ACR1252 Dual Reader</code></p>

<p>To get it working, install <a href="https://pcsc-tools.apdu.fr/">PCSC Tools</a> and the <a href="https://linux.die.net/man/8/pcscd">PCSC Daemon</a>:</p>

<p><code>sudo apt install pcsc-tools pcscd</code></p>

<p>To start the daemon:</p>

<p><code>service pcscd start</code></p>

<p>Running <code>pcsc_scan</code> detected the reader as <em>two</em> readers - PICC and SAM</p>

<pre><code class="language-terminal">Using reader plug&amp;#039;n play mechanism
Scanning present readers...
0: ACS ACR1252 1S CL Reader [ACR1252 Dual Reader PICC] 00 00
1: ACS ACR1252 1S CL Reader [ACR1252 Dual Reader SAM] 01 00
</code></pre>

<p>Putting tokens on and off the reader showed them being detected and removed.</p>

<p>Despite my best efforts, I was <a href="https://github.com/nfc-tools/libnfc/issues/658">unable to get this working with <code>libnfc</code></a>.</p>

<pre><code class="language-txt">nfc-list uses libnfc 1.8.0
No NFC device found.
</code></pre>

<p>For reading and writing basic NDEF tags, I used <a href="https://www.wakdev.com/en/apps/nfc-tools-pc-mac.html">Wakdev's NFC tools</a>, I was also able to use various Python scripts like <a href="https://github.com/Giraut/pcsc-ndef">PCSC NDEF</a></p>

<p>It also worked with a <a href="https://github.com/BryanJacobs/fido2-hid-bridge">FIDO2 / HID Bridge</a> so I could use an MFA token.</p>

<p>There's <a href="https://www.acs.com.hk/en/driver/342/acr1252u-usb-nfc-reader-iii-nfc-forum-certified-reader/">lots of documentation about the reader and its API</a> as well as some <a href="https://www.acs.com.hk/en/utility-tools/">official ACS Linux tools</a>. In theory it supports firmware update - although none have been released.</p>

<p>It's a cheap and cheerful device. It would be nice if there were a way to stop the flashing LED and crappy buzzer.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49611&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/02/review-an-nfc-reader-writer-with-usb-c-acr1252u-mf/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[HOWTO: Sort BitWarden Passwords by Date]]></title>
		<link>https://shkspr.mobi/blog/2024/02/howto-sort-bitwarden-passwords-by-date/</link>
					<comments>https://shkspr.mobi/blog/2024/02/howto-sort-bitwarden-passwords-by-date/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 14 Feb 2024 12:34:30 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[bitwarden]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49616</guid>

					<description><![CDATA[I highly recommend BitWarden as a password manager. It is free, open source, and has a great range of apps and APIs.  The one thing it doesn&#039;t have is a way to sort your accounts by creation date.  I now have over a thousand accounts that I&#039;ve added - so I wanted to prune away some of the older ones.  So, here&#039;s how to do it.  Export your vault  In the desktop version of BitWarden, go to File → E…]]></description>
										<content:encoded><![CDATA[<p>I highly recommend <a href="https://bitwarden.com">BitWarden</a> as a password manager. It is free, open source, and has a great range of apps and APIs.</p>

<p>The one thing it <a href="https://community.bitwarden.com/t/sort-items-by-date-of-modification-addition-last-use-etc/2484">doesn't have is a way to sort your accounts by creation date</a>.  I now have over a thousand accounts that I've added - so I wanted to prune away some of the older ones.</p>

<p>So, here's how to do it.</p>

<h2 id="export-your-vault"><a href="https://shkspr.mobi/blog/2024/02/howto-sort-bitwarden-passwords-by-date/#export-your-vault">Export your vault</a></h2>

<p>In the <em>desktop</em> version of BitWarden, go to File → Export Vault.  Choose the JSON format (this doesn't work for CSV) and follow the on-screen instructions.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/02/BitWarden-Export-fs8.png" alt="Screenshot of the BitWarden export page." width="793" height="500" class="aligncenter size-full wp-image-49617">

<p><strong>NOTE!</strong> This will save <em>all</em> of your passwords to disk. Do not do this on a shared machine. Delete the file as soon as you are done with it.</p>

<h2 id="sort-with-jq"><a href="https://shkspr.mobi/blog/2024/02/howto-sort-bitwarden-passwords-by-date/#sort-with-jq">Sort with JQ</a></h2>

<p>Using the <a href="https://jqlang.github.io/jq/"><code>jq</code> utility</a> it is possible to search and sort the exported JSON.</p>

<p>This command pipes your export to JQ. It selects all the <code>items</code>, then it sorts by when the item was last edited. It then displays the name of the account and the date, followed by a newline.</p>

<pre><code class="language-bash">cat bitwarden.json | jq -r '.items | sort_by(.revisionDate) | .[] | .name, .revisionDate, " " '
</code></pre>

<h2 id="purge"><a href="https://shkspr.mobi/blog/2024/02/howto-sort-bitwarden-passwords-by-date/#purge">Purge!</a></h2>

<p>You <em>could</em> <a href="https://bitwarden.com/help/cli/#delete">use the API to delete items</a> based on their ID.  Personally, I'd rather go through manually.</p>

<h2 id="whats-next"><a href="https://shkspr.mobi/blog/2024/02/howto-sort-bitwarden-passwords-by-date/#whats-next">What's next?</a></h2>

<p>It would be great if BitWarden allowed sorting by date in their UI. Even better if they could sort by usage.  Until then, I'll spend every Valentine's Day manually deleting old and unloved accounts.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49616&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/02/howto-sort-bitwarden-passwords-by-date/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Review: Iiyama 28 inch 4K Vertical Monitor ★★★★⯪]]></title>
		<link>https://shkspr.mobi/blog/2024/01/review-iiyama-28-inch-4k-vertical-monitor/</link>
					<comments>https://shkspr.mobi/blog/2024/01/review-iiyama-28-inch-4k-vertical-monitor/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 20 Jan 2024 12:34:31 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[screen]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49292</guid>

					<description><![CDATA[Four years ago, I got the Iiyama ProLite 24&#34; Vertical Screen. But as my eyes grow dimmer and my hind-brain desires upgrades, I splurged on the (stupidly named) Iiyama ProLite XUB2893UHSU-B5.  It is well lush! Thin bezel around 3 sides. Excellent viewing angle when vertical. A decent array of video ports and USB. And fairly wallet friendly £280.  There&#039;s a lot of screen for your money.   (Yes, I …]]></description>
										<content:encoded><![CDATA[<p>Four years ago, I got the <a href="https://shkspr.mobi/blog/2020/04/review-iiyama-prolite-b2482hs-b1-24-vertical-monitor/">Iiyama ProLite 24" Vertical Screen</a>. But as my eyes grow dimmer and my hind-brain desires upgrades, I splurged on the (stupidly named) <a href="https://amzn.to/3tBezSF">Iiyama ProLite XUB2893UHSU-B5</a>.</p>

<p>It is <em>well</em> lush! Thin bezel around 3 sides. Excellent viewing angle when vertical. A decent array of video ports and USB. And fairly wallet friendly £280.  There's a <em>lot</em> of screen for your money.</p>

<p><img src="https://shkspr.mobi/blog/wp-content/uploads/2024/01/4k-monitor.jpg" alt="A large vertical monitor atop a standing desk." width="1024" height="768" class="aligncenter size-full wp-image-49435">
(Yes, I do have a desk crowded with gadgetry!)</p>

<p>I'm only using this for reading <em>very</em> long (and only slightly boring) documents. I can't tell you if it has the millisecond response you want for gaming. But for watching content, it is superb. The screen isn't reflective and the picture is fabulous.</p>

<p>There are plenty of options if you want to fiddle with your gamma, contrast, brightness, and all the other things which are standard these days.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/01/Picture-adjustment-options.jpg" alt="Picture adjustment options." width="1024" height="768" class="aligncenter size-full wp-image-49357">

<h2 id="downsides"><a href="https://shkspr.mobi/blog/2024/01/review-iiyama-28-inch-4k-vertical-monitor/#downsides">Downsides</a></h2>

<p>I'm going to start with the slight niggles I found.</p>

<p>First, is the built-in USB hub.  You get 4 USB-A sockets - two are USB-3 and have 900mW, two are USB-2 and have 500mW.  That's basically fine, but I would have expected at least a couple of USB-C by now.  But what's worse is that the hub itself takes the stupid USB-B 3.0 connector. Yeah, the weird double height one. 
<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/01/USB-B.jpg" alt="A horrible USB plug." width="512" height="456" class="aligncenter size-full wp-image-49293">
It comes with a cable in the box. But it is a bit daft.</p>

<p>As always, the blue LED for power is too bright - but nothing a bit of tape can't fix.</p>

<p>The speakers are a little tinny. Basically fine for a conference call, but nothing more. There is a headphone socket if you want to route audio to something more substantial.</p>

<p>I <em>think</em> the EDID is a little wonky - see the Linux section below.</p>

<p>On Windows, my laptop sometimes forgot that audio could be routed through the monitor. I restarted my hub and everything worked again. I've no idea if that's the fault of the laptop, hub, or screen.</p>

<p>The settings buttons are a little fiddly. No worse than any other screen - and the sort of thing you play around with once and then never again.</p>

<h2 id="positives"><a href="https://shkspr.mobi/blog/2024/01/review-iiyama-28-inch-4k-vertical-monitor/#positives">Positives</a></h2>

<p>Great mounting options. As well as boring horizontal, the monitor can be rotate left <em>or</em> right to 90 degrees. The stand is well sprung so the height is easily adjusted. Similarly, it can be tilted back a bit if that's what you want.</p>

<p>Audio quality out of the headphone socket is excellent. No cross-chatter even at high volumes.</p>

<p>The cables which come with it are a decent length (HDMI, DP, Power) and the DP cable has a locking mechanism (squeeze to open).</p>

<p>It uses two build-in thumb-turn screws to connect the stand to the base-plate, and the monitor to the stand. No tools required.  Oh, and the base-plate also rotates.</p>

<h2 id="linux"><a href="https://shkspr.mobi/blog/2024/01/review-iiyama-28-inch-4k-vertical-monitor/#linux">Linux</a></h2>

<p>The USB hub shows up as <code>05e3:0610 Genesys Logic, Inc. Hub</code> - nothing remarkable. Just works.</p>

<p>For some reason, I couldn't get my Linux box to drive it at 60Hz without turning on fractional scaling. I think that's a limit of my GPU. I'll be honest, I'm not sure what's the difference between 200% @ 2160p and 100% @ 1080p.</p>

<p>Here's what the monitor reports using <code>sudo get-edid -b 7 | parse-edid</code>  (run without <code>-b 7</code> first to find your bus number).</p>

<pre><code class="language-_">Section "Monitor"
    Identifier "PL2893UH"
    ModelName "PL2893UH"
    VendorName "IVM"
    # Monitor Manufactured week 33 of 2023
    # EDID version 1.4
    # Digital Display
    DisplaySize 620 340
    Gamma 2.20
    Option "DPMS" "true"
    Horizsync 15-150
    VertRefresh 24-75
    # Maximum pixel clock is 600MHz
    #Not giving standard mode: 1920x1440, 60Hz
    #Not giving standard mode: 1920x1200, 60Hz
    #Not giving standard mode: 1920x1080, 60Hz
    #Not giving standard mode: 1680x1050, 60Hz
    #Not giving standard mode: 1440x900,  60Hz
    #Not giving standard mode: 1400x1050, 60Hz
    #Not giving standard mode: 1280x1024, 60Hz
    #Not giving standard mode: 1280x720,  60Hz

    #Extension block found. Parsing...
#WARNING: I may have missed a mode (CEA mode 95)
#WARNING: I may have missed a mode (CEA mode 94)
#WARNING: I may have missed a mode (CEA mode 93)
    Modeline    "Mode 22" 262.75  3840 3888 3920 4000 2160 2163 2168 2191 +hsync -vsync 
    Modeline     "Mode 0" 533.25  3840 3888 3920 4000 2160 2163 2168 2222 +hsync -vsync 
    Modeline     "Mode 1" 
    Modeline     "Mode 2" 
    Modeline     "Mode 3" 148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync
    Modeline     "Mode 4" 148.500 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync
    Modeline     "Mode 5"  74.250 1920 2008 2052 2200 1080 1082 1087 1125 +hsync +vsync interlace
    Modeline     "Mode 6"  74.250 1920 2448 2492 2640 1080 1082 1089 1125 +hsync +vsync interlace
    Modeline     "Mode 7"  74.250 1280 1390 1420 1650  720  725  730  750 +hsync +vsync
    Modeline     "Mode 8"  74.250 1280 1720 1760 1980  720  725  730  750 +hsync +vsync
    Modeline     "Mode 9"  54.000 1440 1464 1592 1728  576  581  586  625 -hsync -vsync
    Modeline    "Mode 10"  54.000 1440 1464 1592 1728  576  581  586  625 -hsync -vsync
    Modeline    "Mode 11"  27.000  720  732  796  864  576  581  586  625 -hsync -vsync
    Modeline    "Mode 12"  27.000  720  732  796  864  576  581  586  625 -hsync -vsync
    Modeline    "Mode 13"  27.000 1440 1464 1590 1728  576  578  581  625 -hsync -vsync interlace
    Modeline    "Mode 14"  27.000 1440 1464 1590 1728  576  578  581  625 -hsync -vsync interlace
    Modeline    "Mode 15"  54.054 1440 1472 1596 1716  480  489  495  525 -hsync -vsync
    Modeline    "Mode 16"  54.054 1440 1472 1596 1716  480  489  495  525 -hsync -vsync
    Modeline    "Mode 17"  27.027  720  736  798  858  480  489  495  525 -hsync -vsync
    Modeline    "Mode 18"  27.027  720  736  798  858  480  489  495  525 -hsync -vsync
    Modeline    "Mode 19"  27.027 1440 1478 1602 1716  480  484  487  525 -hsync -vsync interlace
    Modeline    "Mode 20"  27.027 1440 1478 1602 1716  480  484  487  525 -hsync -vsync interlace
    Modeline    "Mode 21"  25.200  640  656  752  800  480  490  492  525 -hsync -vsync
    Modeline    "Mode 23"  241.50 2560 2608 2640 2720 1440 1443 1448 1481 +hsync -vsync 
    Modeline    "Mode 24"  200.25 2560 2608 2640 2720 1440 1443 1448 1474 +hsync -vsync 
    Option "PreferredMode" "Mode 22"
EndSection
</code></pre>

<p>But, ultimately, all the functions worked with Linux. The display was crisp, sound was passed over DP or HDMI, the USB port worked flawlessly.</p>

<h2 id="verdict"><a href="https://shkspr.mobi/blog/2024/01/review-iiyama-28-inch-4k-vertical-monitor/#verdict">Verdict</a></h2>

<p>Too often "vertical" monitors have crap viewing angles. I'm delighted to say that the PL2893UH is perfect. Even at an oblique angle text remains sharp and colours remain consistent.</p>

<p>If you're going to be staring at a screen all day, it might as well be this one!</p>

<p>You can <a href="https://amzn.to/3tBezSF">buy the monitor on Amazon</a>.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49292&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/01/review-iiyama-28-inch-4k-vertical-monitor/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Gadget Review: FIFINE Ampligame A8 USB-C Gaming Microphone ★★★★⯪]]></title>
		<link>https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/</link>
					<comments>https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 04 Dec 2023 12:34:42 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[usb-c]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=48682</guid>

					<description><![CDATA[The good folks at Fifine have sent me this neat little microphone to review.  Unboxing    Sound Quality  Writing about microphones is like painting about flavour. So here&#039;s what it sounds like:   	🔊 	 	 		💾 Download this audio file. 	   No noticeable hiss. Captured my voice perfectly.  It picked up a little clack from my keyboard as I typed. Colleagues could hear me clearly - even if they were som…]]></description>
										<content:encoded><![CDATA[<p>The good folks at <a href="https://fifinemicrophone.com/products/fifine-ampligame-a8">Fifine</a> have sent me this neat little microphone to review.</p>

<h2 id="unboxing"><a href="https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/#unboxing">Unboxing</a></h2>

<iframe title="Unboxing and Review: FIFINE Ampligame A8" width="620" height="349" src="https://www.youtube.com/embed/NP7Fp2R1ebs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>

<h2 id="sound-quality"><a href="https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/#sound-quality">Sound Quality</a></h2>

<p>Writing about microphones is like painting about flavour. So here's what it sounds like:</p>

<p></p><figure class="audio">
	<figcaption>🔊</figcaption>
	
	<audio controls="" loading="lazy" src="https://shkspr.mobi/blog/wp-content/uploads/2023/12/mictest.mp3">
		<p>💾 <a href="https://shkspr.mobi/blog/wp-content/uploads/2023/12/mictest.mp3">Download this audio file</a>.</p>
	</audio>
</figure><p></p>

<p>No noticeable hiss. Captured my voice perfectly.  It picked up a little clack from my keyboard as I typed. Colleagues could hear me clearly - even if they were somewhat distracted by the pulsing LEDs. I don't play any instruments, so I'm not sure how well it would do with your acoustic rendition of Wonderwall.</p>

<h2 id="features"><a href="https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/#features">Features</a></h2>

<p>USB-C! This is the main reason I wanted to review this bit of kit. I've fully embraced the USB-C lifestyle. I have a single cable which does data and power for my phone, laptop, eReader, printer, electric screwdriver, battery pack - and now my microphone! I can be sure that wherever I go, I'll always have the right cable.</p>

<p>The RGB lights are... well, I think they're fun! If you're a <strong>serious business executive</strong> you might want to turn them off. But life's too short for boring conference calls, right?</p>

<p>The mute button on the top is handy. Of course, if you mute in hardware it doesn't necessarily show in software - so you'll look like you're unmuted on Teams.</p>

<p>The volume control on it works. I'm not quite sure why you'd ever want to fiddle with it, but it's there.</p>

<p>Finally, there's a monitor connection. This is also a clever addition. Plug a pair of analogue heaphones in there and you can hear your own voice - so you can check how loud it is. What's special is that <em>this microphone is also an output device!</em> You can hear your colleagues (or music) and get a latency-free monitor of your voice. Nice!</p>

<p>The base is sturdy and it comes with a few bits if you want to connect it to an existing microphone stand.</p>

<h2 id="linux"><a href="https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/#linux">Linux</a></h2>

<p>As normal for Linux, it was a plug and play experience. No weird drivers needed.</p>

<p>A quick <code>lsusb</code> shows it to be <code>3142:00a8 fifine Microphones fifine  Microphone</code>. My recording software showed it as either a digital (S/PDIF) or analogue stereo source.</p>

<p>It also acted as a USB audio output for the monitor connection. Stereo audio was delivered flawlessly.</p>

<h2 id="downsides"><a href="https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/#downsides">Downsides</a></h2>

<p>There isn't really worth complaining about here. Perhaps it might be nice if the RGB acted as a visualiser and reacted to your voice? The volume knob and colour changer are at the other side of the pop-shield, so you'll need to reach around to fiddle with them.</p>

<p>The mic mute at the top is handy, but you have to tap precisely on the LED. I'd have preferred to have the whole top as a sensor.</p>

<h2 id="verdict"><a href="https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/#verdict">Verdict</a></h2>

<p>For <a href="https://amzn.to/47vS8wt">about £50</a> (depending on whether the algorithm likes you) it's a decent bit of kit. Sound quality is excellent. And, yes, if you don't like shocking pink it also comes in boring black or white.</p>

<h2 id="discount"><a href="https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/#discount">Discount!</a></h2>

<p><a href="https://fifinemicrophone.com/products/fifine-ampligame-a8">Get 15% off when you order from the official website and use code <code>FIFINEMIC15</code>!</a></p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=48682&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/12/gadget-review-fifine-ampligame-a8-usb-c-gaming-microphone/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Hiding malicious commands in copy-and-pasted text]]></title>
		<link>https://shkspr.mobi/blog/2023/10/hiding-malicious-commands-copy-and-pasted-text/</link>
					<comments>https://shkspr.mobi/blog/2023/10/hiding-malicious-commands-copy-and-pasted-text/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 13 Oct 2023 11:34:24 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[CyberSecurity]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=47330</guid>

					<description><![CDATA[Quite often websites will encourage you to copy and paste commands into your terminal.  There are a variety of reasons why this is bad - not least because someone could hide malicious code. That&#039;s usually done with a bit of CSS to make the evil command invisible, or using Javascript to inject something unwanted into your keyboard.  Here&#039;s method that I hadn&#039;t seen before. Copy this code and paste …]]></description>
										<content:encoded><![CDATA[<p>Quite often websites will encourage you to copy and paste commands into your terminal.</p>

<p>There are a variety of reasons why this is bad - not least because someone could hide malicious code. That's usually done with a bit of CSS to make the evil command invisible, or using Javascript to inject something unwanted into your keyboard.</p>

<p>Here's method that I hadn't seen before. Copy this code and paste it into your terminal to see your external IP address:</p>

<p><input type="text" readonly="" value="curl ipconfig.io                   ;yes &quot;Don't copy and paste commands!&quot;" style="display: inline;width: fit-content;background: var(--color-box);border: none;padding: 0; font-family:monospace; border-radius: 0;outline: none;" size="17"></p>

<p>Notice anything weird about it? Depending on how you selected it, possibly not. Try pasting it into your terminal.</p>

<p>Let's take a look at how it works:</p>

<pre><code class="language-html">&amp;lt;input 
   type=&amp;quot;text&amp;quot;
   readonly=&amp;quot;&amp;quot;
   value=&amp;quot;curl ipconfig.io  ;yes &amp;amp;quot;Don&amp;#039;t copy and paste commands!&amp;amp;quot;&amp;quot;
   size=&amp;quot;17&amp;quot; 
   style=&amp;quot;display: inline; 
          width: fit-content; 
          background: var(--color-box); 
          border: none; 
          outline: none;
          padding: 0; 
          font-family:monospace; 
          border-radius: 0;&amp;quot;&amp;gt;
</code></pre>

<p>It's a readonly text input! The size has been set to cut off anything after the innocuous command. The CSS makes it look like part of the regular page with none of the styling associated with an input.</p>

<p>I'd hope that most people would realise that the command they pasted looked different from the one they thought had been copied - but we all make mistakes.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=47330&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/10/hiding-malicious-commands-copy-and-pasted-text/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
